summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk13
-rw-r--r--CleanSpec.mk9
-rw-r--r--cmds/bootanimation/Android.mk23
-rw-r--r--cmds/bootanimation/BootAnimation.cpp374
-rw-r--r--cmds/bootanimation/BootAnimation.h14
-rw-r--r--cmds/bootanimation/bootanimation_main.cpp3
-rw-r--r--cmds/content/src/com/android/commands/content/Content.java24
-rw-r--r--cmds/idmap/create.cpp44
-rw-r--r--cmds/idmap/idmap.cpp72
-rw-r--r--cmds/idmap/idmap.h5
-rw-r--r--cmds/idmap/inspect.cpp15
-rw-r--r--cmds/idmap/scan.cpp102
-rw-r--r--cmds/input/src/com/android/commands/input/Input.java1
-rw-r--r--cmds/media/src/com/android/commands/media/Media.java20
-rwxr-xr-xcmds/pm/pm1
-rw-r--r--cmds/screencap/screencap.cpp22
-rw-r--r--cmds/settings/Android.mk1
-rw-r--r--cmds/settings/src/com/android/commands/settings/SettingsCmd.java94
-rw-r--r--cmds/tm/Android.mk16
-rw-r--r--cmds/tm/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/tm/NOTICE190
-rw-r--r--cmds/tm/src/com/android/commands/tm/Tm.java204
-rwxr-xr-xcmds/tm/tm6
-rw-r--r--core/java/android/accounts/AccountManager.java26
-rw-r--r--core/java/android/app/ActivityManager.java37
-rw-r--r--core/java/android/app/ActivityManagerNative.java28
-rw-r--r--core/java/android/app/ActivityThread.java59
-rw-r--r--core/java/android/app/AlarmManager.java8
-rw-r--r--core/java/android/app/AppOpsManager.java370
-rw-r--r--core/java/android/app/ApplicationPackageManager.java93
-rw-r--r--core/java/android/app/ComposedIconInfo.aidl19
-rw-r--r--core/java/android/app/ComposedIconInfo.java149
-rw-r--r--core/java/android/app/ContextImpl.java72
-rw-r--r--core/java/android/app/DownloadManager.java40
-rw-r--r--core/java/android/app/IActivityManager.java8
-rw-r--r--core/java/android/app/IAlarmManager.aidl2
-rw-r--r--core/java/android/app/IBatteryService.aidl26
-rw-r--r--core/java/android/app/IWallpaperManager.aidl19
-rw-r--r--core/java/android/app/IWallpaperManagerCallback.aidl5
-rw-r--r--core/java/android/app/IconPackHelper.java1062
-rw-r--r--core/java/android/app/Instrumentation.java7
-rw-r--r--core/java/android/app/LoadedApk.java5
-rw-r--r--core/java/android/app/Notification.java7
-rw-r--r--core/java/android/app/NotificationGroup.aidl19
-rw-r--r--core/java/android/app/NotificationGroup.java201
-rw-r--r--core/java/android/app/ResourcesManager.java469
-rw-r--r--core/java/android/app/StatusBarManager.java1
-rw-r--r--core/java/android/app/SystemServiceRegistry.java4
-rw-r--r--core/java/android/app/WallpaperManager.java202
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java20
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--core/java/android/app/backup/FullBackup.java15
-rwxr-xr-x[-rw-r--r--]core/java/android/bluetooth/BluetoothA2dpSink.java83
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java144
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcpController.java87
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcpInfo.aidl34
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcpInfo.java306
-rwxr-xr-x[-rw-r--r--]core/java/android/bluetooth/BluetoothClass.java17
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java21
-rw-r--r--core/java/android/bluetooth/BluetoothDevicePicker.java8
-rw-r--r--core/java/android/bluetooth/BluetoothDun.java296
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java116
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClient.java19
-rw-r--r--core/java/android/bluetooth/BluetoothHidDevice.java502
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl21
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java72
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl21
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java99
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl21
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java82
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceCallback.java128
-rw-r--r--core/java/android/bluetooth/BluetoothInputDevice.java61
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java12
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java56
-rw-r--r--core/java/android/bluetooth/IBluetooth.aidl8
-rwxr-xr-x[-rw-r--r--]core/java/android/bluetooth/IBluetoothA2dpSink.aidl3
-rw-r--r--core/java/android/bluetooth/IBluetoothAvrcpController.aidl8
-rw-r--r--core/java/android/bluetooth/IBluetoothDun.aidl45
-rw-r--r--core/java/android/bluetooth/IBluetoothHidDevice.aidl39
-rw-r--r--core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl33
-rw-r--r--core/java/android/bluetooth/IBluetoothInputDevice.aidl8
-rw-r--r--core/java/android/bluetooth/IBluetoothManager.aidl6
-rw-r--r--core/java/android/content/BroadcastReceiver.java12
-rw-r--r--core/java/android/content/ContentResolver.java5
-rw-r--r--core/java/android/content/Context.java23
-rw-r--r--core/java/android/content/ContextWrapper.java21
-rw-r--r--core/java/android/content/Intent.java118
-rw-r--r--core/java/android/content/ThemeVersion.java75
-rw-r--r--core/java/android/content/pm/ActivityInfo.java13
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java20
-rw-r--r--core/java/android/content/pm/BaseThemeInfo.java111
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl14
-rw-r--r--core/java/android/content/pm/PackageInfo.java48
-rw-r--r--core/java/android/content/pm/PackageInfoLite.java3
-rw-r--r--core/java/android/content/pm/PackageItemInfo.java14
-rw-r--r--core/java/android/content/pm/PackageManager.java102
-rw-r--r--core/java/android/content/pm/PackageParser.java242
-rw-r--r--core/java/android/content/pm/PackageUserState.java6
-rw-r--r--core/java/android/content/pm/PermissionInfo.java11
-rw-r--r--core/java/android/content/pm/ThemeInfo.aidl3
-rw-r--r--core/java/android/content/pm/ThemeInfo.java65
-rw-r--r--core/java/android/content/pm/ThemeUtils.java154
-rw-r--r--core/java/android/content/res/AssetManager.java227
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java3
-rw-r--r--core/java/android/content/res/Configuration.java94
-rw-r--r--core/java/android/content/res/Resources.java176
-rw-r--r--core/java/android/content/res/ResourcesKey.java19
-rw-r--r--core/java/android/content/res/ThemeConfig.java579
-rw-r--r--core/java/android/database/sqlite/SQLiteConnection.java2
-rw-r--r--core/java/android/hardware/Camera.java1541
-rw-r--r--core/java/android/hardware/SystemSensorManager.java2
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestThreadManager.java3
-rw-r--r--core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java14
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java34
-rw-r--r--core/java/android/net/ConnectivityManager.java25
-rw-r--r--core/java/android/net/IConnectivityManager.aidl5
-rw-r--r--core/java/android/net/INetworkManagementEventObserver.aidl7
-rw-r--r--core/java/android/net/LinkProperties.java45
-rw-r--r--core/java/android/net/wimax/WimaxHelper.java188
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java20
-rw-r--r--core/java/android/os/BatteryManager.java160
-rw-r--r--core/java/android/os/BatteryManagerInternal.java21
-rw-r--r--core/java/android/os/BatteryProperties.java54
-rw-r--r--core/java/android/os/Environment.java11
-rw-r--r--core/java/android/os/IBatteryPropertiesRegistrar.aidl2
-rw-r--r--core/java/android/os/IDeviceIdleController.aidl1
-rw-r--r--core/java/android/os/IPowerManager.aidl10
-rw-r--r--core/java/android/os/PowerManager.java82
-rw-r--r--core/java/android/os/PowerManagerInternal.java7
-rw-r--r--core/java/android/os/Process.java7
-rw-r--r--core/java/android/os/RecoverySystem.java43
-rw-r--r--core/java/android/os/StrictMode.java4
-rw-r--r--core/java/android/os/UserManager.java14
-rw-r--r--core/java/android/os/storage/DiskInfo.java6
-rw-r--r--core/java/android/os/storage/IMountService.java39
-rw-r--r--core/java/android/os/storage/StorageVolume.java13
-rw-r--r--core/java/android/preference/DialogPreference.java29
-rwxr-xr-x[-rw-r--r--]core/java/android/preference/MultiSelectListPreference.java17
-rw-r--r--core/java/android/preference/Preference.java10
-rw-r--r--core/java/android/preference/PreferenceFragment.java3
-rw-r--r--core/java/android/preference/PreferenceGroup.java9
-rw-r--r--core/java/android/preference/RingtonePreference.java58
-rw-r--r--core/java/android/preference/SeekBarVolumizer.java19
-rw-r--r--core/java/android/provider/Browser.java6
-rw-r--r--core/java/android/provider/CalendarContract.java8
-rw-r--r--core/java/android/provider/CallLog.java4
-rw-r--r--core/java/android/provider/ContactsContract.java17
-rw-r--r--core/java/android/provider/Downloads.java5
-rw-r--r--core/java/android/provider/Settings.java505
-rw-r--r--core/java/android/service/dreams/DreamManagerInternal.java5
-rw-r--r--core/java/android/service/dreams/IDreamManager.aidl3
-rw-r--r--core/java/android/service/gesture/IGestureService.aidl11
-rw-r--r--core/java/android/speech/SpeechRecognizer.java1
-rw-r--r--core/java/android/text/TextUtils.java12
-rwxr-xr-xcore/java/android/text/format/DateFormat.java29
-rw-r--r--core/java/android/text/method/MetaKeyKeyListener.java31
-rw-r--r--core/java/android/util/DisplayMetrics.java43
-rw-r--r--core/java/android/util/Patterns.java40
-rw-r--r--core/java/android/util/SeempLog.java758
-rw-r--r--core/java/android/view/Display.java3
-rw-r--r--core/java/android/view/DisplayInfo.java3
-rw-r--r--core/java/android/view/IWindowManager.aidl18
-rw-r--r--core/java/android/view/IWindowSession.aidl10
-rw-r--r--core/java/android/view/InputDevice.java13
-rw-r--r--core/java/android/view/KeyEvent.java6
-rw-r--r--core/java/android/view/SurfaceControl.java39
-rw-r--r--core/java/android/view/ThreadedRenderer.java5
-rw-r--r--core/java/android/view/View.java9
-rw-r--r--core/java/android/view/ViewConfiguration.java2
-rw-r--r--core/java/android/view/Window.java35
-rw-r--r--core/java/android/view/WindowManager.java79
-rw-r--r--core/java/android/view/WindowManagerImpl.java2
-rw-r--r--core/java/android/view/WindowManagerPolicy.java11
-rw-r--r--core/java/android/view/WindowManagerPolicyControl.java451
-rw-r--r--core/java/android/webkit/WebChromeClient.java4
-rw-r--r--core/java/android/webkit/WebViewFactory.java17
-rw-r--r--core/java/android/widget/AbsSeekBar.java9
-rw-r--r--core/java/android/widget/FastScroller.java1
-rw-r--r--core/java/android/widget/RemoteViews.java15
-rw-r--r--core/java/android/widget/TextClock.java1
-rw-r--r--core/java/android/widget/Toast.java14
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl8
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl15
-rw-r--r--core/java/com/android/internal/app/LocalePicker.java21
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java9
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java16
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java89
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java29
-rw-r--r--core/java/com/android/internal/os/DeviceKeyHandler.java26
-rw-r--r--core/java/com/android/internal/os/DockBatteryStatsImpl.java56
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java5
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java10
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java260
-rw-r--r--core/java/com/android/internal/util/cm/ActionUtils.java149
-rw-r--r--core/java/com/android/internal/util/cm/PowerMenuConstants.java50
-rw-r--r--core/java/com/android/internal/util/cm/SpamFilter.java65
-rw-r--r--core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java516
-rw-r--r--core/java/com/android/internal/util/cm/palette/ColorUtils.java299
-rw-r--r--core/java/com/android/internal/util/cm/palette/DefaultGenerator.java244
-rw-r--r--core/java/com/android/internal/util/cm/palette/Palette.java740
-rw-r--r--core/java/com/android/internal/view/RotationPolicy.java46
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl2
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java88
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java236
-rw-r--r--core/java/com/android/server/net/BaseNetworkObserver.java5
-rw-r--r--core/java/org/codeaurora/camera/Android.mk30
-rw-r--r--core/java/org/codeaurora/camera/ExtendedFace.java211
-rw-r--r--core/java/org/codeaurora/camera/org.codeaurora.camera.xml35
-rw-r--r--core/jni/Android.mk5
-rw-r--r--core/jni/AndroidRuntime.cpp12
-rw-r--r--core/jni/android/opengl/util.cpp4
-rw-r--r--core/jni/android_hardware_Camera.cpp183
-rw-r--r--core/jni/android_media_AudioFormat.h32
-rw-r--r--core/jni/android_media_AudioSystem.cpp35
-rw-r--r--core/jni/android_opengl_GLES20.cpp148
-rw-r--r--core/jni/android_util_AssetManager.cpp191
-rw-r--r--core/jni/android_util_Binder.cpp2
-rw-r--r--core/jni/android_util_Process.cpp37
-rw-r--r--core/jni/android_util_SeempLog.cpp210
-rw-r--r--core/jni/android_view_DisplayListCanvas.cpp6
-rw-r--r--core/jni/android_view_SurfaceControl.cpp41
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp6
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp65
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp4
-rw-r--r--core/res/AndroidManifest.xml134
-rw-r--r--core/res/res/anim/last_app_in.xml41
-rw-r--r--core/res/res/anim/last_app_out.xml41
-rw-r--r--core/res/res/anim/lock_screen_wallpaper_exit_noop.xml32
-rw-r--r--core/res/res/color/preference_category_text_color.xml20
-rw-r--r--core/res/res/drawable-hdpi/ic_launcher_android.pngbin6870 -> 3418 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.pngbin0 -> 1645 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_security.pngbin0 -> 1554 bytes
-rw-r--r--core/res/res/drawable-hdpi/stat_sys_upload_anim1.pngbin681 -> 634 bytes
-rw-r--r--core/res/res/drawable-hdpi/stat_sys_upload_anim2.pngbin634 -> 681 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_launcher_android.pngbin3779 -> 2206 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.pngbin0 -> 3374 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_security.pngbin0 -> 1277 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_upload_anim1.pngbin577 -> 545 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_upload_anim2.pngbin545 -> 577 bytes
-rw-r--r--core/res/res/drawable-nodpi/platlogo_cm.xml55
-rw-r--r--core/res/res/drawable-nodpi/stat_sys_adb.xml41
-rw-r--r--core/res/res/drawable-xhdpi/ic_launcher_android.pngbin11082 -> 4842 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.pngbin0 -> 1558 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_security.pngbin0 -> 1633 bytes
-rw-r--r--core/res/res/drawable-xhdpi/stat_sys_upload_anim1.pngbin814 -> 759 bytes
-rw-r--r--core/res/res/drawable-xhdpi/stat_sys_upload_anim2.pngbin759 -> 814 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_launcher_android.pngbin0 -> 7718 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.pngbin0 -> 17728 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_security.pngbin0 -> 1761 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/stat_sys_upload_anim1.pngbin641 -> 624 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/stat_sys_upload_anim2.pngbin624 -> 641 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/ic_launcher_android.pngbin0 -> 10486 bytes
-rw-r--r--core/res/res/drawable/ic_lock_dnd_priority.xml27
-rw-r--r--core/res/res/drawable/ic_lock_dnd_total_silence.xml31
-rw-r--r--core/res/res/drawable/ic_lock_lock.xml2
-rw-r--r--core/res/res/drawable/ic_lock_power_reboot.xml33
-rw-r--r--core/res/res/drawable/ic_lock_ring.xml27
-rw-r--r--core/res/res/drawable/ic_lock_screenshot.xml27
-rw-r--r--core/res/res/drawable/ic_lock_settings.xml27
-rw-r--r--core/res/res/drawable/ic_lock_user.xml27
-rw-r--r--core/res/res/drawable/ic_lock_vibrate.xml27
-rw-r--r--core/res/res/drawable/progress_large.xml4
-rw-r--r--core/res/res/drawable/progress_large_white.xml4
-rw-r--r--core/res/res/drawable/progress_medium.xml4
-rw-r--r--core/res/res/drawable/progress_medium_white.xml4
-rw-r--r--core/res/res/drawable/progress_small.xml4
-rw-r--r--core/res/res/drawable/progress_small_titlebar.xml4
-rw-r--r--core/res/res/drawable/progress_small_white.xml4
-rw-r--r--core/res/res/drawable/search_spinner.xml4
-rw-r--r--core/res/res/drawable/stat_notify_privacy_guard.xml11
-rw-r--r--core/res/res/drawable/stat_notify_protected.xml28
-rw-r--r--core/res/res/layout-xlarge/activity_list.xml2
-rw-r--r--core/res/res/layout/alert_dialog_holo.xml4
-rw-r--r--core/res/res/layout/app_permission_item.xml2
-rw-r--r--core/res/res/layout/app_permission_item_money.xml2
-rw-r--r--core/res/res/layout/character_picker_button.xml2
-rw-r--r--core/res/res/layout/chooser_grid.xml6
-rw-r--r--core/res/res/layout/dialog_custom_title_holo.xml2
-rw-r--r--core/res/res/layout/dialog_title_holo.xml2
-rw-r--r--core/res/res/layout/dialog_title_icons_holo.xml2
-rw-r--r--core/res/res/layout/global_actions_silent_mode.xml42
-rw-r--r--core/res/res/layout/immersive_mode_cling.xml10
-rw-r--r--core/res/res/layout/media_controller.xml2
-rw-r--r--core/res/res/layout/notification_material_action.xml2
-rw-r--r--core/res/res/layout/notification_material_action_tombstone.xml2
-rw-r--r--core/res/res/layout/notification_template_material_big_picture.xml2
-rw-r--r--core/res/res/layout/permission_confirmation_dialog.xml67
-rw-r--r--core/res/res/layout/preference_category_material.xml2
-rw-r--r--core/res/res/layout/preference_list_fragment.xml1
-rw-r--r--core/res/res/layout/remote_views_adapter_default_loading_view.xml4
-rw-r--r--core/res/res/layout/resolver_different_item_header.xml3
-rw-r--r--core/res/res/layout/resolver_list.xml7
-rw-r--r--core/res/res/layout/resolver_list_with_default.xml15
-rw-r--r--core/res/res/layout/status_bar_latest_event_content.xml2
-rw-r--r--core/res/res/layout/text_edit_action_popup_text.xml2
-rw-r--r--core/res/res/layout/text_edit_paste_window.xml2
-rw-r--r--core/res/res/layout/text_edit_side_paste_window.xml2
-rw-r--r--core/res/res/layout/transient_notification.xml19
-rw-r--r--core/res/res/layout/typing_filter.xml4
-rw-r--r--core/res/res/layout/web_text_view_dropdown.xml4
-rw-r--r--core/res/res/values-af/cm_strings.xml150
-rw-r--r--core/res/res/values-ar/cm_strings.xml129
-rw-r--r--core/res/res/values-ast-rES/cm_strings.xml128
-rw-r--r--core/res/res/values-ast-rES/donottranslate-maps.xml26
-rw-r--r--core/res/res/values-ast-rES/strings.xml1261
-rw-r--r--core/res/res/values-az-rAZ/cm_strings.xml129
-rw-r--r--core/res/res/values-be/cm_strings.xml147
-rw-r--r--core/res/res/values-be/strings.xml142
-rw-r--r--core/res/res/values-bg/cm_strings.xml150
-rw-r--r--core/res/res/values-bn-rBD/cm_strings.xml97
-rw-r--r--core/res/res/values-ca/cm_strings.xml150
-rw-r--r--core/res/res/values-cs/cm_strings.xml150
-rw-r--r--core/res/res/values-da/cm_strings.xml134
-rw-r--r--core/res/res/values-de/cm_strings.xml150
-rw-r--r--core/res/res/values-el/cm_strings.xml150
-rw-r--r--core/res/res/values-en-rAU/cm_strings.xml120
-rw-r--r--core/res/res/values-en-rIN/cm_strings.xml145
-rw-r--r--core/res/res/values-eo/cm_strings.xml125
-rw-r--r--core/res/res/values-eo/strings.xml224
-rw-r--r--core/res/res/values-es/cm_strings.xml145
-rw-r--r--core/res/res/values-et-rEE/cm_strings.xml129
-rw-r--r--core/res/res/values-eu-rES/cm_strings.xml150
-rw-r--r--core/res/res/values-fa/cm_strings.xml129
-rw-r--r--core/res/res/values-fi/cm_strings.xml150
-rw-r--r--core/res/res/values-fr/cm_strings.xml146
-rw-r--r--core/res/res/values-gl-rES/cm_strings.xml134
-rw-r--r--core/res/res/values-hi/cm_strings.xml127
-rw-r--r--core/res/res/values-hr/cm_strings.xml150
-rw-r--r--core/res/res/values-hu/cm_strings.xml150
-rw-r--r--core/res/res/values-in/cm_strings.xml127
-rw-r--r--core/res/res/values-it/cm_strings.xml150
-rw-r--r--core/res/res/values-iw/cm_strings.xml150
-rw-r--r--core/res/res/values-ja/cm_strings.xml150
-rw-r--r--core/res/res/values-kn-rIN/cm_strings.xml129
-rw-r--r--core/res/res/values-ko/cm_strings.xml150
-rw-r--r--core/res/res/values-ku-rIQ/donottranslate-maps.xml26
-rw-r--r--core/res/res/values-ku/cm_strings.xml116
-rw-r--r--core/res/res/values-ku/strings.xml1322
-rw-r--r--core/res/res/values-lb-rLU/donottranslate-maps.xml26
-rw-r--r--core/res/res/values-lb/cm_strings.xml130
-rw-r--r--core/res/res/values-lb/strings.xml1326
-rw-r--r--core/res/res/values-lt/cm_strings.xml129
-rw-r--r--core/res/res/values-lv/cm_strings.xml105
-rw-r--r--core/res/res/values-mcc204-mnc02/config.xml25
-rw-r--r--core/res/res/values-mcc214-mnc07/config.xml28
-rw-r--r--core/res/res/values-mcc214-mnc32/config.xml25
-rw-r--r--core/res/res/values-mcc219-mnc02/config.xml3
-rw-r--r--core/res/res/values-mcc222-mnc07/config.xml25
-rw-r--r--core/res/res/values-mcc232-mnc03/config.xml25
-rw-r--r--core/res/res/values-mcc232-mnc05/config.xml25
-rw-r--r--core/res/res/values-mcc232-mnc10/config.xml25
-rw-r--r--core/res/res/values-mcc232-mnc11/config.xml25
-rw-r--r--core/res/res/values-mcc232-mnc12/config.xml26
-rw-r--r--core/res/res/values-mcc234-mnc01/config.xml25
-rw-r--r--core/res/res/values-mcc240-mnc10/config.xml26
-rw-r--r--core/res/res/values-mcc244-mnc21/config.xml25
-rw-r--r--core/res/res/values-mcc260-mnc06/config.xml27
-rw-r--r--core/res/res/values-mcc268-mnc04/config.xml25
-rw-r--r--core/res/res/values-mcc268-mnc07/config.xml25
-rw-r--r--core/res/res/values-mcc272-mnc05/config.xml25
-rw-r--r--core/res/res/values-mcc272-mnc11/config.xml25
-rwxr-xr-xcore/res/res/values-mcc310-mnc004/config.xml7
-rw-r--r--core/res/res/values-mcc310-mnc008/config.xml33
-rw-r--r--core/res/res/values-mcc310-mnc009/config.xml33
-rwxr-xr-xcore/res/res/values-mcc311-mnc480/config.xml6
-rw-r--r--core/res/res/values-mcc404-mnc55/config.xml25
-rw-r--r--core/res/res/values-nb/cm_strings.xml147
-rw-r--r--core/res/res/values-nl/cm_strings.xml150
-rw-r--r--core/res/res/values-pl/cm_strings.xml150
-rw-r--r--core/res/res/values-pt-rBR/cm_strings.xml150
-rw-r--r--core/res/res/values-pt-rPT/cm_strings.xml150
-rw-r--r--core/res/res/values-ro/cm_strings.xml148
-rw-r--r--core/res/res/values-ru/cm_strings.xml150
-rw-r--r--core/res/res/values-si-rLK/cm_strings.xml87
-rw-r--r--core/res/res/values-sk/cm_strings.xml129
-rw-r--r--core/res/res/values-sl/cm_strings.xml150
-rw-r--r--core/res/res/values-sr/cm_strings.xml150
-rw-r--r--core/res/res/values-sv/cm_strings.xml150
-rw-r--r--core/res/res/values-ta-rIN/cm_strings.xml70
-rw-r--r--core/res/res/values-th/cm_strings.xml147
-rw-r--r--core/res/res/values-tr/cm_strings.xml145
-rw-r--r--core/res/res/values-ug/cm_strings.xml120
-rw-r--r--core/res/res/values-ug/strings.xml1147
-rw-r--r--core/res/res/values-uk/cm_strings.xml150
-rw-r--r--core/res/res/values-vi/cm_strings.xml129
-rw-r--r--core/res/res/values-zh-rCN/cm_strings.xml150
-rw-r--r--core/res/res/values-zh-rHK/cm_strings.xml108
-rw-r--r--core/res/res/values-zh-rTW/cm_strings.xml145
-rw-r--r--core/res/res/values/attrs.xml3
-rw-r--r--core/res/res/values/attrs_manifest.xml5
-rw-r--r--core/res/res/values/bools.xml4
-rw-r--r--core/res/res/values/cm_arrays.xml220
-rw-r--r--core/res/res/values/cm_colors.xml27
-rw-r--r--core/res/res/values/cm_integers.xml22
-rw-r--r--core/res/res/values/cm_strings.xml235
-rw-r--r--core/res/res/values/cm_symbols.xml157
-rw-r--r--core/res/res/values/config.xml215
-rw-r--r--core/res/res/values/customize.xml40
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/strings.xml8
-rw-r--r--core/res/res/values/symbols.xml74
-rw-r--r--core/res/res/xml/default_zen_mode_config.xml2
-rw-r--r--core/res/res/xml/sms_short_codes.xml3
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageManagerTests.java23
-rw-r--r--data/sounds/AllAudio.mk170
-rw-r--r--data/sounds/AudioPackage10.mk1
-rw-r--r--data/sounds/AudioPackage11.mk1
-rw-r--r--data/sounds/AudioPackage2.mk5
-rw-r--r--data/sounds/AudioPackage3.mk5
-rw-r--r--data/sounds/AudioPackage4.mk6
-rw-r--r--data/sounds/AudioPackage5.mk2
-rw-r--r--data/sounds/AudioPackage6.mk2
-rw-r--r--data/sounds/AudioPackage7.mk8
-rw-r--r--data/sounds/AudioPackage7alt.mk2
-rw-r--r--data/sounds/AudioPackage8.mk9
-rw-r--r--data/sounds/AudioPackage9.mk1
-rw-r--r--data/sounds/F1_MissedCall.oggbin11950 -> 0 bytes
-rw-r--r--data/sounds/F1_New_MMS.oggbin20983 -> 0 bytes
-rw-r--r--data/sounds/OriginalAudio.mk5
-rw-r--r--data/sounds/Ring_Digital_02.oggbin21007 -> 23084 bytes
-rw-r--r--data/sounds/alarms/ogg/Cesium.oggbin27025 -> 0 bytes
-rw-r--r--data/sounds/alarms/ogg/Fermium.oggbin117227 -> 0 bytes
-rw-r--r--data/sounds/alarms/ogg/Hassium.oggbin147068 -> 0 bytes
-rw-r--r--data/sounds/alarms/ogg/Neptunium.oggbin97614 -> 0 bytes
-rw-r--r--data/sounds/alarms/ogg/Nobelium.oggbin176792 -> 0 bytes
-rw-r--r--data/sounds/alarms/ogg/Plutonium.oggbin103252 -> 0 bytes
-rw-r--r--data/sounds/alarms/ogg/Promethium.oggbin112676 -> 0 bytes
-rw-r--r--data/sounds/effects/boosted/Roachpowder_camera-shutter.aiffbin0 -> 26734 bytes
-rw-r--r--data/sounds/newwavelabs/Ding.oggbin15476 -> 0 bytes
-rw-r--r--data/sounds/newwavelabs/MildlyAlarming.oggbin34864 -> 0 bytes
-rw-r--r--data/sounds/newwavelabs/Noises1.oggbin36287 -> 0 bytes
-rw-r--r--data/sounds/notifications/SpaceSeed.oggbin26180 -> 0 bytes
-rw-r--r--data/sounds/notifications/Tinkerbell.oggbin18858 -> 0 bytes
-rw-r--r--data/sounds/notifications/arcturus.oggbin7908 -> 0 bytes
-rw-r--r--data/sounds/notifications/ogg/Lalande.oggbin18138 -> 0 bytes
-rw-r--r--data/sounds/notifications/ogg/Tejat.oggbin15866 -> 0 bytes
-rw-r--r--data/sounds/notifications/ogg/Tejat_proc48.oggbin16804 -> 0 bytes
-rw-r--r--data/sounds/notifications/vega.oggbin29476 -> 0 bytes
-rw-r--r--data/sounds/ringtones/boosted/Andromeda.oggbin0 -> 32226 bytes
-rw-r--r--data/sounds/ringtones/boosted/Aquila.oggbin0 -> 27984 bytes
-rw-r--r--data/sounds/ringtones/boosted/ArgoNavis.oggbin0 -> 110271 bytes
-rw-r--r--data/sounds/ringtones/boosted/Atria.oggbin0 -> 114813 bytes
-rw-r--r--data/sounds/ringtones/boosted/BOOTES.oggbin0 -> 27490 bytes
-rw-r--r--data/sounds/ringtones/boosted/Backroad.oggbin0 -> 42934 bytes
-rw-r--r--data/sounds/ringtones/boosted/BeatPlucker.oggbin0 -> 42453 bytes
-rw-r--r--data/sounds/ringtones/boosted/BentleyDubs.oggbin0 -> 41734 bytes
-rw-r--r--data/sounds/ringtones/boosted/Big_Easy.oggbin0 -> 51996 bytes
-rw-r--r--data/sounds/ringtones/boosted/BirdLoop.oggbin0 -> 64319 bytes
-rw-r--r--data/sounds/ringtones/boosted/Bollywood.oggbin0 -> 48634 bytes
-rw-r--r--data/sounds/ringtones/boosted/BussaMove.oggbin0 -> 56058 bytes
-rw-r--r--data/sounds/ringtones/boosted/CASSIOPEIA.oggbin0 -> 39017 bytes
-rw-r--r--data/sounds/ringtones/boosted/Cairo.oggbin0 -> 40518 bytes
-rw-r--r--data/sounds/ringtones/boosted/Callisto.oggbin0 -> 199132 bytes
-rw-r--r--data/sounds/ringtones/boosted/Calypso_Steel.oggbin0 -> 43574 bytes
-rw-r--r--data/sounds/ringtones/boosted/CanisMajor.oggbin0 -> 29708 bytes
-rw-r--r--data/sounds/ringtones/boosted/CaribbeanIce.oggbin0 -> 45530 bytes
-rw-r--r--data/sounds/ringtones/boosted/Carina.oggbin0 -> 16831 bytes
-rw-r--r--data/sounds/ringtones/boosted/Centaurus.oggbin0 -> 35438 bytes
-rw-r--r--data/sounds/ringtones/boosted/Champagne_Edition.oggbin0 -> 44115 bytes
-rw-r--r--data/sounds/ringtones/boosted/Club_Cubano.oggbin0 -> 43424 bytes
-rw-r--r--data/sounds/ringtones/boosted/CrayonRock.oggbin0 -> 47044 bytes
-rw-r--r--data/sounds/ringtones/boosted/CrazyDream.oggbin0 -> 330530 bytes
-rw-r--r--data/sounds/ringtones/boosted/CurveBall.oggbin0 -> 46713 bytes
-rw-r--r--data/sounds/ringtones/boosted/Cygnus.oggbin0 -> 34853 bytes
-rw-r--r--data/sounds/ringtones/boosted/DancinFool.oggbin0 -> 66666 bytes
-rw-r--r--data/sounds/ringtones/boosted/Dione.oggbin0 -> 176464 bytes
-rw-r--r--data/sounds/ringtones/boosted/DonMessWivIt.oggbin0 -> 59273 bytes
-rw-r--r--data/sounds/ringtones/boosted/Draco.oggbin0 -> 39586 bytes
-rw-r--r--data/sounds/ringtones/boosted/DreamTheme.oggbin0 -> 240708 bytes
-rw-r--r--data/sounds/ringtones/boosted/Eastern_Sky.oggbin0 -> 61338 bytes
-rw-r--r--data/sounds/ringtones/boosted/Enter_the_Nexus.oggbin0 -> 72388 bytes
-rw-r--r--data/sounds/ringtones/boosted/Eridani.oggbin0 -> 40739 bytes
-rw-r--r--data/sounds/ringtones/boosted/EtherShake.oggbin0 -> 45162 bytes
-rw-r--r--data/sounds/ringtones/boosted/FreeFlight.oggbin0 -> 115787 bytes
-rw-r--r--data/sounds/ringtones/boosted/FriendlyGhost.oggbin0 -> 56574 bytes
-rw-r--r--data/sounds/ringtones/boosted/Funk_Yall.oggbin0 -> 49568 bytes
-rw-r--r--data/sounds/ringtones/boosted/GameOverGuitar.oggbin0 -> 58236 bytes
-rw-r--r--data/sounds/ringtones/boosted/Ganymede.oggbin0 -> 72422 bytes
-rw-r--r--data/sounds/ringtones/boosted/Gimme_Mo_Town.oggbin0 -> 47052 bytes
-rw-r--r--data/sounds/ringtones/boosted/Girtab.oggbin0 -> 45473 bytes
-rw-r--r--data/sounds/ringtones/boosted/Glacial_Groove.oggbin0 -> 54179 bytes
-rw-r--r--data/sounds/ringtones/boosted/Growl.oggbin0 -> 66830 bytes
-rw-r--r--data/sounds/ringtones/boosted/HalfwayHome.oggbin0 -> 76373 bytes
-rw-r--r--data/sounds/ringtones/boosted/Hydra.oggbin0 -> 30862 bytes
-rw-r--r--data/sounds/ringtones/boosted/InsertCoin.oggbin0 -> 23013 bytes
-rw-r--r--data/sounds/ringtones/boosted/Kuma.oggbin0 -> 177560 bytes
-rw-r--r--data/sounds/ringtones/boosted/LoopyLounge.oggbin0 -> 52891 bytes
-rw-r--r--data/sounds/ringtones/boosted/LoveFlute.oggbin0 -> 49109 bytes
-rw-r--r--data/sounds/ringtones/boosted/Luna.oggbin0 -> 58928 bytes
-rw-r--r--data/sounds/ringtones/boosted/Lyra.oggbin0 -> 54307 bytes
-rw-r--r--data/sounds/ringtones/boosted/Machina.oggbin0 -> 44844 bytes
-rw-r--r--data/sounds/ringtones/boosted/MidEvilJaunt.oggbin0 -> 44691 bytes
-rw-r--r--data/sounds/ringtones/boosted/Nairobi.oggbin0 -> 44799 bytes
-rw-r--r--data/sounds/ringtones/boosted/Nassau.oggbin0 -> 51368 bytes
-rw-r--r--data/sounds/ringtones/boosted/NewPlayer.oggbin0 -> 21735 bytes
-rw-r--r--data/sounds/ringtones/boosted/No_Limits.oggbin0 -> 41815 bytes
-rw-r--r--data/sounds/ringtones/boosted/Noises2.oggbin0 -> 47466 bytes
-rw-r--r--data/sounds/ringtones/boosted/Noises3.oggbin0 -> 34872 bytes
-rw-r--r--data/sounds/ringtones/boosted/Oberon.oggbin0 -> 225583 bytes
-rw-r--r--data/sounds/ringtones/boosted/OrganDub.oggbin0 -> 43489 bytes
-rw-r--r--data/sounds/ringtones/boosted/Orion.oggbin0 -> 59789 bytes
-rw-r--r--data/sounds/ringtones/boosted/Paradise_Island.oggbin0 -> 44273 bytes
-rw-r--r--data/sounds/ringtones/boosted/Pegasus.oggbin0 -> 105036 bytes
-rw-r--r--data/sounds/ringtones/boosted/Perseus.oggbin0 -> 134971 bytes
-rw-r--r--data/sounds/ringtones/boosted/Phobos.oggbin0 -> 60295 bytes
-rw-r--r--data/sounds/ringtones/boosted/Playa.oggbin0 -> 63529 bytes
-rw-r--r--data/sounds/ringtones/boosted/Pyxis.oggbin0 -> 312897 bytes
-rw-r--r--data/sounds/ringtones/boosted/Rasalas.oggbin0 -> 188609 bytes
-rw-r--r--data/sounds/ringtones/boosted/Revelation.oggbin0 -> 57781 bytes
-rw-r--r--data/sounds/ringtones/boosted/Rigel.oggbin0 -> 35914 bytes
-rw-r--r--data/sounds/ringtones/boosted/Ring_Classic_02.oggbin0 -> 58622 bytes
-rw-r--r--data/sounds/ringtones/boosted/Ring_Digital_02.oggbin0 -> 22135 bytes
-rw-r--r--data/sounds/ringtones/boosted/Ring_Synth_02.oggbin0 -> 56839 bytes
-rw-r--r--data/sounds/ringtones/boosted/Ring_Synth_04.oggbin0 -> 47616 bytes
-rw-r--r--data/sounds/ringtones/boosted/Road_Trip.oggbin0 -> 68361 bytes
-rw-r--r--data/sounds/ringtones/boosted/RomancingTheTone.oggbin0 -> 50717 bytes
-rw-r--r--data/sounds/ringtones/boosted/Safari.oggbin0 -> 44597 bytes
-rw-r--r--data/sounds/ringtones/boosted/Savannah.oggbin0 -> 46778 bytes
-rw-r--r--data/sounds/ringtones/boosted/Scarabaeus.oggbin0 -> 117105 bytes
-rw-r--r--data/sounds/ringtones/boosted/Sceptrum.oggbin0 -> 345388 bytes
-rw-r--r--data/sounds/ringtones/boosted/Sedna.oggbin0 -> 101878 bytes
-rw-r--r--data/sounds/ringtones/boosted/Seville.oggbin0 -> 51230 bytes
-rw-r--r--data/sounds/ringtones/boosted/Shes_All_That.oggbin0 -> 44712 bytes
-rw-r--r--data/sounds/ringtones/boosted/SilkyWay.oggbin0 -> 44214 bytes
-rw-r--r--data/sounds/ringtones/boosted/SitarVsSitar.oggbin0 -> 42256 bytes
-rw-r--r--data/sounds/ringtones/boosted/Solarium.oggbin0 -> 105357 bytes
-rw-r--r--data/sounds/ringtones/boosted/SpringyJalopy.oggbin0 -> 43939 bytes
-rw-r--r--data/sounds/ringtones/boosted/Steppin_Out.oggbin0 -> 45934 bytes
-rw-r--r--data/sounds/ringtones/boosted/Terminated.oggbin0 -> 54774 bytes
-rw-r--r--data/sounds/ringtones/boosted/Testudo.oggbin0 -> 92599 bytes
-rw-r--r--data/sounds/ringtones/boosted/Themos.oggbin0 -> 185452 bytes
-rw-r--r--data/sounds/ringtones/boosted/Third_Eye.oggbin0 -> 43181 bytes
-rw-r--r--data/sounds/ringtones/boosted/Thunderfoot.oggbin0 -> 52633 bytes
-rw-r--r--data/sounds/ringtones/boosted/Titania.oggbin0 -> 340948 bytes
-rw-r--r--data/sounds/ringtones/boosted/Triton.oggbin0 -> 236564 bytes
-rw-r--r--data/sounds/ringtones/boosted/TwirlAway.oggbin0 -> 39204 bytes
-rw-r--r--data/sounds/ringtones/boosted/Umbriel.oggbin0 -> 127862 bytes
-rw-r--r--data/sounds/ringtones/boosted/UrsaMinor.oggbin0 -> 186873 bytes
-rw-r--r--data/sounds/ringtones/boosted/VeryAlarmed.oggbin0 -> 47201 bytes
-rw-r--r--data/sounds/ringtones/boosted/Vespa.oggbin0 -> 27836 bytes
-rw-r--r--data/sounds/ringtones/boosted/World.oggbin0 -> 42440 bytes
-rw-r--r--data/sounds/ringtones/boosted/Zeta.oggbin0 -> 95474 bytes
-rw-r--r--graphics/java/android/graphics/Bitmap.java1
-rw-r--r--graphics/java/android/graphics/FontListConverter.java220
-rw-r--r--graphics/java/android/graphics/FontListParser.java79
-rw-r--r--graphics/java/android/graphics/LegacyFontListParser.java187
-rw-r--r--graphics/java/android/graphics/Typeface.java183
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java12
-rw-r--r--graphics/tests/localtests/Android.mk18
-rw-r--r--graphics/tests/localtests/src/android/graphics/FontListConverterTest.java280
-rw-r--r--graphics/tests/localtests/src/android/graphics/TypefaceTestSuite.java27
-rw-r--r--include/SeempLog.h51
-rw-r--r--include/androidfw/AssetManager.h39
-rw-r--r--include/androidfw/AttributeFinder.h7
-rw-r--r--include/androidfw/ResourceTypes.h24
-rw-r--r--include/private/time_genoff.h87
-rw-r--r--include/storage/IMountService.h1
-rw-r--r--libs/androidfw/AssetManager.cpp402
-rw-r--r--libs/androidfw/ResourceTypes.cpp474
-rw-r--r--libs/androidfw/tests/Android.mk15
-rw-r--r--libs/androidfw/tests/Idmap_test.cpp2
-rw-r--r--libs/androidfw/tests/PackageIdOverride_test.cpp60
-rw-r--r--libs/androidfw/tests/ThemesBags_test.cpp169
-rw-r--r--libs/androidfw/tests/ThemesIdmap_test.cpp133
-rw-r--r--libs/androidfw/tests/data/app/R.h9
-rw-r--r--libs/androidfw/tests/data/app/app_arsc.h101
-rw-r--r--libs/androidfw/tests/data/app/res/values/values.xml15
-rw-r--r--libs/androidfw/tests/data/bags/AndroidManifest.xml21
-rw-r--r--libs/androidfw/tests/data/bags/R.h26
-rw-r--r--libs/androidfw/tests/data/bags/bags_arsc.h88
-rwxr-xr-xlibs/androidfw/tests/data/bags/build6
-rw-r--r--libs/androidfw/tests/data/bags/res/values/values.xml24
-rw-r--r--libs/androidfw/tests/data/basic/res/drawable/drawable1.pngbin0 -> 69 bytes
-rw-r--r--libs/androidfw/tests/data/basic/res/values/values.xml3
-rw-r--r--libs/androidfw/tests/data/cm/app/AndroidManifest.xml19
-rw-r--r--libs/androidfw/tests/data/cm/app/R.h31
-rw-r--r--libs/androidfw/tests/data/cm/app/app_arsc.h91
-rwxr-xr-xlibs/androidfw/tests/data/cm/app/build6
-rw-r--r--libs/androidfw/tests/data/cm/app/res/values/values.xml22
-rw-r--r--libs/androidfw/tests/data/cm/bags/AndroidManifest.xml21
-rw-r--r--libs/androidfw/tests/data/cm/bags/R.h26
-rw-r--r--libs/androidfw/tests/data/cm/bags/bags_arsc.h88
-rwxr-xr-xlibs/androidfw/tests/data/cm/bags/build6
-rw-r--r--libs/androidfw/tests/data/cm/bags/res/values/values.xml24
-rw-r--r--libs/androidfw/tests/data/cm/basic/AndroidManifest.xml21
-rw-r--r--libs/androidfw/tests/data/cm/basic/R.h68
-rw-r--r--libs/androidfw/tests/data/cm/basic/basic_arsc.h194
-rwxr-xr-xlibs/androidfw/tests/data/cm/basic/build11
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/drawable/drawable1.pngbin0 -> 69 bytes
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/layout-fr-sw600dp/main.xml3
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/layout/main.xml3
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/values-de/values.xml5
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/values-fr/values.xml5
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/values-sv/values.xml4
-rw-r--r--libs/androidfw/tests/data/cm/basic/res/values/values.xml29
-rw-r--r--libs/androidfw/tests/data/cm/basic/split_de_fr_arsc.h92
-rw-r--r--libs/androidfw/tests/data/cm/overlay/AndroidManifest.xml21
-rwxr-xr-xlibs/androidfw/tests/data/cm/overlay/build6
-rw-r--r--libs/androidfw/tests/data/cm/overlay/overlay_arsc.h103
-rw-r--r--libs/androidfw/tests/data/cm/overlay/res/drawable/drawable1.pngbin0 -> 69 bytes
-rw-r--r--libs/androidfw/tests/data/cm/overlay/res/values/values.xml12
-rw-r--r--libs/androidfw/tests/data/cm/override/AndroidManifest.xml21
-rw-r--r--libs/androidfw/tests/data/cm/override/R.h16
-rwxr-xr-xlibs/androidfw/tests/data/cm/override/build6
-rw-r--r--libs/androidfw/tests/data/cm/override/override_arsc.h53
-rw-r--r--libs/androidfw/tests/data/cm/override/res/values/values.xml4
-rw-r--r--libs/androidfw/tests/data/cm/system/AndroidManifest.xml19
-rw-r--r--libs/androidfw/tests/data/cm/system/R.h26
-rwxr-xr-xlibs/androidfw/tests/data/cm/system/build6
-rw-r--r--libs/androidfw/tests/data/cm/system/res/values/filler.xml168
-rw-r--r--libs/androidfw/tests/data/cm/system/res/values/themes.xml21
-rw-r--r--libs/androidfw/tests/data/cm/system/system_arsc.h538
-rw-r--r--libs/androidfw/tests/data/overlay/overlay_arsc.h86
-rw-r--r--libs/androidfw/tests/data/overlay/res/drawable/drawable1.pngbin0 -> 69 bytes
-rw-r--r--libs/androidfw/tests/data/overlay/res/values/values.xml4
-rw-r--r--libs/androidfw/tests/data/override/AndroidManifest.xml21
-rw-r--r--libs/androidfw/tests/data/override/R.h16
-rwxr-xr-xlibs/androidfw/tests/data/override/build6
-rw-r--r--libs/androidfw/tests/data/override/override_arsc.h53
-rw-r--r--libs/androidfw/tests/data/override/res/values/values.xml4
-rw-r--r--libs/androidfw/tests/data/system/R.h7
-rw-r--r--libs/androidfw/tests/data/system/res/values/filler.xml168
-rw-r--r--libs/androidfw/tests/data/system/res/values/themes.xml8
-rw-r--r--libs/androidfw/tests/data/system/system_arsc.h525
-rw-r--r--libs/hwui/Android.mk4
-rw-r--r--libs/hwui/FontRenderer.cpp8
-rw-r--r--libs/hwui/FontRenderer.h2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp17
-rw-r--r--libs/hwui/PathCache.cpp7
-rw-r--r--libs/hwui/PathCache.h1
-rw-r--r--libs/hwui/SpotShadow.cpp2
-rw-r--r--libs/hwui/font/CacheTexture.cpp14
-rw-r--r--libs/hwui/font/Font.cpp2
-rw-r--r--libs/hwui/renderstate/RenderState.cpp4
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp5
-rw-r--r--libs/hwui/renderthread/CanvasContext.h2
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp17
-rw-r--r--libs/hwui/renderthread/RenderProxy.h3
-rw-r--r--libs/storage/IMountService.cpp18
-rw-r--r--location/java/android/location/GeoFenceParams.aidl23
-rw-r--r--location/java/android/location/GeoFenceParams.java132
-rw-r--r--[-rwxr-xr-x]location/java/android/location/IGeoFenceListener.aidl (renamed from core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl)20
-rw-r--r--location/java/android/location/IGeoFencer.aidl33
-rw-r--r--location/java/android/location/LocationManager.java17
-rw-r--r--media/java/android/media/AudioFormat.java64
-rw-r--r--media/java/android/media/AudioManager.java101
-rw-r--r--media/java/android/media/AudioRecord.java30
-rw-r--r--media/java/android/media/AudioSystem.java58
-rw-r--r--media/java/android/media/CamcorderProfile.java75
-rw-r--r--media/java/android/media/ClosedCaptionRenderer.java6
-rw-r--r--media/java/android/media/EncoderCapabilities.java9
-rw-r--r--media/java/android/media/IAudioService.aidl17
-rw-r--r--media/java/android/media/IRemoteControlClient.aidl5
-rw-r--r--media/java/android/media/MediaCodecInfo.java7
-rw-r--r--media/java/android/media/MediaFile.java36
-rw-r--r--media/java/android/media/MediaHTTPConnection.java55
-rw-r--r--media/java/android/media/MediaMetadataEditor.java4
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java10
-rw-r--r--media/java/android/media/MediaPlayer.java17
-rw-r--r--media/java/android/media/MediaRecorder.java26
-rw-r--r--media/java/android/media/MediaScanner.java16
-rw-r--r--media/java/android/media/RemoteControlClient.java203
-rw-r--r--media/java/android/media/RemoteController.java186
-rw-r--r--media/java/android/media/Ringtone.java16
-rw-r--r--media/java/android/media/RingtoneManager.java117
-rw-r--r--media/java/android/media/ToneGenerator.java13
-rw-r--r--media/java/android/media/session/ISession.aidl4
-rw-r--r--media/java/android/media/session/ISessionCallback.aidl3
-rw-r--r--media/java/android/media/session/ISessionController.aidl3
-rw-r--r--media/java/android/media/session/ISessionControllerCallback.aidl4
-rw-r--r--media/java/android/media/session/MediaController.java114
-rw-r--r--media/java/android/media/session/MediaSession.java141
-rw-r--r--media/java/android/media/session/MediaSessionLegacyHelper.java21
-rw-r--r--media/java/android/mtp/MtpServer.java5
-rw-r--r--media/jni/android_media_MediaPlayer.cpp202
-rw-r--r--media/jni/android_media_MediaProfiles.cpp17
-rw-r--r--media/jni/android_media_MediaRecorder.cpp14
-rw-r--r--media/jni/android_mtp_MtpServer.cpp13
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp9
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp1
-rw-r--r--obex/javax/obex/ClientOperation.java51
-rw-r--r--obex/javax/obex/ClientSession.java8
-rw-r--r--obex/javax/obex/ObexHelper.java28
-rw-r--r--obex/javax/obex/ObexSession.java2
-rw-r--r--obex/javax/obex/ServerOperation.java25
-rw-r--r--obex/javax/obex/ServerSession.java20
-rw-r--r--packages/BackupRestoreConfirmation/res/values-ast-rES/strings.xml38
-rw-r--r--packages/BackupRestoreConfirmation/res/values-be/strings.xml38
-rw-r--r--packages/BackupRestoreConfirmation/res/values-eo/strings.xml21
-rw-r--r--packages/BackupRestoreConfirmation/res/values-ku/strings.xml38
-rw-r--r--packages/BackupRestoreConfirmation/res/values-lb/strings.xml38
-rw-r--r--packages/BackupRestoreConfirmation/res/values-ug/strings.xml37
-rw-r--r--packages/CaptivePortalLogin/AndroidManifest.xml4
-rw-r--r--packages/CaptivePortalLogin/res/values-ast-rES/strings.xml7
-rw-r--r--packages/CaptivePortalLogin/res/values-be/strings.xml7
-rw-r--r--packages/CaptivePortalLogin/res/values-ku/strings.xml6
-rw-r--r--packages/CaptivePortalLogin/res/values-lb/strings.xml7
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java41
-rw-r--r--packages/DefaultContainerService/res/values-ast-rES/strings.xml23
-rw-r--r--packages/DefaultContainerService/res/values-be/strings.xml23
-rw-r--r--packages/DefaultContainerService/res/values-ku/strings.xml23
-rw-r--r--packages/DefaultContainerService/res/values-lb/strings.xml23
-rw-r--r--packages/DefaultContainerService/res/values-ug/strings.xml23
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java1
-rw-r--r--packages/DocumentsUI/res/layout/activity.xml4
-rw-r--r--packages/DocumentsUI/res/layout/item_doc_grid.xml6
-rw-r--r--packages/DocumentsUI/res/values-ast-rES/strings.xml55
-rw-r--r--packages/DocumentsUI/res/values-be/strings.xml55
-rw-r--r--packages/DocumentsUI/res/values-eo/strings.xml29
-rw-r--r--packages/DocumentsUI/res/values-ku/strings.xml49
-rw-r--r--packages/DocumentsUI/res/values-lb/strings.xml55
-rw-r--r--packages/DocumentsUI/res/values-ug/strings.xml49
-rw-r--r--packages/DocumentsUI/res/values/cm_colors.xml23
-rw-r--r--packages/DocumentsUI/res/values/cm_dimens.xml21
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java6
-rw-r--r--packages/ExternalStorageProvider/res/values-ast-rES/strings.xml21
-rw-r--r--packages/ExternalStorageProvider/res/values-be/strings.xml21
-rw-r--r--packages/ExternalStorageProvider/res/values-eo/strings.xml19
-rw-r--r--packages/ExternalStorageProvider/res/values-ku/strings.xml21
-rw-r--r--packages/ExternalStorageProvider/res/values-lb/strings.xml21
-rw-r--r--packages/ExternalStorageProvider/res/values-ug/strings.xml21
-rw-r--r--packages/FusedLocation/res/values-ast-rES/strings.xml5
-rw-r--r--packages/FusedLocation/res/values-be/strings.xml5
-rw-r--r--packages/FusedLocation/res/values-ku/strings.xml5
-rw-r--r--packages/FusedLocation/res/values-lb/strings.xml5
-rw-r--r--packages/FusedLocation/res/values-ug/strings.xml5
-rw-r--r--packages/InputDevices/res/values-ast-rES/strings.xml43
-rw-r--r--packages/InputDevices/res/values-be/strings.xml43
-rw-r--r--packages/InputDevices/res/values-eo/strings.xml11
-rw-r--r--packages/InputDevices/res/values-ku/strings.xml37
-rw-r--r--packages/InputDevices/res/values-lb/strings.xml43
-rw-r--r--packages/InputDevices/res/values-ug/strings.xml37
-rw-r--r--packages/Keyguard/Android.mk2
-rw-r--r--packages/Keyguard/res/layout/keyguard_pin_view.xml2
-rw-r--r--packages/Keyguard/res/layout/keyguard_sim_pin_view.xml2
-rw-r--r--packages/Keyguard/res/layout/keyguard_sim_puk_view.xml2
-rw-r--r--packages/Keyguard/res/values-af/cm_strings.xml22
-rw-r--r--packages/Keyguard/res/values-ar/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-ast-rES/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-ast-rES/strings.xml95
-rw-r--r--packages/Keyguard/res/values-az-rAZ/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-be/cm_strings.xml27
-rw-r--r--packages/Keyguard/res/values-bg/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-bn-rBD/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-ca/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-cs/cm_strings.xml27
-rw-r--r--packages/Keyguard/res/values-da/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-de/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-el/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-en-rAU/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-en-rIN/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-eo/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-eo/strings.xml25
-rw-r--r--packages/Keyguard/res/values-es/cm_strings.xml25
-rw-r--r--packages/Keyguard/res/values-et-rEE/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-eu-rES/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-fa/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-fi/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-fr/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-gl-rES/cm_strings.xml22
-rw-r--r--packages/Keyguard/res/values-hi/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-hr/cm_strings.xml27
-rw-r--r--packages/Keyguard/res/values-hu/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-in/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-it/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-iw/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-ja/cm_strings.xml25
-rw-r--r--packages/Keyguard/res/values-kn-rIN/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-ko/cm_strings.xml25
-rw-r--r--packages/Keyguard/res/values-ku/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-ku/strings.xml104
-rw-r--r--packages/Keyguard/res/values-lb/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-lb/strings.xml105
-rw-r--r--packages/Keyguard/res/values-lt/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-lv/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-nb/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-nl/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-pl/cm_strings.xml27
-rw-r--r--packages/Keyguard/res/values-pt-rBR/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-pt-rPT/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-ro/cm_strings.xml21
-rw-r--r--packages/Keyguard/res/values-ru/cm_strings.xml27
-rw-r--r--packages/Keyguard/res/values-sk/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-sl/cm_strings.xml28
-rw-r--r--packages/Keyguard/res/values-sr/cm_strings.xml27
-rw-r--r--packages/Keyguard/res/values-sv/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-th/cm_strings.xml24
-rw-r--r--packages/Keyguard/res/values-tr/cm_strings.xml25
-rw-r--r--packages/Keyguard/res/values-ug/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-ug/strings.xml78
-rw-r--r--packages/Keyguard/res/values-uk/cm_strings.xml26
-rw-r--r--packages/Keyguard/res/values-vi/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-zh-rCN/cm_strings.xml25
-rw-r--r--packages/Keyguard/res/values-zh-rHK/cm_strings.xml20
-rw-r--r--packages/Keyguard/res/values-zh-rTW/cm_strings.xml22
-rw-r--r--packages/Keyguard/res/values/cm_colors.xml19
-rw-r--r--packages/Keyguard/res/values/cm_strings.xml32
-rw-r--r--packages/Keyguard/src/com/android/keyguard/CarrierText.java75
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java38
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java8
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java86
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java7
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java21
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java6
-rw-r--r--packages/Keyguard/src/com/android/keyguard/NumPadKey.java39
-rw-r--r--packages/PrintSpooler/res/values-ast-rES/strings.xml83
-rw-r--r--packages/PrintSpooler/res/values-ku/strings.xml83
-rw-r--r--packages/PrintSpooler/res/values-lb/strings.xml80
-rw-r--r--packages/PrintSpooler/res/values-ug/strings.xml60
-rw-r--r--packages/PrintSpooler/res/values-zh-rCN/arrays.xml37
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java5
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java16
-rw-r--r--packages/SettingsLib/res/drawable-hdpi/activities_icon.pngbin0 -> 2399 bytes
-rw-r--r--packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.pngbin4349 -> 725 bytes
-rw-r--r--packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.pngbin3872 -> 511 bytes
-rw-r--r--packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.pngbin4781 -> 867 bytes
-rw-r--r--packages/SettingsLib/res/drawable-mdpi/activities_icon.pngbin0 -> 1702 bytes
-rw-r--r--packages/SettingsLib/res/drawable-xhdpi/activities_icon.pngbin0 -> 2999 bytes
-rw-r--r--packages/SettingsLib/res/drawable-xxhdpi/activities_icon.pngbin0 -> 4977 bytes
-rw-r--r--packages/SettingsLib/res/drawable-xxxhdpi/activities_icon.pngbin0 -> 7498 bytes
-rw-r--r--packages/SettingsLib/res/values-af/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-be/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-bg/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-ca/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-cs/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-da/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-de/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-el/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-en-rIN/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-eu-rES/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-fi/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-fr/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-gl-rES/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-hr/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-hu/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-it/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-iw/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-ja/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-ko/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-lb/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-nb/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-nl/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-pl/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-ro/cm_strings.xml26
-rw-r--r--packages/SettingsLib/res/values-ru/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-sl/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-sr/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-sv/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-uk/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/cm_strings.xml27
-rw-r--r--packages/SettingsLib/res/values/cm_dimens.xml19
-rw-r--r--packages/SettingsLib/res/values/cm_strings.xml26
-rw-r--r--packages/SettingsLib/res/values/strings.xml6
-rw-r--r--[-rwxr-xr-x]packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java34
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java223
-rwxr-xr-x[-rw-r--r--]packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java4
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java29
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java162
-rwxr-xr-x[-rw-r--r--]packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java57
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java9
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/cm/ShortcutPickHelper.java326
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java13
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java14
-rw-r--r--packages/SettingsProvider/Android.mk2
-rw-r--r--packages/SettingsProvider/res/mipmap-hdpi/ic_launcher_settings.pngbin8822 -> 5946 bytes
-rw-r--r--packages/SettingsProvider/res/mipmap-mdpi/ic_launcher_settings.pngbin5362 -> 3589 bytes
-rw-r--r--packages/SettingsProvider/res/mipmap-xhdpi/ic_launcher_settings.pngbin12096 -> 8605 bytes
-rw-r--r--packages/SettingsProvider/res/mipmap-xxhdpi/ic_launcher_settings.pngbin20300 -> 14731 bytes
-rw-r--r--packages/SettingsProvider/res/mipmap-xxxhdpi/ic_launcher_settings.pngbin27997 -> 21728 bytes
-rw-r--r--packages/SettingsProvider/res/values-ast-rES/strings.xml22
-rw-r--r--packages/SettingsProvider/res/values-be/strings.xml22
-rw-r--r--packages/SettingsProvider/res/values-ku/strings.xml22
-rw-r--r--packages/SettingsProvider/res/values-lb/strings.xml22
-rw-r--r--packages/SettingsProvider/res/values-ug/strings.xml22
-rw-r--r--packages/SettingsProvider/res/values/customize.xml63
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml23
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java308
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java41
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java235
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java48
-rw-r--r--packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java2
-rw-r--r--packages/Shell/AndroidManifest.xml5
-rw-r--r--packages/Shell/res/values-ast-rES/strings.xml24
-rw-r--r--packages/Shell/res/values-be/strings.xml24
-rw-r--r--packages/Shell/res/values-ku/strings.xml23
-rw-r--r--packages/Shell/res/values-lb/strings.xml24
-rw-r--r--packages/Shell/res/values-ug/strings.xml23
-rw-r--r--packages/Shell/res/values/cm_strings.xml20
-rw-r--r--packages/Shell/src/com/android/shell/BugreportReceiver.java15
-rw-r--r--packages/SystemUI/Android.mk7
-rw-r--r--packages/SystemUI/AndroidManifest.xml26
-rw-r--r--packages/SystemUI/AndroidManifest_cm.xml77
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_longtomed.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_longtoshort.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort_reverse.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_shorttolong.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_staymed.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_tolong.xml7
-rw-r--r--packages/SystemUI/res/anim/ic_qs_screen_timeout_tomed.xml7
-rwxr-xr-xpackages/SystemUI/res/anim/ic_qs_tile_delete_disable_cross_anim.xml31
-rwxr-xr-xpackages/SystemUI/res/anim/ic_qs_tile_delete_disable_mask_anim.xml25
-rwxr-xr-xpackages/SystemUI/res/anim/ic_qs_tile_delete_disable_root_anim.xml24
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/ic_mini_settings.pngbin0 -> 192 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.pngbin749 -> 385 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_add.pngbin0 -> 536 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_land.pngbin0 -> 532 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_side.pngbin0 -> 992 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_side.pngbin0 -> 1300 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_left.pngbin0 -> 1284 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_right.pngbin0 -> 1307 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big.pngbin0 -> 744 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big_land.pngbin0 -> 744 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_side.pngbin0 -> 1226 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_search.pngbin0 -> 1042 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_land.pngbin0 -> 1016 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_side.pngbin0 -> 1440 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_notify_image.pngbin846 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.pngbin1112 -> 0 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-mdpi/ic_mini_settings.pngbin0 -> 133 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.pngbin507 -> 267 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_add.pngbin0 -> 321 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_land.pngbin0 -> 320 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_side.pngbin0 -> 1083 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_side.pngbin0 -> 1177 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_left.pngbin0 -> 1213 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_right.pngbin0 -> 1218 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big.pngbin0 -> 487 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big_land.pngbin0 -> 479 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_side.pngbin0 -> 1151 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_search.pngbin0 -> 650 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_land.pngbin0 -> 641 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_side.pngbin0 -> 1266 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_notify_image.pngbin691 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.pngbin850 -> 0 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xhdpi/ic_mini_settings.pngbin0 -> 218 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_notification_overlay.9.pngbin1006 -> 519 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add.pngbin0 -> 552 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_land.pngbin0 -> 543 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_side.pngbin0 -> 517 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_side.pngbin0 -> 3434 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_left.pngbin0 -> 1388 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_right.pngbin0 -> 1383 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big.pngbin0 -> 898 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big_land.pngbin0 -> 880 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_side.pngbin0 -> 3209 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search.pngbin0 -> 1457 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_land.pngbin0 -> 1409 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_side.pngbin0 -> 3766 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_notify_image.pngbin981 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.pngbin1418 -> 0 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xxhdpi/ic_mini_settings.pngbin0 -> 324 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_notification_overlay.9.pngbin1823 -> 775 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add.pngbin0 -> 889 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add_land.pngbin0 -> 891 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_left.pngbin0 -> 1632 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_right.pngbin0 -> 1770 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big.pngbin0 -> 1444 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big_land.pngbin0 -> 1479 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search.pngbin0 -> 2566 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search_land.pngbin0 -> 2769 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.pngbin1458 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.pngbin1923 -> 0 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xxxhdpi/ic_mini_settings.pngbin0 -> 401 bytes
-rw-r--r--packages/SystemUI/res/drawable/cid.xml33
-rw-r--r--packages/SystemUI/res/drawable/ic_dynamic_qs_adb.xml58
-rw-r--r--packages/SystemUI/res/drawable/ic_dynamic_qs_ime_selector.xml29
-rw-r--r--packages/SystemUI/res/drawable/ic_dynamic_qs_next_alarm.xml30
-rw-r--r--packages/SystemUI/res/drawable/ic_dynamic_qs_su.xml39
-rw-r--r--packages/SystemUI/res/drawable/ic_livedisplay_auto.xml29
-rw-r--r--packages/SystemUI/res/drawable/ic_livedisplay_day.xml30
-rw-r--r--packages/SystemUI/res/drawable/ic_livedisplay_night.xml29
-rw-r--r--packages/SystemUI/res/drawable/ic_livedisplay_off.xml29
-rw-r--r--packages/SystemUI/res/drawable/ic_livedisplay_outdoor.xml27
-rw-r--r--packages/SystemUI/res/drawable/ic_lockscreen_shortcuts_blank.xml30
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_ambientdisplay_off.xml58
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_ambientdisplay_on.xml51
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_caffeine_off.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_caffeine_on.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_compass_off.xml32
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_compass_on.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_dnd_on_priority.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_edit_tiles.xml30
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_battery_saving.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_lock_screen_off.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_lock_screen_on.xml14
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_network_adb_off.xml32
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_network_adb_on.xml35
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_nfc_off.xml32
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_nfc_on.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_perf_profile.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_profiles_off.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_profiles_on.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_avd.xml12
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_reverse_avd.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_avd.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_reverse_avd.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_avd.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_reverse_avd.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_screen_timeout_vector.xml53
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml50
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_hp.xml27
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_sync_off.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_sync_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_tile_category_other.xml23
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_tile_category_system.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_tile_contract.xml24
-rwxr-xr-xpackages/SystemUI/res/drawable/ic_qs_tile_delete.xml27
-rwxr-xr-xpackages/SystemUI/res/drawable/ic_qs_tile_delete_disable.xml40
-rwxr-xr-xpackages/SystemUI/res/drawable/ic_qs_tile_delete_disable_avd.xml28
-rwxr-xr-xpackages/SystemUI/res/drawable/ic_qs_tile_delete_enable.xml40
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_tile_expand.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_usb_tether_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_usb_tether_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_volume_panel.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_settings.xml39
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_notification.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_notification_mute.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_ringer.xml14
-rw-r--r--packages/SystemUI/res/drawable/lockscreen_shortcuts_phone_background.xml21
-rw-r--r--packages/SystemUI/res/drawable/lockscreen_target_background.xml20
-rw-r--r--packages/SystemUI/res/drawable/notification_guts_ic_ringer_mute.xml20
-rw-r--r--packages/SystemUI/res/drawable/notification_guts_ic_settings.xml20
-rw-r--r--packages/SystemUI/res/drawable/qs_tile_background_drag.xml22
-rw-r--r--packages/SystemUI/res/drawable/stat_notify_image.xml27
-rw-r--r--packages/SystemUI/res/drawable/stat_notify_image_error.xml27
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml50
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_data_fully_connected_hp.xml27
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_data_roaming.xml22
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_dnd_priority.xml28
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_su.xml15
-rw-r--r--packages/SystemUI/res/drawable/volume_dialog_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/zen_mode_panel_background.xml24
-rw-r--r--packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_land.xml115
-rw-r--r--packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_port.xml132
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_bar.xml324
-rw-r--r--packages/SystemUI/res/layout/cmland.xml104
-rw-r--r--packages/SystemUI/res/layout/keyguard_bottom_area.xml4
-rw-r--r--packages/SystemUI/res/layout/keyguard_status_bar.xml16
-rw-r--r--packages/SystemUI/res/layout/lockscreen_shortcuts.xml65
-rw-r--r--packages/SystemUI/res/layout/mid_navigation_bar_land.xml130
-rw-r--r--packages/SystemUI/res/layout/mid_navigation_bar_port.xml126
-rw-r--r--packages/SystemUI/res/layout/mland.xml4
-rw-r--r--packages/SystemUI/res/layout/mland_scorefield.xml2
-rw-r--r--packages/SystemUI/res/layout/mobile_signal_group.xml57
-rw-r--r--packages/SystemUI/res/layout/navigation_bar.xml198
-rw-r--r--packages/SystemUI/res/layout/navigation_bar_edit_menu_item.xml44
-rw-r--r--packages/SystemUI/res/layout/notification_guts.xml14
-rw-r--r--packages/SystemUI/res/layout/profiles_detail_view.xml31
-rw-r--r--packages/SystemUI/res/layout/qs_custom_detail.xml59
-rw-r--r--packages/SystemUI/res/layout/qs_custom_detail_remote.xml25
-rw-r--r--packages/SystemUI/res/layout/qs_detail.xml13
-rw-r--r--packages/SystemUI/res/layout/qs_detail_header.xml13
-rw-r--r--packages/SystemUI/res/layout/qs_detail_item.xml2
-rw-r--r--packages/SystemUI/res/layout/qs_detail_items.xml6
-rw-r--r--packages/SystemUI/res/layout/qs_detail_items_grid.xml27
-rw-r--r--packages/SystemUI/res/layout/qs_detail_items_list.xml54
-rw-r--r--packages/SystemUI/res/layout/qs_panel.xml7
-rw-r--r--packages/SystemUI/res/layout/qs_settings.xml96
-rw-r--r--packages/SystemUI/res/layout/qs_settings_row.xml34
-rw-r--r--packages/SystemUI/res/layout/qs_tile_category_row.xml55
-rw-r--r--packages/SystemUI/res/layout/qs_tile_child_row.xml42
-rw-r--r--packages/SystemUI/res/layout/qs_tile_top.xml86
-rw-r--r--packages/SystemUI/res/layout/qs_user_detail_item.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_settings_notification_brightness_dialog.xml31
-rw-r--r--packages/SystemUI/res/layout/recents_empty.xml6
-rw-r--r--packages/SystemUI/res/layout/recents_search_bar.xml2
-rw-r--r--packages/SystemUI/res/layout/recents_task_view_header.xml4
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request.xml6
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_text_area.xml10
-rw-r--r--packages/SystemUI/res/layout/signal_cluster_view.xml1
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml45
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml4
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml81
-rw-r--r--packages/SystemUI/res/layout/status_bar_no_notifications.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_no_recent_apps.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_toggle_slider.xml2
-rw-r--r--packages/SystemUI/res/layout/super_status_bar.xml49
-rw-r--r--packages/SystemUI/res/layout/system_icons.xml13
-rw-r--r--packages/SystemUI/res/layout/unlock_fab.xml8
-rw-r--r--packages/SystemUI/res/layout/volume_dialog.xml4
-rw-r--r--packages/SystemUI/res/layout/zen_mode_panel.xml2
-rw-r--r--packages/SystemUI/res/menu/recent_popup_menu.xml26
-rw-r--r--packages/SystemUI/res/values-af/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-af/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-ar/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ar/cm_strings.xml120
-rw-r--r--packages/SystemUI/res/values-ast-rES/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ast-rES/cm_strings.xml66
-rw-r--r--packages/SystemUI/res/values-ast-rES/strings.xml311
-rw-r--r--packages/SystemUI/res/values-az-rAZ/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-az-rAZ/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-be/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-be/cm_strings.xml139
-rw-r--r--packages/SystemUI/res/values-be/strings.xml26
-rw-r--r--packages/SystemUI/res/values-bg/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-bg/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-bn-rBD/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-bn-rBD/cm_strings.xml33
-rw-r--r--packages/SystemUI/res/values-ca/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ca/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-cs/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-cs/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-da/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-da/cm_strings.xml135
-rw-r--r--packages/SystemUI/res/values-de/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-de/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-el/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-el/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-en-rAU/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-en-rAU/cm_strings.xml55
-rw-r--r--packages/SystemUI/res/values-en-rIN/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-en-rIN/cm_strings.xml138
-rw-r--r--packages/SystemUI/res/values-eo/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-eo/cm_strings.xml107
-rw-r--r--packages/SystemUI/res/values-es/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-es/cm_strings.xml136
-rw-r--r--packages/SystemUI/res/values-et-rEE/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-et-rEE/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-eu-rES/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-eu-rES/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-fa/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-fa/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-fi/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-fi/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-fr/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-fr/cm_strings.xml138
-rw-r--r--packages/SystemUI/res/values-fy-rNL/cm_strings.xml20
-rw-r--r--packages/SystemUI/res/values-gl-rES/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-gl-rES/cm_strings.xml139
-rw-r--r--packages/SystemUI/res/values-hdpi/cm_dimens.xml19
-rw-r--r--packages/SystemUI/res/values-hi/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-hi/cm_strings.xml107
-rw-r--r--packages/SystemUI/res/values-hr/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-hr/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-hu/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-hu/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-in/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-in/cm_strings.xml107
-rw-r--r--packages/SystemUI/res/values-it/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-it/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-iw/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-iw/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-ja/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ja/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-kn-rIN/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-kn-rIN/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-ko/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ko/cm_strings.xml142
-rw-r--r--packages/SystemUI/res/values-ku/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ku/cm_strings.xml61
-rw-r--r--packages/SystemUI/res/values-ku/strings.xml209
-rw-r--r--packages/SystemUI/res/values-land/cm_dimens.xml21
-rw-r--r--packages/SystemUI/res/values-lb/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-lb/cm_strings.xml138
-rw-r--r--packages/SystemUI/res/values-lb/strings.xml327
-rw-r--r--packages/SystemUI/res/values-lt/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-lt/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-lv/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-lv/cm_strings.xml33
-rw-r--r--packages/SystemUI/res/values-mdpi/cm_dimens.xml19
-rw-r--r--packages/SystemUI/res/values-nb/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-nb/cm_strings.xml139
-rw-r--r--packages/SystemUI/res/values-nl/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-nl/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-pl/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-pl/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-pt-rBR/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-pt-rBR/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-pt-rPT/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-pt-rPT/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-ro/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ro/cm_strings.xml123
-rw-r--r--packages/SystemUI/res/values-ru/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ru/cm_strings.xml143
-rw-r--r--packages/SystemUI/res/values-si-rLK/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-si-rLK/cm_strings.xml33
-rw-r--r--packages/SystemUI/res/values-sk/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-sk/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-sl/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-sl/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-sr/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-sr/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-sv/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-sv/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-th/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-th/cm_strings.xml136
-rw-r--r--packages/SystemUI/res/values-tr/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-tr/cm_strings.xml136
-rw-r--r--packages/SystemUI/res/values-ug/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-ug/cm_strings.xml55
-rw-r--r--packages/SystemUI/res/values-ug/strings.xml166
-rw-r--r--packages/SystemUI/res/values-uk/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-uk/cm_strings.xml138
-rw-r--r--packages/SystemUI/res/values-vi/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-vi/cm_strings.xml119
-rw-r--r--packages/SystemUI/res/values-xhdpi/cm_dimens.xml19
-rw-r--r--packages/SystemUI/res/values-xxhdpi/cm_dimens.xml19
-rw-r--r--packages/SystemUI/res/values-zh-rCN/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-zh-rCN/cm_strings.xml146
-rw-r--r--packages/SystemUI/res/values-zh-rHK/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-zh-rHK/cm_strings.xml97
-rw-r--r--packages/SystemUI/res/values-zh-rTW/cm_arrays.xml29
-rw-r--r--packages/SystemUI/res/values-zh-rTW/cm_strings.xml97
-rw-r--r--packages/SystemUI/res/values/arrays.xml2
-rw-r--r--packages/SystemUI/res/values/cm_arrays.xml146
-rw-r--r--packages/SystemUI/res/values/cm_attrs.xml34
-rw-r--r--packages/SystemUI/res/values/cm_colors.xml120
-rw-r--r--packages/SystemUI/res/values/cm_dimens.xml59
-rw-r--r--packages/SystemUI/res/values/cm_strings.xml267
-rw-r--r--packages/SystemUI/res/values/cm_styles.xml44
-rw-r--r--packages/SystemUI/res/values/colors.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml20
-rw-r--r--packages/SystemUI/res/values/vpi__attrs.xml44
-rw-r--r--packages/SystemUI/res/values/vpi__defaults.xml26
-rw-r--r--packages/SystemUI/res/xml/tuner_prefs.xml55
-rw-r--r--packages/SystemUI/res/xml/tuner_statusbar_icons.xml60
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java139
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/BatteryMeterView.java1123
-rw-r--r--packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java30
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java192
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/GlowBackground.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java239
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java196
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java204
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/UserContentObserver.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/egg/CMLand.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/egg/MLand.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java10
-rwxr-xr-x[-rw-r--r--]packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java241
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerUI.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java163
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsGrid.java154
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java212
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java2148
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPage.java161
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java133
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java368
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSSettings.java82
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileView.java158
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java130
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java85
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java202
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java193
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java301
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java223
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java216
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java163
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java123
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java237
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java287
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java344
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java109
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java119
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessController.java247
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessDialog.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java30
-rwxr-xr-x[-rw-r--r--]packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java200
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java132
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java377
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BackButtonDrawable.java139
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BlurLayer.java196
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java149
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java220
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java101
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java217
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java580
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java403
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java324
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java1366
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java223
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java257
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java350
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java133
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java110
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java187
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java159
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java145
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SuController.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SuControllerImpl.java132
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java126
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java277
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerService.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java142
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java109
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java7
-rw-r--r--packages/SystemUI/src/com/viewpagerindicator/CirclePageIndicator.java527
-rw-r--r--packages/SystemUI/src/com/viewpagerindicator/PageIndicator.java63
-rw-r--r--packages/SystemUI/tests/Android.mk3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java2
-rw-r--r--packages/VpnDialogs/res/values-ast-rES/strings.xml38
-rw-r--r--packages/VpnDialogs/res/values-be/strings.xml38
-rw-r--r--packages/VpnDialogs/res/values-ku/strings.xml29
-rw-r--r--packages/VpnDialogs/res/values-lb/strings.xml37
-rw-r--r--packages/VpnDialogs/res/values-ug/strings.xml26
-rw-r--r--packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml2
-rw-r--r--packages/WallpaperCropper/res/values-ast-rES/strings.xml21
-rw-r--r--packages/WallpaperCropper/res/values-be/strings.xml21
-rw-r--r--packages/WallpaperCropper/res/values-ku/strings.xml21
-rw-r--r--packages/WallpaperCropper/res/values-lb/strings.xml21
-rw-r--r--packages/WallpaperCropper/res/values/cm_colors.xml20
-rw-r--r--services/Android.mk7
-rw-r--r--services/accessibility/Android.mk2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java25
-rw-r--r--services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java7
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java3
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java32
-rw-r--r--services/core/Android.mk4
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java317
-rw-r--r--services/core/java/com/android/server/AppOpsPolicy.java441
-rw-r--r--services/core/java/com/android/server/AppOpsService.java526
-rw-r--r--services/core/java/com/android/server/AssetAtlasService.java5
-rw-r--r--services/core/java/com/android/server/BasePermissionDialog.java84
-rw-r--r--services/core/java/com/android/server/BatteryService.java560
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java325
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java51
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java8
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags7
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java100
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java148
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java48
-rw-r--r--services/core/java/com/android/server/LockSettingsStorage.java19
-rw-r--r--services/core/java/com/android/server/LockSettingsStrongAuth.java12
-rw-r--r--services/core/java/com/android/server/MasterClearReceiver.java6
-rw-r--r--services/core/java/com/android/server/MountService.java36
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java34
-rw-r--r--services/core/java/com/android/server/PermissionDialog.java141
-rw-r--r--services/core/java/com/android/server/PermissionDialogReqQueue.java82
-rw-r--r--services/core/java/com/android/server/SystemConfig.java45
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java17
-rw-r--r--services/core/java/com/android/server/Watchdog.java42
-rw-r--r--services/core/java/com/android/server/WiredAccessoryManager.java41
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java8
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java69
-rwxr-xr-x[-rw-r--r--]services/core/java/com/android/server/am/ActivityManagerService.java497
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java95
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java70
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java114
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java13
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags2
-rw-r--r--services/core/java/com/android/server/am/LockTaskNotify.java28
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java121
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java24
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java365
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java79
-rw-r--r--services/core/java/com/android/server/connectivity/Nat464Xlat.java17
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java268
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java78
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java38
-rw-r--r--services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java163
-rw-r--r--services/core/java/com/android/server/display/LiveDisplayController.java616
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java4
-rw-r--r--services/core/java/com/android/server/display/WifiDisplayController.java35
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java89
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java20
-rw-r--r--services/core/java/com/android/server/gesture/GestureInputFilter.java333
-rw-r--r--services/core/java/com/android/server/gesture/GestureService.java63
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java221
-rw-r--r--services/core/java/com/android/server/lights/Light.java2
-rw-r--r--services/core/java/com/android/server/lights/LightsManager.java4
-rw-r--r--services/core/java/com/android/server/lights/LightsService.java31
-rw-r--r--services/core/java/com/android/server/location/GeoFencerBase.java147
-rw-r--r--services/core/java/com/android/server/location/GeoFencerProxy.java149
-rw-r--r--services/core/java/com/android/server/location/GpsLocationProvider.java36
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java182
-rw-r--r--services/core/java/com/android/server/net/NetPluginDelegate.java101
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java47
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java2
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java519
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java33
-rw-r--r--services/core/java/com/android/server/pm/BasePermission.java2
-rw-r--r--services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java36
-rw-r--r--services/core/java/com/android/server/pm/Installer.java41
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java1261
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java38
-rwxr-xr-x[-rw-r--r--]services/core/java/com/android/server/pm/Settings.java349
-rw-r--r--services/core/java/com/android/server/policy/BarController.java3
-rw-r--r--services/core/java/com/android/server/policy/GlobalActions.java367
-rw-r--r--services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java3
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java1192
-rw-r--r--services/core/java/com/android/server/policy/PolicyControl.java4
-rw-r--r--services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java10
-rw-r--r--services/core/java/com/android/server/policy/WindowOrientationListener.java7
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java16
-rw-r--r--services/core/java/com/android/server/power/Notifier.java35
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java455
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java327
-rw-r--r--services/core/java/com/android/server/tv/TvInputHal.java2
-rw-r--r--services/core/java/com/android/server/twilight/TwilightService.java7
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java323
-rw-r--r--services/core/java/com/android/server/wm/BlurLayer.java313
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java29
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java28
-rw-r--r--services/core/java/com/android/server/wm/Session.java28
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java98
-rw-r--r--services/core/java/com/android/server/wm/Watermark.java52
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java145
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java148
-rw-r--r--services/core/jni/Android.mk7
-rw-r--r--services/core/jni/com_android_server_AlarmManagerService.cpp85
-rw-r--r--services/core/jni/com_android_server_PersistentDataBlockService.cpp21
-rw-r--r--services/core/jni/com_android_server_SystemServer.cpp16
-rw-r--r--services/core/jni/com_android_server_UsbMidiDevice.cpp22
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp62
-rw-r--r--services/core/jni/com_android_server_lights_LightsService.cpp24
-rw-r--r--services/core/jni/com_android_server_location_GpsLocationProvider.cpp9
-rw-r--r--services/core/jni/com_android_server_power_PowerManagerService.cpp18
-rw-r--r--services/core/jni/com_android_server_tv_TvInputHal.cpp85
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java32
-rw-r--r--services/java/com/android/server/SystemServer.java87
-rw-r--r--services/libtvextensions/Android.mk21
-rw-r--r--services/libtvextensions/common/ExtensionsLoader.hpp91
-rw-r--r--services/libtvextensions/common/TvInputHalExtensionsCommon.h69
-rw-r--r--services/libtvextensions/jni/BufferProducerThread.h89
-rw-r--r--services/libtvextensions/jni/TvInputHalExtensions.h54
-rw-r--r--services/libtvextensions/jni/TvInputHalFactory.cpp56
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java66
-rw-r--r--services/usb/Android.mk2
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaManager.java2
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java159
-rw-r--r--services/usb/java/com/android/server/usb/UsbSettingsManager.java2
-rw-r--r--telecomm/java/android/telecom/Call.java163
-rw-r--r--telecomm/java/android/telecom/Conference.java52
-rw-r--r--telecomm/java/android/telecom/Connection.java196
-rw-r--r--telecomm/java/android/telecom/ConnectionRequest.java5
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java116
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java21
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java15
-rw-r--r--telecomm/java/android/telecom/InCallAdapter.java20
-rw-r--r--telecomm/java/android/telecom/InCallService.java21
-rw-r--r--telecomm/java/android/telecom/ParcelableCall.java28
-rw-r--r--telecomm/java/android/telecom/ParcelableConference.java16
-rw-r--r--telecomm/java/android/telecom/ParcelableConnection.java12
-rw-r--r--telecomm/java/android/telecom/Phone.java18
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java38
-rw-r--r--telecomm/java/android/telecom/RemoteConference.java42
-rw-r--r--telecomm/java/android/telecom/RemoteConnection.java40
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java17
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java32
-rw-r--r--telecomm/java/android/telecom/VideoCallImpl.java22
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionService.aidl6
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl4
-rw-r--r--telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl4
-rw-r--r--telecomm/java/com/android/internal/telecom/IInCallService.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl10
-rw-r--r--telephony/java/android/telephony/DisconnectCause.java166
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java118
-rwxr-xr-x[-rw-r--r--]telephony/java/android/telephony/RadioAccessFamily.java24
-rw-r--r--telephony/java/android/telephony/ServiceState.java19
-rw-r--r--telephony/java/android/telephony/SignalStrength.java35
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java22
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java88
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java118
-rw-r--r--telephony/java/com/android/ims/ImsCallForwardInfo.java5
-rw-r--r--telephony/java/com/android/ims/ImsCallProfile.java1
-rw-r--r--telephony/java/com/android/ims/ImsReasonInfo.java23
-rw-r--r--telephony/java/com/android/ims/ImsStreamMediaProfile.java12
-rw-r--r--telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl29
-rw-r--r--telephony/java/com/android/ims/internal/IImsUt.aidl5
-rw-r--r--telephony/java/com/android/internal/telephony/CallerInfo.java2
-rw-r--r--telephony/java/com/android/internal/telephony/IExtTelephony.aidl126
-rw-r--r--telephony/java/com/android/internal/telephony/ISms.aidl107
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl8
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl117
-rw-r--r--telephony/java/com/android/internal/telephony/OperatorInfo.java17
-rwxr-xr-x[-rw-r--r--]telephony/java/com/android/internal/telephony/PhoneConstants.java3
-rwxr-xr-x[-rw-r--r--]telephony/java/com/android/internal/telephony/RILConstants.java5
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java45
-rw-r--r--test-runner/src/android/test/mock/MockContext.java19
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java53
-rwxr-xr-xtests/ThemeTests/cm11_to_cm12/downgrade_to_cm11.sh34
-rw-r--r--tools/aapt/AaptAssets.cpp151
-rw-r--r--tools/aapt/AaptAssets.h21
-rw-r--r--tools/aapt/AaptConfig.cpp11
-rw-r--r--tools/aapt/Android.mk25
-rw-r--r--tools/aapt/Bundle.h17
-rw-r--r--tools/aapt/Command.cpp33
-rw-r--r--tools/aapt/Images.cpp105
-rw-r--r--tools/aapt/Images.h16
-rw-r--r--tools/aapt/Main.cpp47
-rw-r--r--tools/aapt/Main.h9
-rw-r--r--tools/aapt/Package.cpp306
-rw-r--r--tools/aapt/Resource.cpp28
-rw-r--r--tools/aapt/ResourceTable.cpp30
-rw-r--r--tools/aapt/ResourceTable.h3
-rw-r--r--tools/aapt/StringPool.cpp31
-rw-r--r--tools/aapt/StringPool.h3
-rw-r--r--tools/aapt/XMLNode.cpp43
-rw-r--r--tools/aapt/XMLNode.h3
-rw-r--r--tools/aapt/ZipFile.cpp65
-rw-r--r--tools/aapt/ZipFile.h1
-rw-r--r--tools/aapt/tests/ZipReading_test.cpp156
-rw-r--r--tools/aapt/tests/mocks/MockZipEntry.h29
-rw-r--r--tools/aapt/tests/mocks/MockZipFile.h29
-rw-r--r--tools/aidl/aidl.cpp23
-rw-r--r--tools/aidl/aidl_language.h1
-rw-r--r--tools/aidl/generate_java_binder.cpp6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java5
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java16
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java2
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl2
-rw-r--r--wifi/java/android/net/wifi/WifiChannel.java5
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java72
-rwxr-xr-xwifi/java/android/net/wifi/WifiDevice.aidl32
-rwxr-xr-xwifi/java/android/net/wifi/WifiDevice.java137
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java31
1612 files changed, 94893 insertions, 5120 deletions
diff --git a/Android.mk b/Android.mk
index 99e0c46..e7a6038 100644
--- a/Android.mk
+++ b/Android.mk
@@ -72,6 +72,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IAppTask.aidl \
core/java/android/app/ITaskStackListener.aidl \
core/java/android/app/IBackupAgent.aidl \
+ core/java/android/app/IBatteryService.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
core/java/android/app/INotificationManager.aidl \
core/java/android/app/IProcessObserver.aidl \
@@ -103,7 +104,6 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothA2dpSink.aidl \
core/java/android/bluetooth/IBluetoothAvrcpController.aidl \
core/java/android/bluetooth/IBluetoothCallback.aidl \
- core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl \
core/java/android/bluetooth/IBluetoothHeadset.aidl \
core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \
core/java/android/bluetooth/IBluetoothHealth.aidl \
@@ -117,9 +117,12 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothSap.aidl \
core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \
+ core/java/android/bluetooth/IBluetoothHidDevice.aidl \
+ core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl \
core/java/android/bluetooth/IBluetoothGatt.aidl \
core/java/android/bluetooth/IBluetoothGattCallback.aidl \
core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \
+ core/java/android/bluetooth/IBluetoothDun.aidl \
core/java/android/content/IClipboard.aidl \
core/java/android/content/IContentService.aidl \
core/java/android/content/IIntentReceiver.aidl \
@@ -247,6 +250,7 @@ LOCAL_SRC_FILES += \
core/java/android/service/voice/IVoiceInteractionService.aidl \
core/java/android/service/voice/IVoiceInteractionSession.aidl \
core/java/android/service/voice/IVoiceInteractionSessionService.aidl \
+ core/java/android/service/gesture/IGestureService.aidl \
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
core/java/android/service/wallpaper/IWallpaperEngine.aidl \
core/java/android/service/wallpaper/IWallpaperService.aidl \
@@ -322,6 +326,8 @@ LOCAL_SRC_FILES += \
location/java/android/location/IGeofenceProvider.aidl \
location/java/android/location/IGpsMeasurementsListener.aidl \
location/java/android/location/IGpsNavigationMessageListener.aidl \
+ location/java/android/location/IGeoFencer.aidl \
+ location/java/android/location/IGeoFenceListener.aidl \
location/java/android/location/IGpsStatusListener.aidl \
location/java/android/location/IGpsStatusProvider.aidl \
location/java/android/location/ILocationListener.aidl \
@@ -405,6 +411,7 @@ LOCAL_SRC_FILES += \
telephony/java/com/android/internal/telephony/ITelephony.aidl \
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
+ telephony/java/com/android/internal/telephony/IExtTelephony.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
@@ -413,6 +420,7 @@ LOCAL_SRC_FILES += \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
packages/services/Proxy/com/android/net/IProxyCallback.aidl \
packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
+ ../../vendor/cmsdk/src/java/org/cyanogenmod/internal/themes/IIconCacheManager.aidl \
# FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
@@ -565,6 +573,7 @@ aidl_files := \
frameworks/base/core/java/android/app/usage/UsageEvents.aidl \
frameworks/base/core/java/android/app/Notification.aidl \
frameworks/base/core/java/android/app/NotificationManager.aidl \
+ frameworks/base/core/java/android/app/NotificationGroup.aidl \
frameworks/base/core/java/android/app/WallpaperInfo.aidl \
frameworks/base/core/java/android/app/AppOpsManager.aidl \
frameworks/base/core/java/android/app/ActivityManager.aidl \
@@ -1033,7 +1042,7 @@ LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=docs/html-ndk
+LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
# specify a second html input dir and an output path relative to OUT_DIR)
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 48be749..fe7284e 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -239,3 +239,12 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
+
+# clean steps for aapt
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/$(HOST_PREBUILT_TAG)/bin/aapt)
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/$(HOST_PREBUILT_TAG)/obj32/EXECUTABLES/aapt_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/$(HOST_PREBUILT_TAG)/bin/libaapt_tests)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/aapt_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/aapt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/bin/aapt)
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/$(HOST_PREBUILT_TAG)/obj32/STATIC_LIBRARIES/libaapt_intermediates)
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 2ee586f..0c05ded 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -23,7 +23,28 @@ LOCAL_SHARED_LIBRARIES := \
libEGL \
libGLESv1_CM \
libgui \
- libtinyalsa
+ libtinyalsa \
+ libmedia
+
+ifeq ($(TARGET_CONTINUOUS_SPLASH_ENABLED),true)
+ LOCAL_CFLAGS += -DCONTINUOUS_SPLASH
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_PRELOAD),true)
+ LOCAL_CFLAGS += -DPRELOAD_BOOTANIMATION
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_TEXTURE_CACHE),true)
+ LOCAL_CFLAGS += -DNO_TEXTURE_CACHE=0
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_TEXTURE_CACHE),false)
+ LOCAL_CFLAGS += -DNO_TEXTURE_CACHE=1
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_USE_RGB565),true)
+ LOCAL_CFLAGS += -DUSE_565
+endif
LOCAL_MODULE:= bootanimation
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 8f361ce..4e7c9c4 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +25,8 @@
#include <utils/misc.h>
#include <signal.h>
#include <time.h>
+#include <pthread.h>
+#include <sys/select.h>
#include <cutils/properties.h>
@@ -54,12 +57,28 @@
#include <GLES/glext.h>
#include <EGL/eglext.h>
+#include <media/AudioSystem.h>
+#include <media/mediaplayer.h>
+#include <media/IMediaHTTPService.h>
+
#include "BootAnimation.h"
#include "AudioPlayer.h"
#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip"
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
+#define THEME_BOOTANIMATION_FILE "/data/system/theme/bootanimation.zip"
+
+#define OEM_SHUTDOWN_ANIMATION_FILE "/oem/media/shutdownanimation.zip"
+#define SYSTEM_SHUTDOWN_ANIMATION_FILE "/system/media/shutdownanimation.zip"
+#define SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE "/system/media/shutdownanimation-encrypted.zip"
+
+#define OEM_BOOT_MUSIC_FILE "/oem/media/boot.wav"
+#define SYSTEM_BOOT_MUSIC_FILE "/system/media/boot.wav"
+
+#define OEM_SHUTDOWN_MUSIC_FILE "/oem/media/shutdown.wav"
+#define SYSTEM_SHUTDOWN_MUSIC_FILE "/system/media/shutdown.wav"
+
#define EXIT_PROP_NAME "service.bootanim.exit"
namespace android {
@@ -68,6 +87,87 @@ static const int ANIM_ENTRY_NAME_MAX = 256;
// ---------------------------------------------------------------------------
+static pthread_mutex_t mp_lock;
+static pthread_cond_t mp_cond;
+static bool isMPlayerPrepared = false;
+static bool isMPlayerCompleted = false;
+
+class MPlayerListener : public MediaPlayerListener
+{
+ void notify(int msg, int /*ext1*/, int /*ext2*/, const Parcel * /*obj*/)
+ {
+ switch (msg) {
+ case MEDIA_NOP: // interface test message
+ break;
+ case MEDIA_PREPARED:
+ pthread_mutex_lock(&mp_lock);
+ isMPlayerPrepared = true;
+ pthread_cond_signal(&mp_cond);
+ pthread_mutex_unlock(&mp_lock);
+ break;
+ case MEDIA_PLAYBACK_COMPLETE:
+ pthread_mutex_lock(&mp_lock);
+ isMPlayerCompleted = true;
+ pthread_cond_signal(&mp_cond);
+ pthread_mutex_unlock(&mp_lock);
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+static unsigned long getFreeMemory(void)
+{
+ int fd = open("/proc/meminfo", O_RDONLY);
+ const char* const sums[] = { "MemFree:", "Cached:", NULL };
+ const size_t sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), 0 };
+ unsigned int num = 2;
+
+ if (fd < 0) {
+ ALOGW("Unable to open /proc/meminfo");
+ return -1;
+ }
+
+ char buffer[256];
+ const int len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0) {
+ ALOGW("Unable to read /proc/meminfo");
+ return -1;
+ }
+ buffer[len] = 0;
+
+ size_t numFound = 0;
+ unsigned long mem = 0;
+
+ char* p = buffer;
+ while (*p && numFound < num) {
+ int i = 0;
+ while (sums[i]) {
+ if (strncmp(p, sums[i], sumsLen[i]) == 0) {
+ p += sumsLen[i];
+ while (*p == ' ') p++;
+ char* num = p;
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p != 0) {
+ *p = 0;
+ p++;
+ if (*p == 0) p--;
+ }
+ mem += atoll(num);
+ numFound++;
+ break;
+ }
+ i++;
+ }
+ p++;
+ }
+
+ return numFound > 0 ? mem : -1;
+}
+
BootAnimation::BootAnimation() : Thread(false), mZip(NULL)
{
mSession = new SurfaceComposerClient();
@@ -171,16 +271,15 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
if (codec != NULL) {
codec->setDitherImage(false);
codec->decode(&stream, &bitmap,
+ #ifdef USE_565
+ kRGB_565_SkColorType,
+ #else
kN32_SkColorType,
+ #endif
SkImageDecoder::kDecodePixels_Mode);
delete codec;
}
- // FileMap memory is never released until application exit.
- // Release it now as the texture is already loaded and the memory used for
- // the packed resource can be released.
- delete frame.map;
-
// ensure we can call getPixels(). No need to call unlock, since the
// bitmap will go out of scope when we return from this method.
bitmap.lockPixels();
@@ -237,6 +336,18 @@ status_t BootAnimation::readyToRun() {
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
if (status)
return -1;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.panel.orientation", value, "0");
+ int orient = atoi(value) / 90;
+
+ if(orient == eOrientation90 || orient == eOrientation270) {
+ int temp = dinfo.h;
+ dinfo.h = dinfo.w;
+ dinfo.w = temp;
+ }
+
+ Rect destRect(dinfo.w, dinfo.h);
+ mSession->setDisplayProjection(dtoken, orient, destRect, destRect);
// create the native surface
sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
@@ -287,21 +398,63 @@ status_t BootAnimation::readyToRun() {
char decrypt[PROPERTY_VALUE_MAX];
property_get("vold.decrypt", decrypt, "");
+ // Use customized resources for boot and showdown animation
+ // instead of system predefined boot animation files.
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
ZipFileRO* zipFile = NULL;
if ((encryptedAnimation &&
- (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
- ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) ||
+ (access(getAnimationFileName(IMG_ENC), R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_ENC))) != NULL)) ||
+
+ ((access(THEME_BOOTANIMATION_FILE, R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(THEME_BOOTANIMATION_FILE)) != NULL)) ||
((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) ||
((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
- ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) {
+ ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL)) ||
+
+ ((access(getAnimationFileName(IMG_DATA), R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_DATA))) != NULL)) ||
+
+ ((access(getAnimationFileName(IMG_SYS), R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_SYS))) != NULL))) {
mZip = zipFile;
}
+#ifdef PRELOAD_BOOTANIMATION
+ // Preload the bootanimation zip on memory, so we don't stutter
+ // when showing the animation
+ FILE* fd;
+ if (encryptedAnimation && access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)
+ fd = fopen(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, "r");
+ else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0)
+ fd = fopen(OEM_BOOTANIMATION_FILE, "r");
+ else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0)
+ fd = fopen(SYSTEM_BOOTANIMATION_FILE, "r");
+ else
+ return NO_ERROR;
+
+ if (fd != NULL) {
+ // We could use readahead..
+ // ... if bionic supported it :(
+ //readahead(fd, 0, INT_MAX);
+ void *crappyBuffer = malloc(2*1024*1024);
+ if (crappyBuffer != NULL) {
+ // Read all the zip
+ while (!feof(fd))
+ fread(crappyBuffer, 1024, 2*1024, fd);
+
+ free(crappyBuffer);
+ } else {
+ ALOGW("Unable to allocate memory to preload the animation");
+ }
+ fclose(fd);
+ }
+#endif
+
return NO_ERROR;
}
@@ -452,6 +605,7 @@ bool BootAnimation::readFile(const char* name, String8& outString)
bool BootAnimation::movie()
{
+ char value[PROPERTY_VALUE_MAX];
String8 desString;
if (!readFile("desc.txt", desString)) {
@@ -556,11 +710,14 @@ bool BootAnimation::movie()
mZip->endIteration(cookie);
+#ifndef CONTINUOUS_SPLASH
glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
+#endif
+
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
@@ -576,11 +733,45 @@ bool BootAnimation::movie()
Region clearReg(Rect(mWidth, mHeight));
clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));
+ pthread_mutex_init(&mp_lock, NULL);
+ pthread_condattr_t attr;
+ pthread_condattr_init(&attr);
+ pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+ pthread_cond_init(&mp_cond, &attr);
+
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
+
+ // can be 1, 0, or not set
+ #ifdef NO_TEXTURE_CACHE
+ const int noTextureCache = NO_TEXTURE_CACHE;
+ #else
+ const int noTextureCache =
+ ((animation.width * animation.height * fcount) > 48 * 1024 * 1024) ? 1 : 0;
+ #endif
+
glBindTexture(GL_TEXTURE_2D, 0);
+ /*calculate if we need to runtime save memory
+ * condition: runtime free memory is less than the textures that will used.
+ * needSaveMem default to be false
+ */
+ GLint mMaxTextureSize;
+ bool needSaveMem = false;
+ GLuint mTextureid;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+ //ALOGD("freemem:%ld, %d", getFreeMemory(), mMaxTextureSize);
+ if(getFreeMemory() < mMaxTextureSize * mMaxTextureSize * fcount / 1024 || noTextureCache) {
+ ALOGD("Use save memory method, maybe small fps in actual.");
+ needSaveMem = true;
+ glGenTextures(1, &mTextureid);
+ glBindTexture(GL_TEXTURE_2D, mTextureid);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ }
+
for (int r=0 ; !part.count || r<part.count ; r++) {
// Exit any non playuntil complete parts immediately
if(exitPending() && !part.playUntilComplete)
@@ -601,10 +792,10 @@ bool BootAnimation::movie()
const Animation::Frame& frame(part.frames[j]);
nsecs_t lastFrame = systemTime();
- if (r > 0) {
+ if (r > 0 && !needSaveMem) {
glBindTexture(GL_TEXTURE_2D, frame.tid);
} else {
- if (part.count != 1) {
+ if (!needSaveMem && part.count != 1) {
glGenTextures(1, &frame.tid);
glBindTexture(GL_TEXTURE_2D, frame.tid);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -657,18 +848,175 @@ bool BootAnimation::movie()
}
// free the textures for this part
- if (part.count != 1) {
+ if (!needSaveMem && part.count != 1) {
for (size_t j=0 ; j<fcount ; j++) {
const Animation::Frame& frame(part.frames[j]);
glDeleteTextures(1, &frame.tid);
}
}
+
+ if (needSaveMem) {
+ glDeleteTextures(1, &mTextureid);
+ }
+
+ }
+
+ property_get("persist.sys.silent", value, "null");
+ if (strncmp(value, "1", 1) != 0) {
+ ALOGD("playing boot audio here");
+ playBackgroundMusic();
+ }
+
+ if (isMPlayerPrepared) {
+ ALOGD("waiting for media player to complete.");
+ struct timespec timeout;
+ clock_gettime(CLOCK_MONOTONIC, &timeout);
+ timeout.tv_sec += 5; //timeout after 5s.
+
+ pthread_mutex_lock(&mp_lock);
+ while (!isMPlayerCompleted) {
+ int err = pthread_cond_timedwait(&mp_cond, &mp_lock, &timeout);
+ if (err == ETIMEDOUT) {
+ break;
+ }
+ }
+ pthread_mutex_unlock(&mp_lock);
+ ALOGD("media player is completed.");
}
+ pthread_cond_destroy(&mp_cond);
+ pthread_mutex_destroy(&mp_lock);
+
return false;
}
-// ---------------------------------------------------------------------------
+const char *BootAnimation::getAnimationFileName(ImageID image)
+{
+ const char *fileName[2][3] = { { OEM_BOOTANIMATION_FILE,
+ SYSTEM_BOOTANIMATION_FILE,
+ SYSTEM_ENCRYPTED_BOOTANIMATION_FILE }, {
+ OEM_SHUTDOWN_ANIMATION_FILE,
+ SYSTEM_SHUTDOWN_ANIMATION_FILE,
+ SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE} };
+ int state;
+ char sku[PROPERTY_VALUE_MAX];
+ char skusuffix[PATH_MAX];
+
+ state = checkBootState() ? 0 : 1;
+
+ property_get("ro.prebundled.mcc", sku, "000");
+ sprintf(skusuffix,"-%s",sku);
+
+ String16 skuPath(fileName[state][image]);
+ skuPath.insert(skuPath.size()-4,String16(skusuffix));
+
+ if (access(String8(skuPath).string(), R_OK) == 0)
+ return (char *)String8(skuPath).string();
+
+ return fileName[state][image];
+}
+
+const char *BootAnimation::getBootRingtoneFileName(ImageID image)
+{
+ if (image == IMG_ENC) {
+ return NULL;
+ }
+
+ const char *fileName[2][2] = { { OEM_BOOT_MUSIC_FILE,
+ SYSTEM_BOOT_MUSIC_FILE }, {
+ OEM_SHUTDOWN_MUSIC_FILE,
+ SYSTEM_SHUTDOWN_MUSIC_FILE } };
+ int state;
+
+ state = checkBootState() ? 0 : 1;
+
+ return fileName[state][image];
+}
+
+static void* playMusic(void* arg)
+{
+ int index = 0;
+ char *fileName = (char *)arg;
+ sp<MediaPlayer> mp = new MediaPlayer();
+ sp<MPlayerListener> mListener = new MPlayerListener();
+ if (mp != NULL) {
+ ALOGD("starting to play %s", fileName);
+ mp->setListener(mListener);
+
+ if (mp->setDataSource(NULL, fileName, NULL) == NO_ERROR) {
+ mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
+ mp->prepare();
+ } else {
+ ALOGE("failed to setDataSource for %s", fileName);
+ return NULL;
+ }
+
+ //waiting for media player is prepared.
+ pthread_mutex_lock(&mp_lock);
+ while (!isMPlayerPrepared) {
+ pthread_cond_wait(&mp_cond, &mp_lock);
+ }
+ pthread_mutex_unlock(&mp_lock);
+
+ audio_devices_t device = AudioSystem::getDevicesForStream(AUDIO_STREAM_ENFORCED_AUDIBLE);
+ AudioSystem::initStreamVolume(AUDIO_STREAM_ENFORCED_AUDIBLE,0,7);
+ AudioSystem::setStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, 7, device);
+
+ AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, &index, device);
+ if (index != 0) {
+ ALOGD("playing %s", fileName);
+ mp->seekTo(0);
+ mp->start();
+ } else {
+ ALOGW("current volume is zero.");
+ }
+ }
+ return NULL;
+}
+
+void BootAnimation::playBackgroundMusic(void)
+{
+ //Shutdown music is playing in ShutdownThread.java
+ if (!checkBootState()) {
+ return;
+ }
+
+ /* Make sure sound cards are populated */
+ FILE* fp = NULL;
+ if ((fp = fopen("/proc/asound/cards", "r")) == NULL) {
+ ALOGW("Cannot open /proc/asound/cards file to get sound card info.");
+ }
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("qcom.audio.init", value, "null");
+ if (strncmp(value, "complete", 8) != 0) {
+ ALOGW("Audio service is not initiated.");
+ }
+ fclose(fp);
+
+ const char *fileName;
+ if (((fileName = getBootRingtoneFileName(IMG_DATA)) != NULL && access(fileName, R_OK) == 0) ||
+ ((fileName = getBootRingtoneFileName(IMG_SYS)) != NULL
+ && access(fileName, R_OK) == 0)) {
+ pthread_t tid;
+ pthread_create(&tid, NULL, playMusic, (void *)fileName);
+ pthread_join(tid, NULL);
+ }
}
-; // namespace android
+bool BootAnimation::checkBootState(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+ bool ret = true;
+
+ property_get("sys.shutdown.requested", value, "null");
+ if (strncmp(value, "null", 4) != 0) {
+ ret = false;
+ }
+
+ return ret;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f968b25..5bc1e8a 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -40,6 +40,12 @@ class SurfaceControl;
class BootAnimation : public Thread, public IBinder::DeathRecipient
{
public:
+ enum {
+ eOrientationDefault = 0,
+ eOrientation90 = 1,
+ eOrientation180 = 2,
+ eOrientation270 = 3,
+ };
BootAnimation();
virtual ~BootAnimation();
@@ -87,12 +93,18 @@ private:
bool readFile(const char* name, String8& outString);
bool movie();
+ enum ImageID { IMG_DATA = 0, IMG_SYS = 1, IMG_ENC = 2 };
+ const char *getAnimationFileName(ImageID image);
+ const char *getBootRingtoneFileName(ImageID image);
+ void playBackgroundMusic();
+ bool checkBootState();
void checkExit();
+ void checkShowAndroid();
sp<SurfaceComposerClient> mSession;
sp<AudioPlayer> mAudioPlayer;
AssetManager mAssets;
- Texture mAndroid[2];
+ Texture mAndroid[3];
int mWidth;
int mHeight;
EGLDisplay mDisplay;
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index 48a34e7..50e4b1f 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -38,8 +38,9 @@ int main()
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
ALOGI_IF(noBootAnimation, "boot animation disabled");
- if (!noBootAnimation) {
+ property_get("ro.alarm_boot", value, "false");
+ if (!noBootAnimation && strcmp(value, "true")) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index c0ed893..1d8b8b1 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -103,10 +103,12 @@ public class Content {
+ "--where \"name=\'new_setting\'\"\n"
+ "\n"
+ "usage: adb shell content query --uri <URI> [--user <USER_ID>]"
- + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
+ + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>] "
+ + " [--show-type <SHOW-TYPE>] \n"
+ " <PROJECTION> is a list of colon separated column names and is formatted:\n"
+ " <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
+ " <SORT_ORDER> is the order in which rows in the result should be sorted.\n"
+ + " <SHOW-TYPE> if true shows the type of value of each projection column"
+ " Example:\n"
+ " # Select \"name\" and \"value\" columns from secure settings where \"name\" is "
+ "equal to \"new_setting\" and sort the result by name in ascending order.\n"
@@ -142,6 +144,7 @@ public class Content {
private static final String ARGUMENT_METHOD = "--method";
private static final String ARGUMENT_ARG = "--arg";
private static final String ARGUMENT_EXTRA = "--extra";
+ private static final String ARGUMENT_SHOW_TYPE = "--show-type";
private static final String TYPE_BOOLEAN = "b";
private static final String TYPE_STRING = "s";
private static final String TYPE_INTEGER = "i";
@@ -316,6 +319,7 @@ public class Content {
String[] projection = null;
String sort = null;
String where = null;
+ boolean showType = false;
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
@@ -327,6 +331,8 @@ public class Content {
sort = argumentValueRequired(argument);
} else if (ARGUMENT_PROJECTION.equals(argument)) {
projection = argumentValueRequired(argument).split("[\\s]*:[\\s]*");
+ } else if (ARGUMENT_SHOW_TYPE.equals(argument)) {
+ showType = argumentValueRequiredForBoolean(argument);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
@@ -335,7 +341,7 @@ public class Content {
throw new IllegalArgumentException("Content provider URI not specified."
+ " Did you specify --uri argument?");
}
- return new QueryCommand(uri, userId, projection, where, sort);
+ return new QueryCommand(uri, userId, projection, where, sort, showType);
}
private void parseBindValue(ContentValues values) {
@@ -367,6 +373,14 @@ public class Content {
}
}
+ private boolean argumentValueRequiredForBoolean(String argument) {
+ String value = mTokenizer.nextArg();
+ if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) {
+ throw new IllegalArgumentException("No value for argument: " + argument);
+ }
+ return value.equals("true");
+ }
+
private String argumentValueRequired(String argument) {
String value = mTokenizer.nextArg();
if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) {
@@ -539,12 +553,15 @@ public class Content {
private static class QueryCommand extends DeleteCommand {
final String[] mProjection;
final String mSortOrder;
+ final boolean mShowType;
public QueryCommand(
- Uri uri, int userId, String[] projection, String where, String sortOrder) {
+ Uri uri, int userId, String[] projection, String where, String sortOrder,
+ boolean showType) {
super(uri, userId, where);
mProjection = projection;
mSortOrder = sortOrder;
+ mShowType = showType;
}
@Override
@@ -590,6 +607,7 @@ public class Content {
break;
}
builder.append(columnName).append("=").append(columnValue);
+ if (mShowType) builder.append(", type=").append(type);
}
System.out.println(builder);
} while (cursor.moveToNext());
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
index 41395f1..dd0554e 100644
--- a/cmds/idmap/create.cpp
+++ b/cmds/idmap/create.cpp
@@ -33,6 +33,7 @@ namespace {
int open_idmap(const char *path)
{
int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644));
+ bool needUnlink = true;
if (fd == -1) {
ALOGD("error: open %s: %s\n", path, strerror(errno));
goto fail;
@@ -41,8 +42,10 @@ namespace {
ALOGD("error: fchmod %s: %s\n", path, strerror(errno));
goto fail;
}
- if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) {
+ if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX)) != 0) {
ALOGD("error: flock %s: %s\n", path, strerror(errno));
+ // If the file is locked by another process, then we needn't unlink the file.
+ needUnlink = false;
goto fail;
}
@@ -50,7 +53,7 @@ namespace {
fail:
if (fd != -1) {
close(fd);
- unlink(path);
+ if (needUnlink) unlink(path);
}
return -1;
}
@@ -150,26 +153,26 @@ fail:
}
int create_idmap(const char *target_apk_path, const char *overlay_apk_path,
- uint32_t **data, size_t *size)
+ const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, uint32_t **data,
+ size_t *size)
{
uint32_t target_crc, overlay_crc;
- if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
- &target_crc) == -1) {
- return -1;
- }
- if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
- &overlay_crc) == -1) {
- return -1;
- }
+
+ // In the original implementation, crc of the res tables are generated
+ // theme apks however do not need a restable, everything is in assets/
+ // instead timestamps are used
+ target_crc = 0;
+ overlay_crc = 0;
AssetManager am;
- bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc,
- data, size);
+ bool b = am.createIdmap(target_apk_path, overlay_apk_path, cache_path, target_crc,
+ overlay_crc, target_hash, overlay_hash, data, size);
return b ? 0 : -1;
}
int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path,
- int fd, bool check_if_stale)
+ const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, int fd,
+ bool check_if_stale)
{
if (check_if_stale) {
if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) {
@@ -181,7 +184,8 @@ fail:
uint32_t *data = NULL;
size_t size;
- if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) {
+ if (create_idmap(target_apk_path, overlay_apk_path, cache_path, target_hash, overlay_hash,
+ &data, &size) == -1) {
return -1;
}
@@ -196,6 +200,7 @@ fail:
}
int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
+ const char *cache_path, uint32_t target_hash, uint32_t overlay_hash,
const char *idmap_path)
{
if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) {
@@ -208,7 +213,8 @@ int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
return EXIT_FAILURE;
}
- int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false);
+ int r = create_and_write_idmap(target_apk_path, overlay_apk_path, cache_path,
+ target_hash, overlay_hash, fd, false);
close(fd);
if (r != 0) {
unlink(idmap_path);
@@ -216,8 +222,10 @@ int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
-int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd)
+int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path,
+ const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, int fd)
{
- return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ?
+ return create_and_write_idmap(target_apk_path, overlay_apk_path, cache_path, target_hash,
+ overlay_hash, fd, true) == 0 ?
EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp
index 90cfa2c..cc3f231 100644
--- a/cmds/idmap/idmap.cpp
+++ b/cmds/idmap/idmap.cpp
@@ -66,29 +66,31 @@ EXAMPLES \n\
Display an idmap file: \n\
\n\
$ adb shell idmap --inspect /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\
- SECTION ENTRY VALUE COMMENT \n\
- IDMAP HEADER magic 0x706d6469 \n\
- base crc 0xb65a383f \n\
- overlay crc 0x7b9675e8 \n\
- base path .......... /path/to/target.apk \n\
- overlay path .......... /path/to/overlay.apk \n\
- DATA HEADER target pkg 0x0000007f \n\
- types count 0x00000003 \n\
- DATA BLOCK target type 0x00000002 \n\
- overlay type 0x00000002 \n\
- entry count 0x00000001 \n\
- entry offset 0x00000000 \n\
- entry 0x00000000 drawable/drawable \n\
- DATA BLOCK target type 0x00000003 \n\
- overlay type 0x00000003 \n\
- entry count 0x00000001 \n\
- entry offset 0x00000000 \n\
- entry 0x00000000 xml/integer \n\
- DATA BLOCK target type 0x00000004 \n\
- overlay type 0x00000004 \n\
- entry count 0x00000001 \n\
- entry offset 0x00000000 \n\
- entry 0x00000000 raw/lorem_ipsum \n\
+ SECTION ENTRY VALUE COMMENT \n\
+ IDMAP HEADER magic 0x706d6469 \n\
+ base crc 0xb65a383f \n\
+ overlay crc 0x7b9675e8 \n\
+ base mtime 0x1eb47d51 \n\
+ overlay mtime 0x185f87a2 \n\
+ base path .......... /path/to/target.apk \n\
+ overlay path .......... /path/to/overlay.apk \n\
+ DATA HEADER target pkg 0x0000007f \n\
+ types count 0x00000003 \n\
+ DATA BLOCK target type 0x00000002 \n\
+ overlay type 0x00000002 \n\
+ entry count 0x00000001 \n\
+ entry offset 0x00000000 \n\
+ entry 0x00000000 drawable/drawable \n\
+ DATA BLOCK target type 0x00000003 \n\
+ overlay type 0x00000003 \n\
+ entry count 0x00000001 \n\
+ entry offset 0x00000000 \n\
+ entry 0x00000000 xml/integer \n\
+ DATA BLOCK target type 0x00000004 \n\
+ overlay type 0x00000004 \n\
+ entry count 0x00000001 \n\
+ entry offset 0x00000000 \n\
+ entry 0x00000000 raw/lorem_ipsum \n\
\n\
In this example, the overlay package provides three alternative resource values:\n\
drawable/drawable, xml/integer, and raw/lorem_ipsum \n\
@@ -120,7 +122,8 @@ NOTES \n\
}
int maybe_create_fd(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_str)
+ const char *cache_path, const char *idmap_str, const char *target_hash_str,
+ const char *overlay_hash_str)
{
// anyone (not just root or system) may do --fd -- the file has
// already been opened by someone else on our behalf
@@ -141,12 +144,16 @@ NOTES \n\
ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
return -1;
}
+ int target_hash = strtol(target_hash_str, 0, 10);
+ int overlay_hash = strtol(overlay_hash_str, 0, 10);
- return idmap_create_fd(target_apk_path, overlay_apk_path, idmap_fd);
+ return idmap_create_fd(target_apk_path, overlay_apk_path, cache_path, target_hash,
+ overlay_hash, idmap_fd);
}
int maybe_create_path(const char *target_apk_path, const char *overlay_apk_path,
- const char *idmap_path)
+ const char *cache_path, const char *idmap_path, const char *target_hash_str,
+ const char *overlay_hash_str)
{
if (!verify_root_or_system()) {
fprintf(stderr, "error: permission denied: not user root or user system\n");
@@ -163,7 +170,10 @@ NOTES \n\
return -1;
}
- return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path);
+ int target_hash = strtol(target_hash_str, 0, 10);
+ int overlay_hash = strtol(overlay_hash_str, 0, 10);
+ return idmap_create_path(target_apk_path, overlay_apk_path, cache_path, target_hash,
+ overlay_hash, idmap_path);
}
int maybe_scan(const char *overlay_dir, const char *target_package_name,
@@ -222,12 +232,12 @@ int main(int argc, char **argv)
return 0;
}
- if (argc == 5 && !strcmp(argv[1], "--fd")) {
- return maybe_create_fd(argv[2], argv[3], argv[4]);
+ if (argc == 8 && !strcmp(argv[1], "--fd")) {
+ return maybe_create_fd(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
}
- if (argc == 5 && !strcmp(argv[1], "--path")) {
- return maybe_create_path(argv[2], argv[3], argv[4]);
+ if (argc == 8 && !strcmp(argv[1], "--path")) {
+ return maybe_create_path(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
}
if (argc == 6 && !strcmp(argv[1], "--scan")) {
diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h
index f507dd8..6a9c5ef 100644
--- a/cmds/idmap/idmap.h
+++ b/cmds/idmap/idmap.h
@@ -19,9 +19,12 @@
#endif
int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
+ const char *cache_path, uint32_t target_hash, uint32_t overlay_hash,
const char *idmap_path);
-int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
+int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path,
+ const char *cache_path, uint32_t target_hash, uint32_t overlay_hash,
+ int fd);
// Regarding target_package_name: the idmap_scan implementation should
// be able to extract this from the manifest in target_apk_path,
diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
index f6afc85..3087e6e 100644
--- a/cmds/idmap/inspect.cpp
+++ b/cmds/idmap/inspect.cpp
@@ -200,6 +200,18 @@ namespace {
}
print("", "overlay crc", i, "");
+ err = buf.nextUint32(&i);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ print("", "base mtime", i, "");
+
+ err = buf.nextUint32(&i);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ print("", "overlay mtime", i, "");
+
err = buf.nextPath(path);
if (err != NO_ERROR) {
// printe done from IdmapBuffer::nextPath
@@ -223,7 +235,8 @@ namespace {
}
status_t parse_data(IdmapBuffer& buf, const AssetManager& am) {
- const uint32_t packageId = am.getResources().getBasePackageId(0);
+ const ResTable& rt = am.getResources();
+ const uint32_t packageId = rt.getBasePackageId(rt.getBasePackageCount() - 1);
uint16_t data16;
status_t err = buf.nextUint16(&data16);
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 612a7eb..b319e68 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -25,8 +25,7 @@ namespace {
bool operator<(Overlay const& rhs) const
{
- // Note: order is reversed by design
- return rhs.priority < priority;
+ return rhs.priority > priority;
}
String8 apk_path;
@@ -165,6 +164,62 @@ namespace {
delete dataMap;
return priority;
}
+
+ int idmap_scan(const char *overlay_dir, const char *target_package_name,
+ const char *target_apk_path, const char *idmap_dir,
+ SortedVector<Overlay>& overlayVector)
+ {
+ DIR *dir = opendir(overlay_dir);
+ if (dir == NULL) {
+ return EXIT_FAILURE;
+ }
+
+ struct dirent *dirent;
+ while ((dirent = readdir(dir)) != NULL) {
+ struct stat st;
+ char overlay_apk_path[PATH_MAX + 1];
+ snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
+ if (stat(overlay_apk_path, &st) < 0) {
+ continue;
+ }
+ if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ String8 dir_name = String8(overlay_apk_path).getPathLeaf();
+ if (dir_name == "." || dir_name == "..") {
+ // Skip the "." and ".." dir.
+ continue;
+ }
+ idmap_scan(overlay_apk_path, target_package_name, target_apk_path, idmap_dir,
+ overlayVector);
+ } else {
+ int priority = parse_apk(overlay_apk_path, target_package_name);
+ if (priority < 0) {
+ continue;
+ }
+
+ String8 idmap_path(idmap_dir);
+ idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
+ idmap_path.append("@idmap");
+
+ if (idmap_create_path(target_apk_path, overlay_apk_path, NULL, 0, 0,
+ idmap_path.string()) != 0) {
+ ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
+ target_apk_path, overlay_apk_path, idmap_path.string());
+ continue;
+ }
+
+ Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
+ overlayVector.add(overlay);
+ }
+ }
+
+ closedir(dir);
+
+ return EXIT_SUCCESS;
+ }
}
int idmap_scan(const char *overlay_dir, const char *target_package_name,
@@ -176,48 +231,13 @@ int idmap_scan(const char *overlay_dir, const char *target_package_name,
return EXIT_FAILURE;
}
- DIR *dir = opendir(overlay_dir);
- if (dir == NULL) {
- return EXIT_FAILURE;
- }
-
SortedVector<Overlay> overlayVector;
- struct dirent *dirent;
- while ((dirent = readdir(dir)) != NULL) {
- struct stat st;
- char overlay_apk_path[PATH_MAX + 1];
- snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
- if (stat(overlay_apk_path, &st) < 0) {
- continue;
- }
- if (!S_ISREG(st.st_mode)) {
- continue;
- }
-
- int priority = parse_apk(overlay_apk_path, target_package_name);
- if (priority < 0) {
- continue;
- }
-
- String8 idmap_path(idmap_dir);
- idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
- idmap_path.append("@idmap");
-
- if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
- ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
- target_apk_path, overlay_apk_path, idmap_path.string());
- continue;
- }
-
- Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
- overlayVector.add(overlay);
- }
-
- closedir(dir);
+ int res = idmap_scan(overlay_dir, target_package_name, target_apk_path, idmap_dir,
+ overlayVector);
- if (!writePackagesList(filename.string(), overlayVector)) {
+ if (res == EXIT_FAILURE || !writePackagesList(filename.string(), overlayVector)) {
return EXIT_FAILURE;
}
- return EXIT_SUCCESS;
+ return res;
}
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index 2a7c79b..40148c6 100644
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -47,6 +47,7 @@ public class Input {
put("touchpad", InputDevice.SOURCE_TOUCHPAD);
put("touchnavigation", InputDevice.SOURCE_TOUCH_NAVIGATION);
put("joystick", InputDevice.SOURCE_JOYSTICK);
+ put("gesture", InputDevice.SOURCE_GESTURE_SENSOR);
}};
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index d7f23cb..d185b56 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -222,6 +222,26 @@ public class Media extends BaseCommand {
System.out.println("onVolumeInfoChanged " + info);
}
+ @Override
+ public void onPlayItemResponse(boolean success) throws RemoteException {
+ System.out.println("onPlayItemResponse ");
+ }
+
+ @Override
+ public void onUpdateNowPlayingEntries(long[] playList) throws RemoteException {
+ System.out.println("onUpdateNowPlayingEntries ");
+ }
+
+ @Override
+ public void onUpdateFolderInfoBrowsedPlayer(String stringUri) throws RemoteException {
+ System.out.println("onUpdateFolderInfoBrowsedPlayer ");
+ }
+
+ @Override
+ public void onUpdateNowPlayingContentChange() throws RemoteException {
+ System.out.println("onUpdateNowPlayingContentChange ");
+ }
+
void printUsageMessage() {
try {
System.out.println("V2Monitoring session " + mController.getTag()
diff --git a/cmds/pm/pm b/cmds/pm/pm
index 8183838..53f85b2 100755
--- a/cmds/pm/pm
+++ b/cmds/pm/pm
@@ -1,3 +1,4 @@
+#!/system/bin/sh
# Script to start "pm" on the device, which has a very rudimentary
# shell.
#
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index c469ae4..865a216 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -50,6 +50,7 @@ static void usage(const char* pname)
"usage: %s [-hp] [-d display-id] [FILENAME]\n"
" -h: this message\n"
" -p: save the file as a png.\n"
+ " -j: save the file as a jpeg.\n"
" -d: specify the display id to capture, default %d.\n"
"If FILENAME ends with .png it will be saved as a png.\n"
"If FILENAME is not given, the results will be printed to stdout.\n",
@@ -112,13 +113,17 @@ int main(int argc, char** argv)
const char* pname = argv[0];
bool png = false;
+ bool jpeg = false;
int32_t displayId = DEFAULT_DISPLAY_ID;
int c;
- while ((c = getopt(argc, argv, "phd:")) != -1) {
+ while ((c = getopt(argc, argv, "pjhd:")) != -1) {
switch (c) {
case 'p':
png = true;
break;
+ case 'j':
+ jpeg = true;
+ break;
case 'd':
displayId = atoi(optarg);
break;
@@ -143,8 +148,14 @@ int main(int argc, char** argv)
return 1;
}
const int len = strlen(fn);
- if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) {
- png = true;
+ if (len >= 4) {
+ if (0 == strcmp(fn+len-4, ".png")) {
+ png = true;
+ } else if (0 == strcmp(fn+len-4, ".jpg")) {
+ jpeg = true;
+ } else if (len > 4 && 0 == strcmp(fn+len-5, ".jpeg")) {
+ jpeg = true;
+ }
}
}
@@ -220,11 +231,12 @@ int main(int argc, char** argv)
}
if (base != NULL) {
- if (png) {
+ if (png || jpeg) {
const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f),
kPremul_SkAlphaType);
SkAutoTUnref<SkData> data(SkImageEncoder::EncodeData(info, base, s*bytesPerPixel(f),
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality));
+ (png ? SkImageEncoder::kPNG_Type : SkImageEncoder::kJPEG_Type),
+ SkImageEncoder::kDefaultQuality));
if (data.get()) {
write(fd, data->data(), data->size());
}
diff --git a/cmds/settings/Android.mk b/cmds/settings/Android.mk
index 05deb99..c397535 100644
--- a/cmds/settings/Android.mk
+++ b/cmds/settings/Android.mk
@@ -4,6 +4,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.internal
LOCAL_MODULE := settings
LOCAL_MODULE_TAGS := optional
include $(BUILD_JAVA_LIBRARY)
diff --git a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
index c27d0c0..64610fe 100644
--- a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
+++ b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
@@ -29,6 +29,8 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.TextUtils;
+import cyanogenmod.providers.CMSettings;
import java.util.ArrayList;
import java.util.Collections;
@@ -36,6 +38,9 @@ import java.util.List;
public final class SettingsCmd {
+ private static final String SETTINGS_AUTHORITY = Settings.AUTHORITY;
+ private static final String CMSETTINGS_AUTHORITY = CMSettings.AUTHORITY;
+
enum CommandVerb {
UNSPECIFIED,
GET,
@@ -51,6 +56,7 @@ public final class SettingsCmd {
String mTable = null;
String mKey = null;
String mValue = null;
+ boolean mUseCMSettingsProvider = false;
public static void main(String[] args) {
if (args == null || args.length < 2) {
@@ -77,6 +83,8 @@ public final class SettingsCmd {
break;
}
mUser = Integer.parseInt(nextArg());
+ } else if ("--cm".equals(arg)) {
+ mUseCMSettingsProvider = true;
} else if (mVerb == CommandVerb.UNSPECIFIED) {
if ("get".equalsIgnoreCase(arg)) {
mVerb = CommandVerb.GET;
@@ -133,13 +141,21 @@ public final class SettingsCmd {
mUser = UserHandle.USER_OWNER;
}
+ // Implicitly use CMSettings provider if the setting is a legacy setting
+ if (!mUseCMSettingsProvider && isLegacySetting(mTable, mKey)) {
+ System.err.println("'" + mKey + "' has moved to CMSettings. Use --cm to avoid " +
+ "this warning in the future.");
+ mUseCMSettingsProvider = true;
+ }
+
try {
IActivityManager activityManager = ActivityManagerNative.getDefault();
IContentProvider provider = null;
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
- "settings", UserHandle.USER_OWNER, token);
+ mUseCMSettingsProvider ? CMSETTINGS_AUTHORITY : SETTINGS_AUTHORITY,
+ UserHandle.USER_OWNER, token);
if (holder == null) {
throw new IllegalStateException("Could not find settings provider");
}
@@ -182,9 +198,15 @@ public final class SettingsCmd {
}
private List<String> listForUser(IContentProvider provider, int userHandle, String table) {
- final Uri uri = "system".equals(table) ? Settings.System.CONTENT_URI
- : "secure".equals(table) ? Settings.Secure.CONTENT_URI
- : "global".equals(table) ? Settings.Global.CONTENT_URI
+ final Uri systemUri = mUseCMSettingsProvider ? CMSettings.System.CONTENT_URI
+ : Settings.System.CONTENT_URI;
+ final Uri secureUri = mUseCMSettingsProvider ? CMSettings.Secure.CONTENT_URI
+ : Settings.Secure.CONTENT_URI;
+ final Uri globalUri = mUseCMSettingsProvider ? CMSettings.Global.CONTENT_URI
+ : Settings.Global.CONTENT_URI;
+ final Uri uri = "system".equals(table) ? systemUri
+ : "secure".equals(table) ? secureUri
+ : "global".equals(table) ? globalUri
: null;
final ArrayList<String> lines = new ArrayList<String>();
if (uri == null) {
@@ -220,10 +242,16 @@ public final class SettingsCmd {
String getForUser(IContentProvider provider, int userHandle,
final String table, final String key) {
+ final String systemGetCommand = mUseCMSettingsProvider ? CMSettings.CALL_METHOD_GET_SYSTEM
+ : Settings.CALL_METHOD_GET_SYSTEM;
+ final String secureGetCommand = mUseCMSettingsProvider ? CMSettings.CALL_METHOD_GET_SECURE
+ : Settings.CALL_METHOD_GET_SECURE;
+ final String globalGetCommand = mUseCMSettingsProvider ? CMSettings.CALL_METHOD_GET_GLOBAL
+ : Settings.CALL_METHOD_GET_GLOBAL;
final String callGetCommand;
- if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
- else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
- else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
+ if ("system".equals(table)) callGetCommand = systemGetCommand;
+ else if ("secure".equals(table)) callGetCommand = secureGetCommand;
+ else if ("global".equals(table)) callGetCommand = globalGetCommand;
else {
System.err.println("Invalid table; no put performed");
throw new IllegalArgumentException("Invalid table " + table);
@@ -232,7 +260,8 @@ public final class SettingsCmd {
String result = null;
try {
Bundle arg = new Bundle();
- arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+ arg.putInt(mUseCMSettingsProvider ? CMSettings.CALL_METHOD_USER_KEY
+ : Settings.CALL_METHOD_USER_KEY, userHandle);
Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
if (b != null) {
result = b.getPairValue();
@@ -245,10 +274,16 @@ public final class SettingsCmd {
void putForUser(IContentProvider provider, int userHandle,
final String table, final String key, final String value) {
+ final String systemPutCommand = mUseCMSettingsProvider ? CMSettings.CALL_METHOD_PUT_SYSTEM
+ : Settings.CALL_METHOD_PUT_SYSTEM;
+ final String securePutCommand = mUseCMSettingsProvider ? CMSettings.CALL_METHOD_PUT_SECURE
+ : Settings.CALL_METHOD_PUT_SECURE;
+ final String globalPutCommand = mUseCMSettingsProvider ? CMSettings.CALL_METHOD_PUT_GLOBAL
+ : Settings.CALL_METHOD_PUT_GLOBAL;
final String callPutCommand;
- if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
- else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
- else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
+ if ("system".equals(table)) callPutCommand = systemPutCommand;
+ else if ("secure".equals(table)) callPutCommand = securePutCommand;
+ else if ("global".equals(table)) callPutCommand = globalPutCommand;
else {
System.err.println("Invalid table; no put performed");
return;
@@ -257,7 +292,8 @@ public final class SettingsCmd {
try {
Bundle arg = new Bundle();
arg.putString(Settings.NameValueTable.VALUE, value);
- arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+ arg.putInt(mUseCMSettingsProvider ? CMSettings.CALL_METHOD_USER_KEY
+ : Settings.CALL_METHOD_USER_KEY, userHandle);
provider.call(resolveCallingPackage(), callPutCommand, key, arg);
} catch (RemoteException e) {
System.err.println("Can't set key " + key + " in " + table + " for user " + userHandle);
@@ -266,10 +302,16 @@ public final class SettingsCmd {
int deleteForUser(IContentProvider provider, int userHandle,
final String table, final String key) {
+ final Uri systemUri = mUseCMSettingsProvider ? CMSettings.System.getUriFor(key)
+ : Settings.System.getUriFor(key);
+ final Uri secureUri = mUseCMSettingsProvider ? CMSettings.Secure.getUriFor(key)
+ : Settings.Secure.getUriFor(key);
+ final Uri globalUri = mUseCMSettingsProvider ? CMSettings.Global.getUriFor(key)
+ : Settings.Global.getUriFor(key);
Uri targetUri;
- if ("system".equals(table)) targetUri = Settings.System.getUriFor(key);
- else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key);
- else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key);
+ if ("system".equals(table)) targetUri = systemUri;
+ else if ("secure".equals(table)) targetUri = secureUri;
+ else if ("global".equals(table)) targetUri = globalUri;
else {
System.err.println("Invalid table; no delete performed");
throw new IllegalArgumentException("Invalid table " + table);
@@ -286,12 +328,26 @@ public final class SettingsCmd {
}
private static void printUsage() {
- System.err.println("usage: settings [--user NUM] get namespace key");
- System.err.println(" settings [--user NUM] put namespace key value");
- System.err.println(" settings [--user NUM] delete namespace key");
- System.err.println(" settings [--user NUM] list namespace");
+ System.err.println("usage: settings [--user NUM] [--cm] get namespace key");
+ System.err.println(" settings [--user NUM] [--cm] put namespace key value");
+ System.err.println(" settings [--user NUM] [--cm] delete namespace key");
+ System.err.println(" settings [--user NUM] [--cm] list namespace");
System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive");
System.err.println("If '--user NUM' is not given, the operations are performed on the owner user.");
+ System.err.println("If '--cm' is given, the operations are performed on the CMSettings provider.");
+ }
+
+ private static boolean isLegacySetting(String table, String key) {
+ if (!TextUtils.isEmpty(key)) {
+ if ("system".equals(table)) {
+ return CMSettings.System.isLegacySetting(key);
+ } else if ("secure".equals(table)) {
+ return CMSettings.Secure.isLegacySetting(key);
+ } else if ("global".equals(table)) {
+ return CMSettings.Global.isLegacySetting(key);
+ }
+ }
+ return false;
}
public static String resolveCallingPackage() {
diff --git a/cmds/tm/Android.mk b/cmds/tm/Android.mk
new file mode 100644
index 0000000..97e8ee4
--- /dev/null
+++ b/cmds/tm/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2015 The CyanogenMod Project
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.internal
+LOCAL_MODULE := tm
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := tm
+LOCAL_SRC_FILES := tm
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
diff --git a/cmds/tm/MODULE_LICENSE_APACHE2 b/cmds/tm/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/tm/MODULE_LICENSE_APACHE2
diff --git a/cmds/tm/NOTICE b/cmds/tm/NOTICE
new file mode 100644
index 0000000..0820f6d
--- /dev/null
+++ b/cmds/tm/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2015, The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/cmds/tm/src/com/android/commands/tm/Tm.java b/cmds/tm/src/com/android/commands/tm/Tm.java
new file mode 100644
index 0000000..0ba5cb9
--- /dev/null
+++ b/cmds/tm/src/com/android/commands/tm/Tm.java
@@ -0,0 +1,204 @@
+/*
+**
+** Copyright 2015, The CyanogenMod 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.commands.tm;
+
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.AndroidException;
+import com.android.internal.os.BaseCommand;
+
+import cyanogenmod.app.CMContextConstants;
+import cyanogenmod.themes.IThemeService;
+import cyanogenmod.themes.ThemeChangeRequest;
+
+import org.cyanogenmod.internal.util.ThemeUtils;
+
+import java.io.PrintStream;
+import java.util.List;
+import java.util.Map;
+
+public class Tm extends BaseCommand {
+ private static final String SYSTEM_THEME = "system";
+
+ IThemeService mTs;
+ IPackageManager mPm;
+
+ /**
+ * Command-line entry point.
+ *
+ * @param args The command-line arguments
+ */
+ public static void main(String[] args) {
+ (new Tm()).run(args);
+ }
+
+ public void onShowUsage(PrintStream out) {
+ List<String> components = ThemeUtils.getAllComponents();
+ StringBuilder sb = new StringBuilder();
+ sb.append("usage: tm [subcommand] [options]\n");
+ sb.append(" tm list\n");
+ sb.append(" tm apply <PACKAGE_NAME> [-r] [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
+ sb.append(" tm rebuild\n");
+ sb.append(" tm process <PACKAGE_NAME>\n");
+ sb.append("\n");
+ sb.append("tm list: return a list of theme packages.\n");
+ sb.append("\n");
+ sb.append("tm apply: applies the components for the theme specified by PACKAGE_NAME.\n");
+ sb.append(" -r: remove per app themes\n");
+ sb.append(" [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
+ sb.append(" if no components are specified all components will be applied.\n");
+ sb.append(" Valid components are:\n");
+ for (String component : components) {
+ sb.append(" ");
+ sb.append(component);
+ sb.append("\n");
+ }
+ sb.append("\n");
+ sb.append("tm rebuild: rebuilds the resource cache.\n");
+ sb.append("\n");
+ sb.append("tm process: processes the theme resources for the theme specified by " +
+ "PACKAGE_NAME.\n");
+
+ out.println(sb.toString());
+ }
+
+ public void onRun() throws Exception {
+ mTs = IThemeService.Stub.asInterface(ServiceManager
+ .getService(CMContextConstants.CM_THEME_SERVICE));
+ if (mTs == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't connect to theme service; is the system running?");
+ }
+
+ mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ if (mPm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't connect to package manager; is the system running?");
+ }
+
+ String op = nextArgRequired();
+
+ if (op.equals("list")) {
+ runListThemePackages();
+ } else if (op.equals("apply")) {
+ runApplyTheme();
+ } else if (op.equals("rebuild")) {
+ runRebuildResourceCache();
+ } else if (op.equals("process")) {
+ runProcessTheme();
+ } else {
+ showError("Error: unknown command '" + op + "'");
+ return;
+ }
+ }
+
+ private void runListThemePackages() throws Exception {
+ List<PackageInfo> packages = getInstalledPackages(mPm, 0, UserHandle.USER_OWNER);
+
+ // there is always a "system" theme available
+ System.out.println("package:system [theme]");
+ for (PackageInfo info : packages) {
+ if (info.isThemeApk || info.isLegacyIconPackApk) {
+ System.out.print("package:");
+ System.out.print(info.packageName);
+ if (info.isThemeApk) {
+ System.out.println(" [theme]");
+ } else {
+ System.out.println(" [icon pack]");
+ }
+ }
+ }
+ }
+
+ private void runApplyTheme() throws Exception {
+ String pkgName = nextArg();
+ if (pkgName == null) {
+ System.err.println("Error: didn't specify theme package to apply");
+ return;
+ }
+ if (!SYSTEM_THEME.equals(pkgName)) {
+ PackageInfo info = mPm.getPackageInfo(pkgName, 0, UserHandle.USER_OWNER);
+ if (info == null) {
+ System.err.println("Error: invalid package name");
+ return;
+ }
+ if (!(info.isThemeApk || info.isLegacyIconPackApk)) {
+ System.err.println("Error: package is not a theme or icon pack");
+ return;
+ }
+ }
+
+ boolean removePerAppThemes = false;
+
+ ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-c")) {
+ builder.setComponent(nextArgRequired(), pkgName);
+ } else if (opt.equals("-r")) {
+ removePerAppThemes = true;
+ }
+ }
+
+ // No components specified so let's just try and apply EVERYTHING!
+ Map<String, String> componentMap = builder.build().getThemeComponentsMap();
+ if (componentMap.size() == 0) {
+ List<String> components = ThemeUtils.getAllComponents();
+ for (String component : components) {
+ builder.setComponent(component, pkgName);
+ }
+ }
+ mTs.requestThemeChange(builder.build(), removePerAppThemes);
+ }
+
+ private void runRebuildResourceCache() throws Exception {
+ mTs.rebuildResourceCache();
+ }
+
+ private void runProcessTheme() throws Exception {
+ String pkgName = nextArg();
+ if (pkgName == null) {
+ System.err.println("Error: didn't specify theme package to apply");
+ return;
+ }
+ PackageInfo info = mPm.getPackageInfo(pkgName, 0, UserHandle.USER_OWNER);
+ if (info == null) {
+ System.err.println("Error: invalid package name");
+ return;
+ }
+ if (!info.isThemeApk) {
+ System.err.println("Error: package is not a theme");
+ return;
+ }
+
+ mTs.processThemeResources(pkgName);
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
+ throws RemoteException {
+ ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId);
+ return slice.getList();
+ }
+
+}
diff --git a/cmds/tm/tm b/cmds/tm/tm
new file mode 100755
index 0000000..dc95b6f
--- /dev/null
+++ b/cmds/tm/tm
@@ -0,0 +1,6 @@
+# Script to start "tm" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/tm.jar
+exec app_process $base/bin com.android.commands.tm.Tm "$@"
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 9ef13de..eb59f6b 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -329,6 +329,7 @@ public class AccountManager {
* @return The account's password, null if none or if the account doesn't exist
*/
public String getPassword(final Account account) {
+ android.util.SeempLog.record(22);
if (account == null) throw new IllegalArgumentException("account is null");
try {
return mService.getPassword(account);
@@ -357,6 +358,7 @@ public class AccountManager {
* @return The user data, null if the account or key doesn't exist
*/
public String getUserData(final Account account, final String key) {
+ android.util.SeempLog.record(23);
if (account == null) throw new IllegalArgumentException("account is null");
if (key == null) throw new IllegalArgumentException("key is null");
try {
@@ -567,6 +569,7 @@ public class AccountManager {
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
return new Future2Task<String>(handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.getAuthTokenLabel(mResponse, accountType, authTokenType);
}
@@ -612,6 +615,7 @@ public class AccountManager {
if (features == null) throw new IllegalArgumentException("features is null");
return new Future2Task<Boolean>(handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName());
}
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
@@ -664,6 +668,7 @@ public class AccountManager {
if (type == null) throw new IllegalArgumentException("type is null");
return new Future2Task<Account[]>(handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.getAccountsByFeatures(mResponse, type, features,
mContext.getOpPackageName());
}
@@ -707,6 +712,7 @@ public class AccountManager {
* already exists, the account is null, or another error occurs.
*/
public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
+ android.util.SeempLog.record(24);
if (account == null) throw new IllegalArgumentException("account is null");
try {
return mService.addAccountExplicitly(account, password, userdata);
@@ -777,6 +783,7 @@ public class AccountManager {
return new Future2Task<Account>(handler, callback) {
@Override
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.renameAccount(mResponse, account, newName);
}
@Override
@@ -837,10 +844,12 @@ public class AccountManager {
@Deprecated
public AccountManagerFuture<Boolean> removeAccount(final Account account,
AccountManagerCallback<Boolean> callback, Handler handler) {
+ android.util.SeempLog.record(25);
if (account == null) throw new IllegalArgumentException("account is null");
return new Future2Task<Boolean>(handler, callback) {
@Override
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.removeAccount(mResponse, account, false);
}
@Override
@@ -896,10 +905,12 @@ public class AccountManager {
*/
public AccountManagerFuture<Bundle> removeAccount(final Account account,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
+ android.util.SeempLog.record(28);
if (account == null) throw new IllegalArgumentException("account is null");
return new AmsTask(activity, handler, callback) {
@Override
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(34);
mService.removeAccount(mResponse, account, activity != null);
}
}.start();
@@ -921,6 +932,7 @@ public class AccountManager {
return new Future2Task<Boolean>(handler, callback) {
@Override
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
}
@Override
@@ -946,6 +958,7 @@ public class AccountManager {
throw new IllegalArgumentException("userHandle is null");
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(34);
mService.removeAccountAsUser(mResponse, account, activity != null,
userHandle.getIdentifier());
}
@@ -1062,6 +1075,7 @@ public class AccountManager {
* @param password The password to set, null to clear the password
*/
public void setPassword(final Account account, final String password) {
+ android.util.SeempLog.record(26);
if (account == null) throw new IllegalArgumentException("account is null");
try {
mService.setPassword(account, password);
@@ -1091,6 +1105,7 @@ public class AccountManager {
* @param account The account whose password to clear
*/
public void clearPassword(final Account account) {
+ android.util.SeempLog.record(27);
if (account == null) throw new IllegalArgumentException("account is null");
try {
mService.clearPassword(account);
@@ -1119,6 +1134,7 @@ public class AccountManager {
* @param value String value to set, {@code null} to clear this user data key
*/
public void setUserData(final Account account, final String key, final String value) {
+ android.util.SeempLog.record(28);
if (account == null) throw new IllegalArgumentException("account is null");
if (key == null) throw new IllegalArgumentException("key is null");
try {
@@ -1270,6 +1286,7 @@ public class AccountManager {
optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.getAuthToken(mResponse, account, authTokenType,
false /* notifyOnAuthFailure */, true /* expectActivityLaunch */,
optionsIn);
@@ -1438,6 +1455,7 @@ public class AccountManager {
optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
return new AmsTask(null, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.getAuthToken(mResponse, account, authTokenType,
notifyAuthFailure, false /* expectActivityLaunch */, optionsIn);
}
@@ -1498,6 +1516,7 @@ public class AccountManager {
final String authTokenType, final String[] requiredFeatures,
final Bundle addAccountOptions,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
+ android.util.SeempLog.record(29);
if (accountType == null) throw new IllegalArgumentException("accountType is null");
final Bundle optionsIn = new Bundle();
if (addAccountOptions != null) {
@@ -1507,6 +1526,7 @@ public class AccountManager {
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.addAccount(mResponse, accountType, authTokenType,
requiredFeatures, activity != null, optionsIn);
}
@@ -1531,6 +1551,7 @@ public class AccountManager {
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.addAccountAsUser(mResponse, accountType, authTokenType,
requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier());
}
@@ -1578,6 +1599,7 @@ public class AccountManager {
return new Future2Task<Boolean>(handler, callback) {
@Override
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(34);
mService.copyAccountToUser(
mResponse, account, UserHandle.USER_OWNER, user.getIdentifier());
}
@@ -1705,6 +1727,7 @@ public class AccountManager {
final int userId = userHandle.getIdentifier();
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
userId);
}
@@ -1817,9 +1840,11 @@ public class AccountManager {
public AccountManagerFuture<Bundle> editProperties(final String accountType,
final Activity activity, final AccountManagerCallback<Bundle> callback,
final Handler handler) {
+ android.util.SeempLog.record(30);
if (accountType == null) throw new IllegalArgumentException("accountType is null");
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
mService.editProperties(mResponse, accountType, activity != null);
}
}.start();
@@ -2175,6 +2200,7 @@ public class AccountManager {
private volatile int mNumAccounts = 0;
public void doWork() throws RemoteException {
+ android.util.SeempLog.record(31);
getAccountsByTypeAndFeatures(mAccountType, mFeatures,
new AccountManagerCallback<Account[]>() {
public void run(AccountManagerFuture<Account[]> future) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 87c9efc2..ad08c23 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -41,6 +41,7 @@ import android.content.pm.ConfigurationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
@@ -59,6 +60,7 @@ import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Size;
import android.util.Slog;
+
import org.xmlpull.v1.XmlSerializer;
import java.io.FileDescriptor;
@@ -525,8 +527,16 @@ public class ActivityManager {
* @hide
*/
static public boolean isHighEndGfx() {
- return !isLowRamDeviceStatic() &&
- !Resources.getSystem().getBoolean(com.android.internal.R.bool.config_avoidGfxAccel);
+ return (!isLowRamDeviceStatic() &&
+ !Resources.getSystem().getBoolean(com.android.internal.R.bool.config_avoidGfxAccel))
+ || isForcedHighEndGfx();
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean isForcedHighEndGfx() {
+ return SystemProperties.getBoolean("persist.sys.force_highendgfx", false);
}
/**
@@ -2298,6 +2308,16 @@ public class ActivityManager {
return null;
}
}
+ /**
+ * @hide
+ */
+ public Configuration getConfiguration() {
+ try {
+ return ActivityManagerNative.getDefault().getConfiguration();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
/**
* Sets the memory trim mode for a process and schedules a memory trim operation.
@@ -2988,4 +3008,17 @@ public class ActivityManager {
}
}
}
+
+ /**
+ * @throws SecurityException Throws SecurityException if the caller does
+ * not hold the {@link android.Manifest.permission#CHANGE_CONFIGURATION} permission.
+ *
+ * @hide
+ */
+ public void updateConfiguration(Configuration values) throws SecurityException {
+ try {
+ ActivityManagerNative.getDefault().updateConfiguration(values);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f6e0735..d638de6 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -577,6 +577,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_CALLING_PACKAGE_FOR_BROADCAST_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ boolean foreground = data.readInt() == 1 ? true : false;
+ String res = getCallingPackageForBroadcast(foreground);
+ reply.writeNoException();
+ reply.writeString(res);
+ return true;
+ }
+
case GET_CALLING_ACTIVITY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -2096,7 +2105,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case KEYGUARD_GOING_AWAY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- keyguardGoingAway(data.readInt() != 0, data.readInt() != 0);
+ keyguardGoingAway(data.readInt() != 0, data.readInt() != 0, data.readInt() != 0);
reply.writeNoException();
return true;
}
@@ -3192,6 +3201,19 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
+ public String getCallingPackageForBroadcast(boolean foreground) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(foreground ? 1 : 0);
+ mRemote.transact(GET_CALLING_PACKAGE_FOR_BROADCAST_TRANSACTION, data, reply, 0);
+ reply.readException();
+ String res = reply.readString();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
public ComponentName getCallingActivity(IBinder token)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -5263,12 +5285,14 @@ class ActivityManagerProxy implements IActivityManager
}
public void keyguardGoingAway(boolean disableWindowAnimations,
- boolean keyguardGoingToNotificationShade) throws RemoteException {
+ boolean keyguardGoingToNotificationShade,
+ boolean keyguardShowingMedia) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(disableWindowAnimations ? 1 : 0);
data.writeInt(keyguardGoingToNotificationShade ? 1 : 0);
+ data.writeInt(keyguardShowingMedia ? 1 : 0);
mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fd88a05..782dc46 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -46,6 +46,7 @@ import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Typeface;
import android.hardware.display.DisplayManagerGlobal;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
@@ -78,6 +79,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.security.NetworkSecurityPolicy;
+import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
@@ -90,6 +92,7 @@ import android.util.Slog;
import android.util.SuperNotCalledException;
import android.view.Display;
import android.view.HardwareRenderer;
+import android.view.InflateException;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewManager;
@@ -893,9 +896,25 @@ public final class ActivityThread {
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
- updateProcessState(processState, false);
- receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
- sticky, sendingUser);
+ RemoteException remoteException = null;
+ if (!Binder.isProxy(receiver)) {
+ updateProcessState(processState, false);
+ try {
+ receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
+ sticky, sendingUser);
+ return;
+ } catch (RemoteException e) {
+ remoteException = e;
+ }
+ }
+ if (ordered) {
+ Slog.w(TAG, receiver + " is no longer alive");
+ ActivityManagerNative.getDefault().finishReceiver(receiver.asBinder(),
+ resultCode, dataStr, extras, true, intent.getFlags());
+ if (remoteException != null) {
+ throw remoteException;
+ }
+ }
}
@Override
@@ -1697,9 +1716,21 @@ public final class ActivityThread {
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
String[] libDirs, int displayId, Configuration overrideConfiguration,
- LoadedApk pkgInfo) {
+ LoadedApk pkgInfo, Context context, String pkgName) {
return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
- displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
+ displayId, pkgName, overrideConfiguration, pkgInfo.getCompatibilityInfo(), context,
+ pkgInfo.getApplicationInfo().isThemeable);
+ }
+
+ /**
+ * Creates the top level resources for the given package.
+ */
+ Resources getTopLevelThemedResources(String resDir, int displayId,
+ Configuration overrideConfiguration, LoadedApk pkgInfo,
+ String pkgName, String themePkgName) {
+ return mResourcesManager.getTopLevelThemedResources(resDir, displayId, pkgName,
+ themePkgName, pkgInfo.getCompatibilityInfo(),
+ pkgInfo.getApplicationInfo().isThemeable);
}
final Handler getHandler() {
@@ -1817,8 +1848,7 @@ public final class ActivityThread {
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
- if (packageInfo == null || (packageInfo.mResources != null
- && !packageInfo.mResources.getAssets().isUpToDate())) {
+ if (packageInfo == null) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
: "Loading resource-only package ") + aInfo.packageName
+ " (in " + (mBoundApplication != null
@@ -1844,6 +1874,10 @@ public final class ActivityThread {
new WeakReference<LoadedApk>(packageInfo));
}
}
+ if (packageInfo.mResources != null
+ && !packageInfo.mResources.getAssets().isUpToDate()) {
+ packageInfo.mResources = null;
+ }
return packageInfo;
}
}
@@ -4258,8 +4292,12 @@ public final class ActivityThread {
if (configDiff != 0) {
// Ask text layout engine to free its caches if there is a locale change
boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
- if (hasLocaleConfigChange) {
+ boolean hasFontConfigChange = ((configDiff & ActivityInfo.CONFIG_THEME_FONT) != 0);
+ if (hasLocaleConfigChange || hasFontConfigChange) {
Canvas.freeTextLayoutCaches();
+ if (hasFontConfigChange) {
+ Typeface.recreateDefaults();
+ }
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
}
}
@@ -4428,7 +4466,7 @@ public final class ActivityThread {
+ DisplayMetrics.DENSITY_DEVICE + " to "
+ mCurDefaultDisplayDpi);
DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
- Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
+ Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEVICE);
}
}
@@ -4528,7 +4566,8 @@ public final class ActivityThread {
}
- final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
+ final boolean is24Hr = android.text.format.DateFormat.is24HourFormat(
+ mCoreSettings.getString(Settings.System.TIME_12_24), data.config.locale);
DateFormat.set24HourTimePref(is24Hr);
View.mDebugViewAttributes =
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 330d730..b0afe7c 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -100,6 +100,14 @@ public class AlarmManager {
*/
public static final int ELAPSED_REALTIME = 3;
+ /** @hide
+ * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()}
+ * (wall clock time in UTC), which will wake up the device when
+ * it goes off. And it will power on the devices when it shuts down.
+ * Set as 5 to make it be compatible with android_alarm_type.
+ */
+ public static final int RTC_POWEROFF_WAKEUP = 5;
+
/**
* Broadcast Action: Sent after the value returned by
* {@link #getNextAlarmClock()} has changed.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 09c0a6e..11a5ee8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +31,7 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.SystemProperties;
import android.os.UserManager;
import android.util.ArrayMap;
@@ -69,6 +73,10 @@ public class AppOpsManager {
* will do this for you).
*/
+ /** {@hide */
+ public static final String ACTION_SU_SESSION_CHANGED =
+ "android.intent.action.SU_SESSION_CHANGED";
+
final Context mContext;
final IAppOpsService mService;
final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
@@ -103,9 +111,18 @@ public class AppOpsManager {
*/
public static final int MODE_DEFAULT = 3;
+ /**
+ * @hide Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}:
+ * AppOps Service should show a dialog box on screen to get user
+ * permission.
+ */
+ public static final int MODE_ASK = 4;
+
// when adding one of these:
// - increment _NUM_OP
- // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
+ // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode, sOpDefaultStrictMode,
+ // sOpToOpString, sOpStrictMode.
+ // - add descriptive strings to frameworks/base/core/res/res/values/config.xml
// - add descriptive strings to Settings/res/values/arrays.xml
// - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
@@ -237,8 +254,20 @@ public class AppOpsManager {
public static final int OP_TURN_SCREEN_ON = 61;
/** @hide Get device accounts. */
public static final int OP_GET_ACCOUNTS = 62;
+ /** @hide Wifi state change **/
+ public static final int OP_WIFI_CHANGE = 63;
+ /** @hide */
+ public static final int OP_BLUETOOTH_CHANGE = 64;
/** @hide */
- public static final int _NUM_OP = 63;
+ public static final int OP_BOOT_COMPLETED = 65;
+ /** @hide */
+ public static final int OP_NFC_CHANGE = 66;
+ /** @hide */
+ public static final int OP_DATA_CONNECT_CHANGE = 67;
+ /** @hide */
+ public static final int OP_SU = 68;
+ /** @hide */
+ public static final int _NUM_OP = 69;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -336,6 +365,19 @@ public class AppOpsManager {
/** @hide Get device accounts. */
public static final String OPSTR_GET_ACCOUNTS
= "android:get_accounts";
+ /** @hide **/
+ private static final String OPSTR_WIFI_CHANGE =
+ "android:wifi_change";
+ private static final String OPSTR_BLUETOOTH_CHANGE =
+ "android:bluetooth_change";
+ private static final String OPSTR_BOOT_COMPLETED =
+ "android:boot_completed";
+ private static final String OPSTR_NFC_CHANGE =
+ "android:nfc_change";
+ private static final String OPSTR_DATA_CONNECT_CHANGE =
+ "android:data_connect_change";
+ private static final String OPSTR_SU =
+ "android:su";
/**
* This maps each operation to the operation that serves as the
@@ -356,7 +398,7 @@ public class AppOpsManager {
OP_WRITE_CALL_LOG,
OP_READ_CALENDAR,
OP_WRITE_CALENDAR,
- OP_COARSE_LOCATION,
+ OP_WIFI_SCAN,
OP_POST_NOTIFICATION,
OP_COARSE_LOCATION,
OP_CALL_PHONE,
@@ -409,6 +451,12 @@ public class AppOpsManager {
OP_WRITE_EXTERNAL_STORAGE,
OP_TURN_SCREEN_ON,
OP_GET_ACCOUNTS,
+ OP_WIFI_CHANGE,
+ OP_BLUETOOTH_CHANGE,
+ OP_BOOT_COMPLETED,
+ OP_NFC_CHANGE,
+ OP_DATA_CONNECT_CHANGE,
+ OP_SU
};
/**
@@ -478,7 +526,13 @@ public class AppOpsManager {
OPSTR_READ_EXTERNAL_STORAGE,
OPSTR_WRITE_EXTERNAL_STORAGE,
null,
- OPSTR_GET_ACCOUNTS
+ OPSTR_GET_ACCOUNTS,
+ OPSTR_WIFI_CHANGE,
+ OPSTR_BLUETOOTH_CHANGE,
+ OPSTR_BOOT_COMPLETED,
+ OPSTR_NFC_CHANGE,
+ OPSTR_DATA_CONNECT_CHANGE,
+ OPSTR_SU,
};
/**
@@ -549,6 +603,12 @@ public class AppOpsManager {
"WRITE_EXTERNAL_STORAGE",
"TURN_ON_SCREEN",
"GET_ACCOUNTS",
+ "WIFI_CHANGE",
+ "BLUETOOTH_CHANGE",
+ "BOOT_COMPLETED",
+ "NFC_CHANGE",
+ "DATA_CONNECT_CHANGE",
+ "SU",
};
/**
@@ -566,7 +626,7 @@ public class AppOpsManager {
android.Manifest.permission.WRITE_CALL_LOG,
android.Manifest.permission.READ_CALENDAR,
android.Manifest.permission.WRITE_CALENDAR,
- android.Manifest.permission.ACCESS_WIFI_STATE,
+ null, // no permission for wifi scan available
null, // no permission required for notifications
null, // neighboring cells shares the coarse location perm
android.Manifest.permission.CALL_PHONE,
@@ -618,7 +678,13 @@ public class AppOpsManager {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
null, // no permission for turning the screen on
- Manifest.permission.GET_ACCOUNTS
+ Manifest.permission.GET_ACCOUNTS,
+ Manifest.permission.CHANGE_WIFI_STATE,
+ null,
+ Manifest.permission.RECEIVE_BOOT_COMPLETED,
+ Manifest.permission.NFC,
+ Manifest.permission.MODIFY_PHONE_STATE,
+ null,
};
/**
@@ -690,6 +756,12 @@ public class AppOpsManager {
null, // WRITE_EXTERNAL_STORAGE
null, // TURN_ON_SCREEN
null, // GET_ACCOUNTS
+ null, //WIFI_CHANGE
+ null, //BLUETOOTH_CHANGE
+ null, //BOOT_COMPLETED
+ null, //NFC_CHANGE
+ null, //DATA_CONNECT_CHANGE
+ UserManager.DISALLOW_SU, //SU TODO: this should really be investigated.
};
/**
@@ -760,6 +832,12 @@ public class AppOpsManager {
false, // WRITE_EXTERNAL_STORAGE
false, // TURN_ON_SCREEN
false, // GET_ACCOUNTS
+ true, // WIFI_CHANGE
+ true, // BLUETOOTH_CHANGE
+ true, // BOOT_COMPLETED
+ true, // NFC_CHANGE
+ true, //DATA_CONNECT_CHANGE
+ false, //SU
};
/**
@@ -829,6 +907,163 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED, // OP_TURN_ON_SCREEN
AppOpsManager.MODE_ALLOWED,
+ AppOpsManager.MODE_ALLOWED, // OP_WIFI_CHANGE
+ AppOpsManager.MODE_ALLOWED, // OP_BLUETOOTH_CHANGE
+ AppOpsManager.MODE_ALLOWED, // OP_BOOT_COMPLETED
+ AppOpsManager.MODE_ALLOWED, // OP_NFC_CHANGE
+ AppOpsManager.MODE_ALLOWED,
+ AppOpsManager.MODE_ASK, // OP_SU
+ };
+
+ /**
+ * This specifies the default mode for each strict operation.
+ */
+
+ private static int[] sOpDefaultStrictMode = new int[] {
+ AppOpsManager.MODE_ASK, // OP_COARSE_LOCATION
+ AppOpsManager.MODE_ASK, // OP_FINE_LOCATION
+ AppOpsManager.MODE_ASK, // OP_GPS
+ AppOpsManager.MODE_ALLOWED, // OP_VIBRATE
+ AppOpsManager.MODE_ASK, // OP_READ_CONTACTS
+ AppOpsManager.MODE_ASK, // OP_WRITE_CONTACTS
+ AppOpsManager.MODE_ASK, // OP_READ_CALL_LOG
+ AppOpsManager.MODE_ASK, // OP_WRITE_CALL_LOG
+ AppOpsManager.MODE_ALLOWED, // OP_READ_CALENDAR
+ AppOpsManager.MODE_ALLOWED, // OP_WRITE_CALENDAR
+ AppOpsManager.MODE_ASK, // OP_WIFI_SCAN
+ AppOpsManager.MODE_ALLOWED, // OP_POST_NOTIFICATION
+ AppOpsManager.MODE_ALLOWED, // OP_NEIGHBORING_CELLS
+ AppOpsManager.MODE_ASK, // OP_CALL_PHONE
+ AppOpsManager.MODE_ASK, // OP_READ_SMS
+ AppOpsManager.MODE_ASK, // OP_WRITE_SMS
+ AppOpsManager.MODE_ASK, // OP_RECEIVE_SMS
+ AppOpsManager.MODE_ALLOWED, // OP_RECEIVE_EMERGECY_SMS
+ AppOpsManager.MODE_ASK, // OP_RECEIVE_MMS
+ AppOpsManager.MODE_ALLOWED, // OP_RECEIVE_WAP_PUSH
+ AppOpsManager.MODE_ASK, // OP_SEND_SMS
+ AppOpsManager.MODE_ALLOWED, // OP_READ_ICC_SMS
+ AppOpsManager.MODE_ALLOWED, // OP_WRITE_ICC_SMS
+ AppOpsManager.MODE_ALLOWED, // OP_WRITE_SETTINGS
+ AppOpsManager.MODE_ALLOWED, // OP_SYSTEM_ALERT_WINDOW
+ AppOpsManager.MODE_ALLOWED, // OP_ACCESS_NOTIFICATIONS
+ AppOpsManager.MODE_ASK, // OP_CAMERA
+ AppOpsManager.MODE_ASK, // OP_RECORD_AUDIO
+ AppOpsManager.MODE_ALLOWED, // OP_PLAY_AUDIO
+ AppOpsManager.MODE_ALLOWED, // OP_READ_CLIPBOARD
+ AppOpsManager.MODE_ALLOWED, // OP_WRITE_CLIPBOARD
+ AppOpsManager.MODE_ALLOWED, // OP_TAKE_MEDIA_BUTTONS
+ AppOpsManager.MODE_ALLOWED, // OP_TAKE_AUDIO_FOCUS
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_MASTER_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_VOICE_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_RING_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_MEDIA_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_ALARM_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_NOTIFICATION_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_AUDIO_BLUETOOTH_VOLUME
+ AppOpsManager.MODE_ALLOWED, // OP_WAKE_LOCK
+ AppOpsManager.MODE_ALLOWED, // OP_MONITOR_LOCATION
+ AppOpsManager.MODE_ASK, // OP_MONITOR_HIGH_POWER_LOCATION
+ AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS
+ AppOpsManager.MODE_ALLOWED, // OP_MUTE_MICROPHONE
+ AppOpsManager.MODE_ALLOWED, // OP_TOAST_WINDOW
+ AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
+ AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
+ AppOpsManager.MODE_ALLOWED, // OP WALLPAPER
+ AppOpsManager.MODE_ALLOWED, // OP_ASSIST_STRUCTURE
+ AppOpsManager.MODE_ALLOWED, // OP_ASSIST_SCREENSHOT
+ AppOpsManager.MODE_ALLOWED, // OP_READ_PHONE_STATE
+ AppOpsManager.MODE_ALLOWED, // OP_ADD_VOICEMAIL
+ AppOpsManager.MODE_ALLOWED, // OP_USE_SIP
+ AppOpsManager.MODE_ALLOWED, // OP_PROCESS_OUTGOING_CALLS
+ AppOpsManager.MODE_ALLOWED, // OP_USE_FINGERPRINT
+ AppOpsManager.MODE_ALLOWED, // OP_BODY_SENSORS
+ AppOpsManager.MODE_ALLOWED, // OP_READ_CELL_BROADCASTS
+ AppOpsManager.MODE_ERRORED, // OP_MOCK_LOCATION
+ AppOpsManager.MODE_ALLOWED, // OP_READ_EXTERNAL_STORAGE
+ AppOpsManager.MODE_ALLOWED, // OP_WRITE_EXTERNAL_STORAGE
+ AppOpsManager.MODE_ALLOWED, // OP_TURN_ON_SCREEN
+ AppOpsManager.MODE_ALLOWED, // OP_GET_ACCOUNTS
+ AppOpsManager.MODE_ASK, // OP_WIFI_CHANGE
+ AppOpsManager.MODE_ASK, // OP_BLUETOOTH_CHANGE
+ AppOpsManager.MODE_ALLOWED, // OP_BOOT_COMPLETED
+ AppOpsManager.MODE_ASK, // OP_NFC_CHANGE
+ AppOpsManager.MODE_ASK, // OP_DATA_CONNECT_CHANGE
+ AppOpsManager.MODE_ASK, // OP_SU
+ };
+
+ /**
+ * This specifies if operation is in strict mode.
+ */
+ private final static boolean[] sOpStrictMode = new boolean[] {
+ true, // OP_COARSE_LOCATION
+ true, // OP_FINE_LOCATION
+ true, // OP_GPS
+ false, // OP_VIBRATE
+ true, // OP_READ_CONTACTS
+ true, // OP_WRITE_CONTACTS
+ true, // OP_READ_CALL_LOG
+ true, // OP_WRITE_CALL_LOG
+ false, // OP_READ_CALENDAR
+ false, // OP_WRITE_CALENDAR
+ true, // OP_WIFI_SCAN
+ false, // OP_POST_NOTIFICATION
+ false, // OP_NEIGHBORING_CELLS
+ true, // OP_CALL_PHONE
+ true, // OP_READ_SMS
+ true, // OP_WRITE_SMS
+ false, // OP_RECEIVE_SMS
+ false, // OP_RECEIVE_EMERGECY_SMS
+ true, // OP_RECEIVE_MMS
+ false, // OP_RECEIVE_WAP_PUSH
+ true, // OP_SEND_SMS
+ false, // OP_READ_ICC_SMS
+ false, // OP_WRITE_ICC_SMS
+ false, // OP_WRITE_SETTINGS
+ false, // OP_SYSTEM_ALERT_WINDOW
+ false, // OP_ACCESS_NOTIFICATIONS
+ true, // OP_CAMERA
+ true, // OP_RECORD_AUDIO
+ false, // OP_PLAY_AUDIO
+ false, // OP_READ_CLIPBOARD
+ false, // OP_WRITE_CLIPBOARD
+ false, // OP_TAKE_MEDIA_BUTTONS
+ false, // OP_TAKE_AUDIO_FOCUS
+ false, // OP_AUDIO_MASTER_VOLUME
+ false, // OP_AUDIO_VOICE_VOLUME
+ false, // OP_AUDIO_RING_VOLUME
+ false, // OP_AUDIO_MEDIA_VOLUME
+ false, // OP_AUDIO_ALARM_VOLUME
+ false, // OP_AUDIO_NOTIFICATION_VOLUME
+ false, // OP_AUDIO_BLUETOOTH_VOLUME
+ false, // OP_WAKE_LOCK
+ false, // OP_MONITOR_LOCATION
+ true, // OP_MONITOR_HIGH_POWER_LOCATION
+ false, // OP_GET_USAGE_STATS
+ false, // OP_MUTE_MICROPHONE
+ false, // OP_TOAST_WINDOW
+ false, // OP_PROJECT_MEDIA
+ false, // OP_ACTIVATE_VPN
+ true, // OP WALLPAPER
+ false, //ASSIST_STRUCTURE
+ false, //ASSIST_SCREENSHOT
+ false, //READ_PHONE_STATE
+ false, //ADD_VOICEMAIL
+ false, // USE_SIP
+ false, // PROCESS_OUTGOING_CALLS
+ false, // USE_FINGERPRINT
+ false, // BODY_SENSORS
+ false, // READ_CELL_BROADCASTS
+ false, // MOCK_LOCATION
+ true, // READ_EXTERNAL_STORAGE
+ true, // WRITE_EXTERNAL_STORAGE
+ false, // TURN_ON_SCREEN
+ false, // GET_ACCOUNTS
+ true, // OP_WIFI_CHANGE
+ true, // OP_BLUETOOTH_CHANGE
+ false, // OP_BOOT_COMPLETED
+ true, // OP_NFC_CHANGE
+ true, // OP_DATA_CONNECT_CHANGE
+ true, // OP_SU
};
/**
@@ -901,7 +1136,13 @@ public class AppOpsManager {
false,
false,
false,
- false
+ false,
+ false, // OP_WIFI_CHANGE
+ false, // OP_BLUETOOTH_CHANGE
+ false, // OP_BOOT_COMPLETED
+ false, // OP_NFC_CHANGE
+ false, // OP_DATA_CONNECT_CHANGE
+ false, // OP_SU
};
/**
@@ -914,6 +1155,8 @@ public class AppOpsManager {
*/
private static HashMap<String, Integer> sPermToOp = new HashMap<>();
+ private static HashMap<String, Integer> sNameToOp = new HashMap<String, Integer>();
+
static {
if (sOpToSwitch.length != _NUM_OP) {
throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length
@@ -935,6 +1178,10 @@ public class AppOpsManager {
throw new IllegalStateException("sOpDefaultMode length " + sOpDefaultMode.length
+ " should be " + _NUM_OP);
}
+ if (sOpDefaultStrictMode.length != _NUM_OP) {
+ throw new IllegalStateException("sOpDefaultStrictMode length " + sOpDefaultStrictMode.length
+ + " should be " + _NUM_OP);
+ }
if (sOpDisableReset.length != _NUM_OP) {
throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length
+ " should be " + _NUM_OP);
@@ -947,6 +1194,10 @@ public class AppOpsManager {
throw new IllegalStateException("sOpAllowSYstemRestrictionsBypass length "
+ sOpRestrictions.length + " should be " + _NUM_OP);
}
+ if (sOpStrictMode.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStrictMode length "
+ + sOpStrictMode.length + " should be " + _NUM_OP);
+ }
for (int i=0; i<_NUM_OP; i++) {
if (sOpToString[i] != null) {
sOpStrToOp.put(sOpToString[i], i);
@@ -957,6 +1208,9 @@ public class AppOpsManager {
sPermToOp.put(sOpPerms[i], i);
}
}
+ for (int i=0; i<_NUM_OP; i++) {
+ sNameToOp.put(sOpNames[i], i);
+ }
}
/**
@@ -989,6 +1243,15 @@ public class AppOpsManager {
}
/**
+ * Map a non-localized name for the operation back to the Op number
+ * @hide
+ */
+ public static int nameToOp(String name) {
+ Integer val = sNameToOp.get(name);
+ return val != null ? val : OP_NONE;
+ }
+
+ /**
* Retrieve the permission associated with an operation, or null if there is not one.
* @hide
*/
@@ -1026,7 +1289,9 @@ public class AppOpsManager {
* Retrieve the default mode for the operation.
* @hide
*/
- public static int opToDefaultMode(int op) {
+ public static int opToDefaultMode(int op, boolean isStrict) {
+ if (isStrict)
+ return sOpDefaultStrictMode[op];
return sOpDefaultMode[op];
}
@@ -1113,9 +1378,11 @@ public class AppOpsManager {
private final int mDuration;
private final int mProxyUid;
private final String mProxyPackageName;
+ private final int mAllowedCount;
+ private final int mIgnoredCount;
public OpEntry(int op, int mode, long time, long rejectTime, int duration,
- int proxyUid, String proxyPackage) {
+ int proxyUid, String proxyPackage, int allowedCount, int ignoredCount) {
mOp = op;
mMode = mode;
mTime = time;
@@ -1123,6 +1390,8 @@ public class AppOpsManager {
mDuration = duration;
mProxyUid = proxyUid;
mProxyPackageName = proxyPackage;
+ mAllowedCount = allowedCount;
+ mIgnoredCount = ignoredCount;
}
public int getOp() {
@@ -1157,6 +1426,14 @@ public class AppOpsManager {
return mProxyPackageName;
}
+ public int getAllowedCount() {
+ return mAllowedCount;
+ }
+
+ public int getIgnoredCount() {
+ return mIgnoredCount;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -1171,6 +1448,8 @@ public class AppOpsManager {
dest.writeInt(mDuration);
dest.writeInt(mProxyUid);
dest.writeString(mProxyPackageName);
+ dest.writeInt(mAllowedCount);
+ dest.writeInt(mIgnoredCount);
}
OpEntry(Parcel source) {
@@ -1181,6 +1460,8 @@ public class AppOpsManager {
mDuration = source.readInt();
mProxyUid = source.readInt();
mProxyPackageName = source.readString();
+ mAllowedCount = source.readInt();
+ mIgnoredCount = source.readInt();
}
public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
@@ -1753,4 +2034,75 @@ public class AppOpsManager {
public void finishOp(int op) {
finishOp(op, Process.myUid(), mContext.getOpPackageName());
}
+
+ /** @hide */
+ public static boolean isStrictEnable() {
+ return SystemProperties.getBoolean("persist.sys.strict_op_enable", false);
+ }
+
+ /**
+ * Check if op in strict mode
+ * @hide
+ */
+ public static boolean isStrictOp(int code) {
+ return sOpStrictMode[code];
+ }
+
+
+ /** @hide */
+ public static int stringToMode(String permission) {
+ if ("allowed".equalsIgnoreCase(permission)) {
+ return AppOpsManager.MODE_ALLOWED;
+ } else if ("ignored".equalsIgnoreCase(permission)) {
+ return AppOpsManager.MODE_IGNORED;
+ } else if ("ask".equalsIgnoreCase(permission)) {
+ return AppOpsManager.MODE_ASK;
+ }
+ return AppOpsManager.MODE_ERRORED;
+ }
+
+ /** @hide */
+ public static int stringOpToOp (String op) {
+ Integer val = sOpStrToOp.get(op);
+ if (val == null) {
+ val = OP_NONE;
+ }
+ return val;
+ }
+
+ /** @hide */
+ public boolean isControlAllowed(int op, String packageName) {
+ boolean isShow = true;
+ try {
+ isShow = mService.isControlAllowed(op, packageName);
+ } catch (RemoteException e) {
+ }
+ return isShow;
+ }
+
+ /** @hide */
+ public boolean getPrivacyGuardSettingForPackage(int uid, String packageName) {
+ try {
+ return mService.getPrivacyGuardSettingForPackage(uid, packageName);
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
+ /** @hide */
+ public void setPrivacyGuardSettingForPackage(int uid, String packageName,
+ boolean state) {
+ try {
+ mService.setPrivacyGuardSettingForPackage(uid, packageName, state);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /** @hide */
+ public void resetCounters() {
+ try {
+ mService.resetCounters();
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7cae745..db4e123 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -23,6 +23,7 @@ import android.annotation.StringRes;
import android.annotation.XmlRes;
import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
@@ -1028,12 +1029,13 @@ final class ApplicationPackageManager extends PackageManager {
if (app.packageName.equals("system")) {
return mContext.mMainThread.getSystemContext().getResources();
}
+
final boolean sameUid = (app.uid == Process.myUid());
final Resources r = mContext.mMainThread.getTopLevelResources(
sameUid ? app.sourceDir : app.publicSourceDir,
sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
- null, mContext.mPackageInfo);
+ null, mContext.mPackageInfo, mContext, app.packageName);
if (r != null) {
return r;
}
@@ -1069,6 +1071,49 @@ final class ApplicationPackageManager extends PackageManager {
throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
}
+ /** @hide */
+ @Override public Resources getThemedResourcesForApplication(
+ ApplicationInfo app, String themePkgName) throws NameNotFoundException {
+ if (app.packageName.equals("system")) {
+ return mContext.mMainThread.getSystemContext().getResources();
+ }
+
+ Resources r = mContext.mMainThread.getTopLevelThemedResources(
+ app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir,
+ Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo, app.packageName,
+ themePkgName);
+ if (r != null) {
+ return r;
+ }
+ throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
+ }
+
+ /** @hide */
+ @Override public Resources getThemedResourcesForApplication(
+ String appPackageName, String themePkgName) throws NameNotFoundException {
+ return getThemedResourcesForApplication(
+ getApplicationInfo(appPackageName, 0), themePkgName);
+ }
+
+ /** @hide */
+ @Override
+ public Resources getThemedResourcesForApplicationAsUser(String appPackageName,
+ String themePackageName, int userId) throws NameNotFoundException {
+ if (userId < 0) {
+ throw new IllegalArgumentException(
+ "Call does not support special user #" + userId);
+ }
+ try {
+ ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, 0, userId);
+ if (ai != null) {
+ return getThemedResourcesForApplication(ai, themePackageName);
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
+ }
+
int mCachedSafeMode = -1;
@Override public boolean isSafeMode() {
try {
@@ -1993,6 +2038,26 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
+ public void setComponentProtectedSetting(ComponentName componentName, boolean newState) {
+ try {
+ mPM.setComponentProtectedSetting(componentName, newState, mContext.getUserId());
+ } catch (RemoteException re) {
+ Log.e(TAG, "Failed to set component protected setting", re);
+ }
+ }
+
+ /** @hide */
+ @Override
+ public boolean isComponentProtected(String callingPackage, ComponentName componentName) {
+ try {
+ return mPM.isComponentProtected(callingPackage, componentName, mContext.getUserId());
+ } catch (RemoteException re) {
+ Log.e(TAG, "Failed to get component protected setting", re);
+ return false;
+ }
+ }
+
+ @Override
public PackageInstaller getPackageInstaller() {
synchronized (mLock) {
if (mInstaller == null) {
@@ -2240,4 +2305,30 @@ final class ApplicationPackageManager extends PackageManager {
return false;
}
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public void updateIconMaps(String pkgName) {
+ try {
+ mPM.updateIconMapping(pkgName);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Failed to update icon maps", re);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public int processThemeResources(String themePkgName) {
+ try {
+ return mPM.processThemeResources(themePkgName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to process theme resources for " + themePkgName, e);
+ }
+
+ return 0;
+ }
}
diff --git a/core/java/android/app/ComposedIconInfo.aidl b/core/java/android/app/ComposedIconInfo.aidl
new file mode 100644
index 0000000..8a1bab5
--- /dev/null
+++ b/core/java/android/app/ComposedIconInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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;
+
+/** @hide */
+parcelable ComposedIconInfo;
diff --git a/core/java/android/app/ComposedIconInfo.java b/core/java/android/app/ComposedIconInfo.java
new file mode 100644
index 0000000..f49c230
--- /dev/null
+++ b/core/java/android/app/ComposedIconInfo.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class ComposedIconInfo implements Parcelable {
+ public int iconUpon, iconMask;
+ public int[] iconBacks;
+ public float iconScale;
+ public float iconRotation;
+ // value used to provide some randomization to the angle of rotation
+ public float iconRotationVariance;
+ public float iconTranslationX;
+ public float iconTranslationY;
+ public int iconDensity;
+ public int iconSize;
+ public float[] colorFilter;
+
+ // Palettized background items
+ public int iconPaletteBack;
+ public SwatchType swatchType;
+ public int[] defaultSwatchColors;
+
+ public ComposedIconInfo() {
+ super();
+ iconPaletteBack = 0;
+ swatchType = SwatchType.None;
+ iconRotation = 0;
+ iconTranslationX = 0;
+ iconTranslationY = 0;
+ iconScale = 1f;
+ }
+
+ private ComposedIconInfo(Parcel source) {
+ iconScale = source.readFloat();
+ iconRotation = source.readFloat();
+ iconRotationVariance = source.readFloat();
+ iconTranslationX = source.readFloat();
+ iconTranslationY = source.readFloat();
+ iconDensity = source.readInt();
+ iconSize = source.readInt();
+ int backCount = source.readInt();
+ if (backCount > 0) {
+ iconBacks = new int[backCount];
+ for (int i = 0; i < backCount; i++) {
+ iconBacks[i] = source.readInt();
+ }
+ }
+ iconMask = source.readInt();
+ iconUpon = source.readInt();
+ int colorFilterSize = source.readInt();
+ if (colorFilterSize > 0) {
+ colorFilter = new float[colorFilterSize];
+ for (int i = 0; i < colorFilterSize; i++) {
+ colorFilter[i] = source.readFloat();
+ }
+ }
+ iconPaletteBack = source.readInt();
+ swatchType = SwatchType.values()[source.readInt()];
+ int numDefaultColors = source.readInt();
+ if (numDefaultColors > 0) {
+ defaultSwatchColors = new int[numDefaultColors];
+ for (int i = 0; i < numDefaultColors; i++) {
+ defaultSwatchColors[i] = source.readInt();
+ }
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeFloat(iconScale);
+ dest.writeFloat(iconRotation);
+ dest.writeFloat(iconRotationVariance);
+ dest.writeFloat(iconTranslationX);
+ dest.writeFloat(iconTranslationY);
+ dest.writeInt(iconDensity);
+ dest.writeInt(iconSize);
+ dest.writeInt(iconBacks != null ? iconBacks.length : 0);
+ if (iconBacks != null) {
+ for (int resId : iconBacks) {
+ dest.writeInt(resId);
+ }
+ }
+ dest.writeInt(iconMask);
+ dest.writeInt(iconUpon);
+ if (colorFilter != null) {
+ dest.writeInt(colorFilter.length);
+ for (float val : colorFilter) {
+ dest.writeFloat(val);
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(iconPaletteBack);
+ dest.writeInt(swatchType.ordinal());
+ if (defaultSwatchColors != null) {
+ dest.writeInt(defaultSwatchColors.length);
+ for (int color : defaultSwatchColors) {
+ dest.writeInt(color);
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ public static final Creator<ComposedIconInfo> CREATOR
+ = new Creator<ComposedIconInfo>() {
+ @Override
+ public ComposedIconInfo createFromParcel(Parcel source) {
+ return new ComposedIconInfo(source);
+ }
+
+ @Override
+ public ComposedIconInfo[] newArray(int size) {
+ return new ComposedIconInfo[0];
+ }
+ };
+
+ public enum SwatchType {
+ None,
+ Vibrant,
+ VibrantLight,
+ VibrantDark,
+ Muted,
+ MutedLight,
+ MutedDark
+ }
+}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 235f294..d443d80 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -74,6 +74,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
class ReceiverRestrictedContext extends ContextWrapper {
ReceiverRestrictedContext(Context base) {
@@ -269,6 +270,15 @@ class ContextImpl extends Context {
}
@Override
+ public void recreateTheme() {
+ if (mTheme != null) {
+ Resources.Theme newTheme = mResources.newTheme();
+ newTheme.applyStyle(mThemeResource, true);
+ mTheme.setTo(newTheme);
+ }
+ }
+
+ @Override
public ClassLoader getClassLoader() {
return mPackageInfo != null ?
mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
@@ -1657,13 +1667,19 @@ class ContextImpl extends Context {
@Override
public Context createApplicationContext(ApplicationInfo application, int flags)
throws NameNotFoundException {
+ return createApplicationContext(application, null, flags);
+ }
+
+ @Override
+ public Context createApplicationContext(ApplicationInfo application, String themePackageName,
+ int flags) throws NameNotFoundException {
LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE);
if (pi != null) {
final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
new UserHandle(UserHandle.getUserId(application.uid)), restricted,
- mDisplay, null, Display.INVALID_DISPLAY);
+ mDisplay, null, Display.INVALID_DISPLAY, themePackageName);
if (c.mResources != null) {
return c;
}
@@ -1676,24 +1692,30 @@ class ContextImpl extends Context {
@Override
public Context createPackageContext(String packageName, int flags)
throws NameNotFoundException {
- return createPackageContextAsUser(packageName, flags,
+ return createPackageContextAsUser(packageName, null, flags,
mUser != null ? mUser : Process.myUserHandle());
}
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws NameNotFoundException {
+ return createPackageContextAsUser(packageName, null, flags, user);
+ }
+
+ @Override
+ public Context createPackageContextAsUser(String packageName, String themePackageName,
+ int flags, UserHandle user) throws NameNotFoundException {
final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
if (packageName.equals("system") || packageName.equals("android")) {
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
+ user, restricted, mDisplay, null, Display.INVALID_DISPLAY, themePackageName);
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
if (pi != null) {
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
- user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
+ user, restricted, mDisplay, null, Display.INVALID_DISPLAY, themePackageName);
if (c.mResources != null) {
return c;
}
@@ -1774,7 +1796,7 @@ class ContextImpl extends Context {
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread,
- packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
+ packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY, null);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetricsLocked());
return context;
@@ -1783,19 +1805,27 @@ class ContextImpl extends Context {
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
- packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
+ packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY, null);
}
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread, packageInfo, null, null, false,
- null, overrideConfiguration, displayId);
+ null, overrideConfiguration, displayId, null);
}
private ContextImpl(ContextImpl container, ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
Display display, Configuration overrideConfiguration, int createDisplayWithId) {
+ this(container, mainThread, packageInfo, activityToken, user, restricted, display,
+ overrideConfiguration, createDisplayWithId, null);
+ }
+
+ private ContextImpl(ContextImpl container, ActivityThread mainThread,
+ LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
+ Display display, Configuration overrideConfiguration, int createDisplayWithId,
+ String themePackageName) {
mOuterContext = this;
mMainThread = mainThread;
@@ -1829,16 +1859,27 @@ class ContextImpl extends Context {
mDisplay = (createDisplayWithId == Display.INVALID_DISPLAY) ? display
: ResourcesManager.getInstance().getAdjustedDisplay(displayId, mDisplayAdjustments);
+ // We need to create the content resolver before all the context resources creation because
+ // the content resolver is reference by the outer context while the theme information
+ // is created.
+ mContentResolver = new ApplicationContentResolver(this, mainThread, user);
+
Resources resources = packageInfo.getResources(mainThread);
if (resources != null) {
if (displayId != Display.DEFAULT_DISPLAY
+ || themePackageName != null
|| overrideConfiguration != null
|| (compatInfo != null && compatInfo.applicationScale
!= resources.getCompatibilityInfo().applicationScale)) {
- resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
- packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
+ resources = themePackageName == null ? mResourcesManager.getTopLevelResources(
+ packageInfo.getResDir(), packageInfo.getSplitResDirs(),
+ packageInfo.getOverlayDirs(),
packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
- overrideConfiguration, compatInfo);
+ packageInfo.getAppDir(), overrideConfiguration, compatInfo, mOuterContext,
+ packageInfo.getApplicationInfo().isThemeable) :
+ mResourcesManager.getTopLevelThemedResources(packageInfo.getResDir(), displayId,
+ packageInfo.getPackageName(), themePackageName, compatInfo,
+ packageInfo.getApplicationInfo().isThemeable);
}
}
mResources = resources;
@@ -1859,8 +1900,6 @@ class ContextImpl extends Context {
mOpPackageName = mBasePackageName;
}
}
-
- mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
@@ -1950,9 +1989,12 @@ class ContextImpl extends Context {
* unable to create, they are filtered by replacing with {@code null}.
*/
private File[] ensureDirsExistOrFilter(File[] dirs) {
- File[] result = new File[dirs.length];
+ ArrayList<File> result = new ArrayList<File>(dirs.length);
for (int i = 0; i < dirs.length; i++) {
File dir = dirs[i];
+ if (Environment.MEDIA_REMOVED.equals(Environment.getStorageState(dir))) {
+ continue;
+ }
if (!dir.exists()) {
if (!dir.mkdirs()) {
// recheck existence in case of cross-process race
@@ -1974,9 +2016,9 @@ class ContextImpl extends Context {
}
}
}
- result[i] = dir;
+ result.add(dir);
}
- return result;
+ return result.toArray(new File[result.size()]);
}
// ----------------------------------------------------------------------
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index fb0e79b..682ab97 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -266,6 +266,13 @@ public class DownloadManager {
*/
public final static int PAUSED_UNKNOWN = 4;
+ /**
+ * Value of {@link #COLUMN_REASON} when the download is paused by manual.
+ *
+ * @hide
+ */
+ public final static int PAUSED_BY_MANUAL = 5;
+
/**
* Broadcast intent action sent by the download manager when a download completes.
*/
@@ -865,6 +872,7 @@ public class DownloadManager {
parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY));
parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK));
parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI));
+ parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_MANUAL));
}
if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) {
parts.add(statusClause("=", Downloads.Impl.STATUS_SUCCESS));
@@ -1100,6 +1108,34 @@ public class DownloadManager {
}
/**
+ * Pause the given running download by manual.
+ *
+ * @param id the ID of the download to be paused
+ * @return the number of downloads actually updated
+ * @hide
+ */
+ public int pauseDownload(long id) {
+ ContentValues values = new ContentValues();
+ values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PAUSED_BY_MANUAL);
+
+ return mResolver.update(ContentUris.withAppendedId(mBaseUri, id), values, null, null);
+ }
+
+ /**
+ * Resume the given paused download by manual.
+ *
+ * @param id the ID of the download to be resumed
+ * @return the number of downloads actually updated
+ * @hide
+ */
+ public int resumeDownload(long id) {
+ ContentValues values = new ContentValues();
+ values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_RUNNING);
+
+ return mResolver.update(ContentUris.withAppendedId(mBaseUri, id), values, null, null);
+ }
+
+ /**
* Returns maximum size, in bytes, of downloads that may go over a mobile connection; or null if
* there's no limit
*
@@ -1335,6 +1371,9 @@ public class DownloadManager {
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
return PAUSED_QUEUED_FOR_WIFI;
+ case Downloads.Impl.STATUS_PAUSED_BY_MANUAL:
+ return PAUSED_BY_MANUAL;
+
default:
return PAUSED_UNKNOWN;
}
@@ -1390,6 +1429,7 @@ public class DownloadManager {
case Downloads.Impl.STATUS_WAITING_TO_RETRY:
case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
+ case Downloads.Impl.STATUS_PAUSED_BY_MANUAL:
return STATUS_PAUSED;
case Downloads.Impl.STATUS_SUCCESS:
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ef121ce..a27f9c8 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -122,6 +122,7 @@ public interface IActivityManager extends IInterface {
public void activitySlept(IBinder token) throws RemoteException;
public void activityDestroyed(IBinder token) throws RemoteException;
public String getCallingPackage(IBinder token) throws RemoteException;
+ public String getCallingPackageForBroadcast(boolean foreground) throws RemoteException;
public ComponentName getCallingActivity(IBinder token) throws RemoteException;
public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException;
public int addAppTask(IBinder activityToken, Intent intent,
@@ -411,7 +412,8 @@ public interface IActivityManager extends IInterface {
public void keyguardWaitingForActivityDrawn() throws RemoteException;
public void keyguardGoingAway(boolean disableWindowAnimations,
- boolean keyguardGoingToNotificationShade) throws RemoteException;
+ boolean keyguardGoingToNotificationShade,
+ boolean keyguardShowingMedia) throws RemoteException;
public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
throws RemoteException;
@@ -839,6 +841,10 @@ public interface IActivityManager extends IInterface {
int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240;
int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241;
int REGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+242;
+ // 243: Available
+
+ // start of CM transactions
+ int GET_CALLING_PACKAGE_FOR_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+244;
// Start of M transactions
int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 327c00b..4fdbfaa 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -35,6 +35,8 @@ interface IAlarmManager {
void remove(in PendingIntent operation);
long getNextWakeFromIdleTime();
AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
+ // update the uids being synchronized by network socket request manager
+ void updateBlockedUids(int uid, boolean isBlocked);
}
diff --git a/core/java/android/app/IBatteryService.aidl b/core/java/android/app/IBatteryService.aidl
new file mode 100644
index 0000000..196159b
--- /dev/null
+++ b/core/java/android/app/IBatteryService.aidl
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2016, The CyanogenMod 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;
+
+/**
+ * System private API for talking with the battery service.
+ *
+ * {@hide}
+ */
+interface IBatteryService {
+ boolean isDockBatterySupported();
+}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index ccba250..c717459 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -30,6 +30,12 @@ interface IWallpaperManager {
* Set the wallpaper.
*/
ParcelFileDescriptor setWallpaper(String name, in String callingPackage);
+
+ /**
+ * Set the keyguard wallpaper.
+ * @hide
+ */
+ ParcelFileDescriptor setKeyguardWallpaper(String name, in String callingPackage);
/**
* Set the live wallpaper.
@@ -46,6 +52,13 @@ interface IWallpaperManager {
*/
ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
out Bundle outParams);
+
+ /**
+ * Get the keyguard wallpaper.
+ * @hide
+ */
+ ParcelFileDescriptor getKeyguardWallpaper(IWallpaperManagerCallback cb,
+ out Bundle outParams);
/**
* Get information about a live wallpaper.
@@ -57,6 +70,12 @@ interface IWallpaperManager {
*/
void clearWallpaper(in String callingPackage);
+ /*
+ * Clear the keyguard wallpaper.
+ * @hide
+ */
+ void clearKeyguardWallpaper();
+
/**
* Return whether there is a wallpaper set with the given name.
*/
diff --git a/core/java/android/app/IWallpaperManagerCallback.aidl b/core/java/android/app/IWallpaperManagerCallback.aidl
index 991b2bc..b217318 100644
--- a/core/java/android/app/IWallpaperManagerCallback.aidl
+++ b/core/java/android/app/IWallpaperManagerCallback.aidl
@@ -28,4 +28,9 @@ oneway interface IWallpaperManagerCallback {
* Called when the wallpaper has changed
*/
void onWallpaperChanged();
+
+ /**
+ * Called when the keygaurd wallpaper has changed
+ */
+ void onKeyguardWallpaperChanged();
}
diff --git a/core/java/android/app/IconPackHelper.java b/core/java/android/app/IconPackHelper.java
new file mode 100644
index 0000000..80fb401
--- /dev/null
+++ b/core/java/android/app/IconPackHelper.java
@@ -0,0 +1,1062 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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 java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import android.content.pm.PackageInfo;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.graphics.drawable.VectorDrawable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.util.TypedValue;
+
+import com.android.internal.util.cm.palette.Palette;
+
+import org.cyanogenmod.internal.themes.IIconCacheManager;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ThemeUtils;
+import android.content.res.AssetManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+
+/** @hide */
+public class IconPackHelper {
+ private static final String TAG = IconPackHelper.class.getSimpleName();
+
+ private static final boolean DEBUG = false;
+
+ private static final String ICON_MASK_TAG = "iconmask";
+ private static final String ICON_BACK_TAG = "iconback";
+ private static final String ICON_UPON_TAG = "iconupon";
+ private static final String ICON_SCALE_TAG = "scale";
+ private static final String ICON_ROTATE_TAG = "rotate";
+ private static final String ICON_TRANSLATE_TAG = "translate";
+ private static final String ICON_BACK_FORMAT = "iconback%d";
+
+ // Palettized icon background constants
+ private static final String ICON_PALETTIZED_BACK_TAG = "paletteback";
+ private static final String IMG_ATTR = "img";
+ private static final String SWATCH_TYPE_ATTR = "swatchType";
+ private static final String DEFAULT_SWATCH_COLOR_ATTR = "defaultSwatchColor";
+ private static final String VIBRANT_VALUE = "vibrant";
+ private static final String VIBRANT_LIGHT_VALUE = "vibrantLight";
+ private static final String VIBRANT_DARK_VALUE = "vibrantDark";
+ private static final String MUTED_VALUE = "muted";
+ private static final String MUTED_LIGHT_VALUE = "mutedLight";
+ private static final String MUTED_DARK_VALUE = "mutedDark";
+ private static final int NUM_PALETTE_COLORS = 32;
+
+ // Rotation and translation constants
+ private static final String ANGLE_ATTR = "angle";
+ private static final String ANGLE_VARIANCE = "plusMinus";
+ private static final String TRANSLATE_X_ATTR = "xOffset";
+ private static final String TRANSLATE_Y_ATTR = "yOffset";
+
+ private static final ComponentName ICON_BACK_COMPONENT;
+ private static final ComponentName ICON_MASK_COMPONENT;
+ private static final ComponentName ICON_UPON_COMPONENT;
+ private static final ComponentName ICON_SCALE_COMPONENT;
+
+ private static final float DEFAULT_SCALE = 1.0f;
+ private static final int COMPOSED_ICON_COOKIE = 128;
+
+ private static final String ICON_CACHE_SERVICE = "cmiconcache";
+
+ public static final String SYSTEM_THEME_PATH = "/data/system/theme";
+ public static final String SYSTEM_THEME_ICON_CACHE_DIR = SYSTEM_THEME_PATH
+ + File.separator + "icons";
+
+ private final Context mContext;
+ private Map<ComponentName, String> mIconPackResourceMap;
+ private String mLoadedIconPackName;
+ private Resources mLoadedIconPackResource;
+ private ComposedIconInfo mComposedIconInfo;
+ private int mIconBackCount = 0;
+ private ColorFilterUtils.Builder mFilterBuilder;
+
+ static {
+ ICON_BACK_COMPONENT = new ComponentName(ICON_BACK_TAG, "");
+ ICON_MASK_COMPONENT = new ComponentName(ICON_MASK_TAG, "");
+ ICON_UPON_COMPONENT = new ComponentName(ICON_UPON_TAG, "");
+ ICON_SCALE_COMPONENT = new ComponentName(ICON_SCALE_TAG, "");
+ }
+
+ public IconPackHelper(Context context) {
+ mContext = context;
+ mIconPackResourceMap = new HashMap<ComponentName, String>();
+ ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ mComposedIconInfo = new ComposedIconInfo();
+ mComposedIconInfo.iconSize = am.getLauncherLargeIconSize();
+ mComposedIconInfo.iconDensity = am.getLauncherLargeIconDensity();
+ mFilterBuilder = new ColorFilterUtils.Builder();
+ }
+
+ private void loadResourcesFromXmlParser(XmlPullParser parser,
+ Map<ComponentName, String> iconPackResources)
+ throws XmlPullParserException, IOException {
+ mIconBackCount = 0;
+ int eventType = parser.getEventType();
+ do {
+
+ if (eventType != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parseComposedIconComponent(parser, iconPackResources)) {
+ continue;
+ }
+
+ if (ColorFilterUtils.parseIconFilter(parser, mFilterBuilder)) {
+ continue;
+ }
+
+ if (parser.getName().equalsIgnoreCase(ICON_SCALE_TAG)) {
+ String factor = parser.getAttributeValue(null, "factor");
+ if (factor == null) {
+ if (parser.getAttributeCount() == 1) {
+ factor = parser.getAttributeValue(0);
+ }
+ }
+ iconPackResources.put(ICON_SCALE_COMPONENT, factor);
+ continue;
+ }
+
+ if (parseRotationComponent(parser, mComposedIconInfo)) {
+ continue;
+ }
+
+ if (parseTranslationComponent(parser, mComposedIconInfo)) {
+ continue;
+ }
+
+ if (!parser.getName().equalsIgnoreCase("item")) {
+ continue;
+ }
+
+ String component = parser.getAttributeValue(null, "component");
+ String drawable = parser.getAttributeValue(null, "drawable");
+
+ // Validate component/drawable exist
+ if (TextUtils.isEmpty(component) || TextUtils.isEmpty(drawable)) {
+ continue;
+ }
+
+ // Validate format/length of component
+ if (!component.startsWith("ComponentInfo{") || !component.endsWith("}")
+ || component.length() < 16 || drawable.length() == 0) {
+ continue;
+ }
+
+ // Sanitize stored value
+ component = component.substring(14, component.length() - 1).toLowerCase();
+
+ ComponentName name = null;
+ if (!component.contains("/")) {
+ // Package icon reference
+ name = new ComponentName(component.toLowerCase(), "");
+ } else {
+ name = ComponentName.unflattenFromString(component);
+ }
+
+ if (name != null) {
+ iconPackResources.put(name, drawable);
+ }
+ } while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT);
+ }
+
+ private boolean isComposedIconComponent(String tag) {
+ return ICON_MASK_TAG.equalsIgnoreCase(tag) ||
+ ICON_BACK_TAG.equalsIgnoreCase(tag) ||
+ ICON_UPON_TAG.equalsIgnoreCase(tag) ||
+ ICON_PALETTIZED_BACK_TAG.equalsIgnoreCase(tag);
+ }
+
+ private boolean parseComposedIconComponent(XmlPullParser parser,
+ Map<ComponentName, String> iconPackResources) {
+ String icon;
+ String tag = parser.getName();
+ if (!isComposedIconComponent(tag)) {
+ return false;
+ }
+
+ if (parser.getAttributeCount() >= 1) {
+ if (ICON_BACK_TAG.equalsIgnoreCase(tag)) {
+ mIconBackCount = parser.getAttributeCount();
+ for (int i = 0; i < mIconBackCount; i++) {
+ tag = String.format(ICON_BACK_FORMAT, i);
+ icon = parser.getAttributeValue(i);
+ iconPackResources.put(new ComponentName(tag, ""), icon);
+ }
+ } else if (ICON_PALETTIZED_BACK_TAG.equalsIgnoreCase(tag)) {
+ parsePalettizedBackground(parser, mComposedIconInfo);
+ } else {
+ icon = parser.getAttributeValue(0);
+ iconPackResources.put(new ComponentName(tag, ""),
+ icon);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ private void parsePalettizedBackground(XmlPullParser parser, ComposedIconInfo iconInfo) {
+ int attrCount = parser.getAttributeCount();
+ ArrayList<Integer> convertedColors = new ArrayList<Integer>();
+ for (int i = 0; i < attrCount; i++) {
+ String name = parser.getAttributeName(i);
+ String value = parser.getAttributeValue(i);
+ if (TextUtils.isEmpty(name)) {
+ Log.w(TAG, "Attribute name cannot be empty or null");
+ continue;
+ }
+ if (TextUtils.isEmpty(value)) {
+ Log.w(TAG, "Attribute value cannot be empty or null");
+ continue;
+ }
+ if (IMG_ATTR.equalsIgnoreCase(name)) {
+ iconInfo.iconPaletteBack = getResourceIdForDrawable(value);
+ if (DEBUG) {
+ Log.d(TAG, String.format("img=%s, resId=%d", value,
+ iconInfo.iconPaletteBack));
+ }
+ } else if (SWATCH_TYPE_ATTR.equalsIgnoreCase(name)) {
+ ComposedIconInfo.SwatchType type = ComposedIconInfo.SwatchType.None;
+ if (VIBRANT_VALUE.equalsIgnoreCase(value)) {
+ type = ComposedIconInfo.SwatchType.Vibrant;
+ } else if (VIBRANT_LIGHT_VALUE.equalsIgnoreCase(value)) {
+ type = ComposedIconInfo.SwatchType.VibrantLight;
+ } else if (VIBRANT_DARK_VALUE.equalsIgnoreCase(value)) {
+ type = ComposedIconInfo.SwatchType.VibrantDark;
+ } else if (MUTED_VALUE.equalsIgnoreCase(value)) {
+ type = ComposedIconInfo.SwatchType.Muted;
+ } else if (MUTED_LIGHT_VALUE.equalsIgnoreCase(value)) {
+ type = ComposedIconInfo.SwatchType.MutedLight;
+ } else if (MUTED_DARK_VALUE.equalsIgnoreCase(value)) {
+ type = ComposedIconInfo.SwatchType.MutedDark;
+ }
+ if (type != ComposedIconInfo.SwatchType.None) {
+ iconInfo.swatchType = type;
+ if (DEBUG) Log.d(TAG, "PaletteType=" + type);
+ }
+ } else if (name.startsWith(DEFAULT_SWATCH_COLOR_ATTR)) {
+ try {
+ // ensure alpha is always 0xff
+ convertedColors.add(Color.parseColor(value) | 0xff000000);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Invalid color format", e);
+ }
+ }
+ if (convertedColors.size() > 0) {
+ iconInfo.defaultSwatchColors = new int[convertedColors.size()];
+ for (int j = 0; j < convertedColors.size(); j++) {
+ iconInfo.defaultSwatchColors[j] = convertedColors.get(j);
+ }
+ }
+ }
+ }
+
+ private boolean parseRotationComponent(XmlPullParser parser, ComposedIconInfo iconInfo) {
+ if (!parser.getName().equalsIgnoreCase(ICON_ROTATE_TAG)) return false;
+ String angle = parser.getAttributeValue(null, ANGLE_ATTR);
+ String variance = parser.getAttributeValue(null, ANGLE_VARIANCE);
+ if (angle != null) {
+ try {
+ iconInfo.iconRotation = Float.valueOf(angle);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Error parsing " + ANGLE_ATTR, e);
+ }
+ }
+ if (variance != null) {
+ try {
+ iconInfo.iconRotationVariance = Float.valueOf(variance);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Error parsing " + ANGLE_VARIANCE, e);
+ }
+ }
+ return true;
+ }
+
+ private boolean parseTranslationComponent(XmlPullParser parser, ComposedIconInfo iconInfo) {
+ if (!parser.getName().equalsIgnoreCase(ICON_TRANSLATE_TAG)) return false;
+
+ final float density = mContext.getResources().getDisplayMetrics().density;
+ String translateX = parser.getAttributeValue(null, TRANSLATE_X_ATTR);
+ String translateY = parser.getAttributeValue(null, TRANSLATE_Y_ATTR);
+ if (translateX != null) {
+ try {
+ iconInfo.iconTranslationX = Float.valueOf(translateX) * density;
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Error parsing " + TRANSLATE_X_ATTR, e);
+ }
+ }
+ if (translateY != null) {
+ try {
+ iconInfo.iconTranslationY = Float.valueOf(translateY) * density;
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Error parsing " + TRANSLATE_Y_ATTR, e);
+ }
+ }
+ return true;
+ }
+
+ public void loadIconPack(String packageName) throws NameNotFoundException {
+ if (packageName == null) {
+ mLoadedIconPackResource = null;
+ mLoadedIconPackName = null;
+ mComposedIconInfo.iconBacks = null;
+ mComposedIconInfo.iconMask = mComposedIconInfo.iconUpon = 0;
+ mComposedIconInfo.iconScale = 0;
+ mComposedIconInfo.iconRotation = 0;
+ mComposedIconInfo.iconTranslationX = 0;
+ mComposedIconInfo.iconTranslationY = 0;
+ mComposedIconInfo.colorFilter = null;
+ mComposedIconInfo.iconPaletteBack = 0;
+ mComposedIconInfo.swatchType = ComposedIconInfo.SwatchType.None;
+ } else {
+ mIconBackCount = 0;
+ Resources res = createIconResource(mContext, packageName);
+ mLoadedIconPackResource = res;
+ mLoadedIconPackName = packageName;
+ mIconPackResourceMap = getIconResMapFromXml(res, packageName);
+ loadComposedIconComponents();
+ ColorMatrix cm = mFilterBuilder.build();
+ if (cm != null) {
+ mComposedIconInfo.colorFilter = cm.getArray().clone();
+ }
+ }
+ }
+
+ public ComposedIconInfo getComposedIconInfo() {
+ return mComposedIconInfo;
+ }
+
+ private void loadComposedIconComponents() {
+ mComposedIconInfo.iconMask = getResourceIdForName(ICON_MASK_COMPONENT);
+ mComposedIconInfo.iconUpon = getResourceIdForName(ICON_UPON_COMPONENT);
+
+ // Take care of loading iconback which can have multiple images
+ if (mIconBackCount > 0) {
+ mComposedIconInfo.iconBacks = new int[mIconBackCount];
+ for (int i = 0; i < mIconBackCount; i++) {
+ mComposedIconInfo.iconBacks[i] =
+ getResourceIdForName(
+ new ComponentName(String.format(ICON_BACK_FORMAT, i), ""));
+ }
+ }
+
+ // Get the icon scale from this pack
+ String scale = mIconPackResourceMap.get(ICON_SCALE_COMPONENT);
+ if (scale != null) {
+ try {
+ mComposedIconInfo.iconScale = Float.valueOf(scale);
+ } catch (NumberFormatException e) {
+ mComposedIconInfo.iconScale = DEFAULT_SCALE;
+ }
+ } else {
+ mComposedIconInfo.iconScale = DEFAULT_SCALE;
+ }
+ }
+
+ private int getResourceIdForName(ComponentName component) {
+ String item = mIconPackResourceMap.get(component);
+ if (!TextUtils.isEmpty(item)) {
+ return getResourceIdForDrawable(item);
+ }
+ return 0;
+ }
+
+ public static Resources createIconResource(Context context, String packageName)
+ throws NameNotFoundException {
+ PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
+ String themeApk = info.applicationInfo.publicSourceDir;
+
+ String prefixPath;
+ String iconApkPath;
+ if (info.isLegacyIconPackApk) {
+ iconApkPath = "";
+ prefixPath = "";
+ } else {
+ prefixPath = ThemeUtils.ICONS_PATH; //path inside APK
+ iconApkPath = ThemeUtils.getIconPackApkPath(packageName);
+ }
+
+ AssetManager assets = new AssetManager();
+ assets.addIconPath(themeApk, iconApkPath,
+ prefixPath, Resources.THEME_ICON_PKG_ID);
+
+ DisplayMetrics dm = context.getResources().getDisplayMetrics();
+ Configuration config = context.getResources().getConfiguration();
+ Resources res = new Resources(assets, dm, config);
+ return res;
+ }
+
+ public Map<ComponentName, String> getIconResMapFromXml(Resources res, String packageName) {
+ XmlPullParser parser = null;
+ InputStream inputStream = null;
+ Map<ComponentName, String> iconPackResources = new HashMap<ComponentName, String>();
+
+ try {
+ inputStream = res.getAssets().open("appfilter.xml");
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ parser = factory.newPullParser();
+ parser.setInput(inputStream, "UTF-8");
+ } catch (Exception e) {
+ // Catch any exception since we want to fall back to parsing the xml/
+ // resource in all cases
+ int resId = res.getIdentifier("appfilter", "xml", packageName);
+ if (resId != 0) {
+ parser = res.getXml(resId);
+ }
+ }
+
+ if (parser != null) {
+ try {
+ loadResourcesFromXmlParser(parser, iconPackResources);
+ return iconPackResources;
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ // Cleanup resources
+ if (parser instanceof XmlResourceParser) {
+ ((XmlResourceParser) parser).close();
+ } else if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ // Application uses a different theme format (most likely launcher pro)
+ int arrayId = res.getIdentifier("theme_iconpack", "array", packageName);
+ if (arrayId == 0) {
+ arrayId = res.getIdentifier("icon_pack", "array", packageName);
+ }
+
+ if (arrayId != 0) {
+ String[] iconPack = res.getStringArray(arrayId);
+ ComponentName compName = null;
+ for (String entry : iconPack) {
+
+ if (TextUtils.isEmpty(entry)) {
+ continue;
+ }
+
+ String icon = entry;
+ entry = entry.replaceAll("_", ".");
+
+ compName = new ComponentName(entry.toLowerCase(), "");
+ iconPackResources.put(compName, icon);
+
+ int activityIndex = entry.lastIndexOf(".");
+ if (activityIndex <= 0 || activityIndex == entry.length() - 1) {
+ continue;
+ }
+
+ String iconPackage = entry.substring(0, activityIndex);
+ if (TextUtils.isEmpty(iconPackage)) {
+ continue;
+ }
+
+ String iconActivity = entry.substring(activityIndex + 1);
+ if (TextUtils.isEmpty(iconActivity)) {
+ continue;
+ }
+
+ // Store entries as lower case to ensure match
+ iconPackage = iconPackage.toLowerCase();
+ iconActivity = iconActivity.toLowerCase();
+
+ iconActivity = iconPackage + "." + iconActivity;
+ compName = new ComponentName(iconPackage, iconActivity);
+ iconPackResources.put(compName, icon);
+ }
+ }
+ return iconPackResources;
+ }
+
+ boolean isIconPackLoaded() {
+ return mLoadedIconPackResource != null &&
+ mLoadedIconPackName != null &&
+ mIconPackResourceMap != null;
+ }
+
+ private int getResourceIdForDrawable(String resource) {
+ int resId =
+ mLoadedIconPackResource.getIdentifier(resource, "drawable",mLoadedIconPackName);
+ return resId;
+ }
+
+ public int getResourceIdForActivityIcon(ActivityInfo info) {
+ if (!isIconPackLoaded()) {
+ return 0;
+ }
+ ComponentName compName = new ComponentName(info.packageName.toLowerCase(),
+ info.name.toLowerCase());
+ String drawable = mIconPackResourceMap.get(compName);
+ if (drawable != null) {
+ int resId = getResourceIdForDrawable(drawable);
+ if (resId != 0) return resId;
+ }
+
+ // Icon pack doesn't have an icon for the activity, fallback to package icon
+ compName = new ComponentName(info.packageName.toLowerCase(), "");
+ drawable = mIconPackResourceMap.get(compName);
+ if (drawable == null) {
+ return 0;
+ }
+ return getResourceIdForDrawable(drawable);
+ }
+
+ public int getResourceIdForApp(String pkgName) {
+ ActivityInfo info = new ActivityInfo();
+ info.packageName = pkgName;
+ info.name = "";
+ return getResourceIdForActivityIcon(info);
+ }
+
+ public Drawable getDrawableForActivity(ActivityInfo info) {
+ int id = getResourceIdForActivityIcon(info);
+ if (id == 0) return null;
+ return mLoadedIconPackResource.getDrawable(id, null, false);
+ }
+
+ public Drawable getDrawableForActivityWithDensity(ActivityInfo info, int density) {
+ int id = getResourceIdForActivityIcon(info);
+ if (id == 0) return null;
+ return mLoadedIconPackResource.getDrawableForDensity(id, density, null, false);
+ }
+
+ public static boolean shouldComposeIcon(ComposedIconInfo iconInfo) {
+ return iconInfo != null &&
+ (iconInfo.iconBacks != null ||
+ iconInfo.iconMask != 0 ||
+ iconInfo.iconUpon != 0 ||
+ iconInfo.colorFilter != null ||
+ iconInfo.iconPaletteBack != 0 ||
+ iconInfo.iconRotation != 0 ||
+ iconInfo.iconRotationVariance != 0 ||
+ iconInfo.iconTranslationX != 0 ||
+ iconInfo.iconTranslationY != 0 ||
+ iconInfo.iconScale != 1f);
+ }
+
+ public static class IconCustomizer {
+ private static final Random sRandom = new Random();
+ private static final IIconCacheManager sIconCacheManager;
+
+ static {
+ sIconCacheManager = IIconCacheManager.Stub.asInterface(
+ ServiceManager.getService(ICON_CACHE_SERVICE));
+ }
+
+ public static Drawable getComposedIconDrawable(Drawable icon, Context context,
+ ComposedIconInfo iconInfo) {
+ final Resources res = context.getResources();
+ return getComposedIconDrawable(icon, res, iconInfo);
+ }
+
+ public static Drawable getComposedIconDrawable(Drawable icon, Resources res,
+ ComposedIconInfo iconInfo) {
+ if (iconInfo == null) return icon;
+ int back = 0;
+ int defaultSwatchColor = 0;
+ if (iconInfo.swatchType != ComposedIconInfo.SwatchType.None) {
+ back = iconInfo.iconPaletteBack;
+ if (iconInfo.defaultSwatchColors.length > 0) {
+ defaultSwatchColor = iconInfo.defaultSwatchColors[
+ sRandom.nextInt(iconInfo.defaultSwatchColors.length)];
+ }
+ } else if (iconInfo.iconBacks != null && iconInfo.iconBacks.length > 0) {
+ back = iconInfo.iconBacks[sRandom.nextInt(iconInfo.iconBacks.length)];
+ }
+ Bitmap bmp = createIconBitmap(icon, res, back, defaultSwatchColor, iconInfo);
+ return bmp != null ? new BitmapDrawable(res, bmp): null;
+ }
+
+ public static void getValue(Resources res, int resId, TypedValue outValue,
+ Drawable baseIcon) {
+ final String pkgName = res.getAssets().getAppName();
+ final ComposedIconInfo iconInfo = res.getComposedIconInfo();
+ if (iconInfo == null) {
+ // No composed icon info available so return, keeping original value
+ return;
+ }
+ TypedValue tempValue = new TypedValue();
+ tempValue.setTo(outValue);
+ outValue.assetCookie = COMPOSED_ICON_COOKIE;
+ outValue.data = resId & (COMPOSED_ICON_COOKIE << 24 | 0x00ffffff);
+ outValue.string = getCachedIconPath(pkgName, resId, outValue.density);
+ int hashCode = outValue.string.hashCode() & 0x7fffffff;
+ int defaultSwatchColor = 0;
+
+ if (!(new File(outValue.string.toString()).exists())) {
+ // compose the icon and cache it
+ int back = 0;
+ if (iconInfo.swatchType != ComposedIconInfo.SwatchType.None) {
+ back = iconInfo.iconPaletteBack;
+ if (iconInfo.defaultSwatchColors.length > 0) {
+ defaultSwatchColor =iconInfo.defaultSwatchColors[
+ hashCode % iconInfo.defaultSwatchColors.length];
+ }
+ } else if (iconInfo.iconBacks != null && iconInfo.iconBacks.length > 0) {
+ back = iconInfo.iconBacks[hashCode % iconInfo.iconBacks.length];
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Composing icon for " + pkgName);
+ }
+ Bitmap bmp = createIconBitmap(baseIcon, res, back, defaultSwatchColor, iconInfo);
+ if (!cacheComposedIcon(bmp, getCachedIconName(pkgName, resId, outValue.density))) {
+ Log.w(TAG, "Unable to cache icon " + outValue.string);
+ // restore the original TypedValue
+ outValue.setTo(tempValue);
+ }
+ }
+ }
+
+ private static Bitmap createIconBitmap(Drawable icon, Resources res, int iconBack,
+ int defaultSwatchColor, ComposedIconInfo iconInfo) {
+ if (iconInfo.iconSize <= 0) return null;
+
+ final Canvas canvas = new Canvas();
+ canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.ANTI_ALIAS_FLAG,
+ Paint.FILTER_BITMAP_FLAG));
+
+ int width = 0, height = 0;
+ int backTintColor = 0;
+ if (icon instanceof PaintDrawable) {
+ PaintDrawable painter = (PaintDrawable) icon;
+ painter.setIntrinsicWidth(iconInfo.iconSize);
+ painter.setIntrinsicHeight(iconInfo.iconSize);
+
+ // A PaintDrawable does not have an exact size
+ width = iconInfo.iconSize;
+ height = iconInfo.iconSize;
+ } else if (icon instanceof BitmapDrawable) {
+ // Ensure the bitmap has a density.
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
+ Bitmap bitmap = bitmapDrawable.getBitmap();
+ if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
+ bitmapDrawable.setTargetDensity(res.getDisplayMetrics());
+ }
+ canvas.setDensity(bitmap.getDensity());
+
+ // If the original size of the icon isn't greater
+ // than twice the size of recommended large icons
+ // respect the original size of the icon
+ // otherwise enormous icons can easily create
+ // OOM situations.
+ if ((bitmap.getWidth() < (iconInfo.iconSize * 2))
+ && (bitmap.getHeight() < (iconInfo.iconSize * 2))) {
+ width = bitmap.getWidth();
+ height = bitmap.getHeight();
+ } else {
+ width = iconInfo.iconSize;
+ height = iconInfo.iconSize;
+ }
+ if (iconInfo.swatchType != ComposedIconInfo.SwatchType.None) {
+ Palette palette = Palette.generate(bitmap, NUM_PALETTE_COLORS);
+ switch (iconInfo.swatchType) {
+ case Vibrant:
+ backTintColor = palette.getVibrantColor(defaultSwatchColor);
+ break;
+ case VibrantLight:
+ backTintColor = palette.getLightVibrantColor(defaultSwatchColor);
+ break;
+ case VibrantDark:
+ backTintColor = palette.getDarkVibrantColor(defaultSwatchColor);
+ break;
+ case Muted:
+ backTintColor = palette.getMutedColor(defaultSwatchColor);
+ break;
+ case MutedLight:
+ backTintColor = palette.getLightMutedColor(defaultSwatchColor);
+ break;
+ case MutedDark:
+ backTintColor = palette.getDarkMutedColor(defaultSwatchColor);
+ break;
+ }
+ if (DEBUG) {
+ Log.d(TAG, String.format("palette tint color=0x%08x", backTintColor));
+ }
+ }
+ } else if (icon instanceof VectorDrawable) {
+ width = height = iconInfo.iconSize;
+ }
+
+ if (width <= 0 || height <= 0) return null;
+
+ Bitmap bitmap = Bitmap.createBitmap(width, height,
+ Bitmap.Config.ARGB_8888);
+ canvas.setBitmap(bitmap);
+
+ // Scale the original
+ Rect oldBounds = new Rect();
+ oldBounds.set(icon.getBounds());
+ icon.setBounds(0, 0, width, height);
+ canvas.save();
+ final float halfWidth = width / 2f;
+ final float halfHeight = height / 2f;
+ float angle = iconInfo.iconRotation;
+ if (iconInfo.iconRotationVariance != 0) {
+ angle += (sRandom.nextFloat() * (iconInfo.iconRotationVariance * 2))
+ - iconInfo.iconRotationVariance;
+ }
+ canvas.scale(iconInfo.iconScale, iconInfo.iconScale, halfWidth, halfHeight);
+ canvas.translate(iconInfo.iconTranslationX, iconInfo.iconTranslationY);
+ canvas.rotate(angle, halfWidth, halfHeight);
+ if (iconInfo.colorFilter != null) {
+ Paint p = null;
+ if (icon instanceof BitmapDrawable) {
+ p = ((BitmapDrawable) icon).getPaint();
+ } else if (icon instanceof PaintDrawable) {
+ p = ((PaintDrawable) icon).getPaint();
+ }
+ if (p != null) p.setColorFilter(new ColorMatrixColorFilter(iconInfo.colorFilter));
+ }
+ icon.draw(canvas);
+ canvas.restore();
+
+ // Mask off the original if iconMask is not null
+ if (iconInfo.iconMask != 0) {
+ Drawable mask = res.getDrawable(iconInfo.iconMask);
+ if (mask != null) {
+ mask.setBounds(icon.getBounds());
+ ((BitmapDrawable) mask).getPaint().setXfermode(
+ new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ mask.draw(canvas);
+ }
+ }
+ // Draw the iconBacks if not null and then the original (scaled and masked) icon on top
+ if (iconBack != 0) {
+ Drawable back = res.getDrawable(iconBack);
+ if (back != null) {
+ back.setBounds(icon.getBounds());
+ Paint paint = ((BitmapDrawable) back).getPaint();
+ paint.setXfermode(
+ new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
+ if (backTintColor != 0) {
+ paint.setColorFilter(new PorterDuffColorFilter(backTintColor,
+ PorterDuff.Mode.MULTIPLY));
+ }
+ back.draw(canvas);
+ }
+ }
+ // Finally draw the foreground if one was supplied
+ if (iconInfo.iconUpon != 0) {
+ Drawable upon = res.getDrawable(iconInfo.iconUpon);
+ if (upon != null) {
+ upon.setBounds(icon.getBounds());
+ upon.draw(canvas);
+ }
+ }
+ icon.setBounds(oldBounds);
+ bitmap.setDensity(canvas.getDensity());
+
+ return bitmap;
+ }
+
+ private static boolean cacheComposedIcon(Bitmap bmp, String path) {
+ try {
+ return sIconCacheManager.cacheComposedIcon(bmp, path);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to cache icon.", e);
+ }
+
+ return false;
+ }
+
+ private static String getCachedIconPath(String pkgName, int resId, int density) {
+ return String.format("%s/%s", SYSTEM_THEME_ICON_CACHE_DIR,
+ getCachedIconName(pkgName, resId, density));
+ }
+
+ private static String getCachedIconName(String pkgName, int resId, int density) {
+ return String.format("%s_%08x_%d.png", pkgName, resId, density);
+ }
+ }
+
+ public static class ColorFilterUtils {
+ private static final String TAG_FILTER = "filter";
+ private static final String FILTER_HUE = "hue";
+ private static final String FILTER_SATURATION = "saturation";
+ private static final String FILTER_INVERT = "invert";
+ private static final String FILTER_BRIGHTNESS = "brightness";
+ private static final String FILTER_CONTRAST = "contrast";
+ private static final String FILTER_ALPHA = "alpha";
+ private static final String FILTER_TINT = "tint";
+
+ private static final int MIN_HUE = -180;
+ private static final int MAX_HUE = 180;
+ private static final int MIN_SATURATION = 0;
+ private static final int MAX_SATURATION = 200;
+ private static final int MIN_BRIGHTNESS = 0;
+ private static final int MAX_BRIGHTNESS = 200;
+ private static final int MIN_CONTRAST = -100;
+ private static final int MAX_CONTRAST = 100;
+ private static final int MIN_ALPHA = 0;
+ private static final int MAX_ALPHA = 100;
+
+ public static boolean parseIconFilter(XmlPullParser parser, Builder builder)
+ throws IOException, XmlPullParserException {
+ String tag = parser.getName();
+ if (!TAG_FILTER.equals(tag)) return false;
+
+ int attrCount = parser.getAttributeCount();
+ String attrName;
+ String attr = null;
+ int intValue;
+ while (attrCount-- > 0) {
+ attrName = parser.getAttributeName(attrCount);
+ if (attrName.equals("name")) {
+ attr = parser.getAttributeValue(attrCount);
+ }
+ }
+ String content = parser.nextText();
+ if (attr != null && content != null && content.length() > 0) {
+ content = content.trim();
+ if (FILTER_HUE.equalsIgnoreCase(attr)) {
+ intValue = clampValue(getInt(content, 0),MIN_HUE, MAX_HUE);
+ builder.hue(intValue);
+ } else if (FILTER_SATURATION.equalsIgnoreCase(attr)) {
+ intValue = clampValue(getInt(content, 100),
+ MIN_SATURATION, MAX_SATURATION);
+ builder.saturate(intValue);
+ } else if (FILTER_INVERT.equalsIgnoreCase(attr)) {
+ if ("true".equalsIgnoreCase(content)) {
+ builder.invertColors();
+ }
+ } else if (FILTER_BRIGHTNESS.equalsIgnoreCase(attr)) {
+ intValue = clampValue(getInt(content, 100),
+ MIN_BRIGHTNESS, MAX_BRIGHTNESS);
+ builder.brightness(intValue);
+ } else if (FILTER_CONTRAST.equalsIgnoreCase(attr)) {
+ intValue = clampValue(getInt(content, 0),
+ MIN_CONTRAST, MAX_CONTRAST);
+ builder.contrast(intValue);
+ } else if (FILTER_ALPHA.equalsIgnoreCase(attr)) {
+ intValue = clampValue(getInt(content, 100), MIN_ALPHA, MAX_ALPHA);
+ builder.alpha(intValue);
+ } else if (FILTER_TINT.equalsIgnoreCase(attr)) {
+ try {
+ intValue = Color.parseColor(content);
+ builder.tint(intValue);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Cannot apply tint, invalid argument: " + content);
+ }
+ }
+ }
+ return true;
+ }
+
+ private static int getInt(String value, int defaultValue) {
+ try {
+ return Integer.valueOf(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ private static int clampValue(int value, int min, int max) {
+ return Math.min(max, Math.max(min, value));
+ }
+
+ /**
+ * See the following links for reference
+ * http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953
+ * http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html
+ * @param value
+ */
+ public static ColorMatrix adjustHue(float value) {
+ ColorMatrix cm = new ColorMatrix();
+ value = value / 180 * (float) Math.PI;
+ if (value != 0) {
+ float cosVal = (float) Math.cos(value);
+ float sinVal = (float) Math.sin(value);
+ float lumR = 0.213f;
+ float lumG = 0.715f;
+ float lumB = 0.072f;
+ float[] mat = new float[]{
+ lumR + cosVal * (1 - lumR) + sinVal * (-lumR),
+ lumG + cosVal * (-lumG) + sinVal * (-lumG),
+ lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
+ lumR + cosVal * (-lumR) + sinVal * (0.143f),
+ lumG + cosVal * (1 - lumG) + sinVal * (0.140f),
+ lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
+ lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)),
+ lumG + cosVal * (-lumG) + sinVal * (lumG),
+ lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1};
+ cm.set(mat);
+ }
+ return cm;
+ }
+
+ public static ColorMatrix adjustSaturation(float saturation) {
+ saturation = saturation / 100;
+ ColorMatrix cm = new ColorMatrix();
+ cm.setSaturation(saturation);
+
+ return cm;
+ }
+
+ public static ColorMatrix invertColors() {
+ float[] matrix = {
+ -1, 0, 0, 0, 255, //red
+ 0, -1, 0, 0, 255, //green
+ 0, 0, -1, 0, 255, //blue
+ 0, 0, 0, 1, 0 //alpha
+ };
+
+ return new ColorMatrix(matrix);
+ }
+
+ public static ColorMatrix adjustBrightness(float brightness) {
+ brightness = brightness / 100;
+ ColorMatrix cm = new ColorMatrix();
+ cm.setScale(brightness, brightness, brightness, 1);
+
+ return cm;
+ }
+
+ public static ColorMatrix adjustContrast(float contrast) {
+ contrast = contrast / 100 + 1;
+ float o = (-0.5f * contrast + 0.5f) * 255;
+ float[] matrix = {
+ contrast, 0, 0, 0, o, //red
+ 0, contrast, 0, 0, o, //green
+ 0, 0, contrast, 0, o, //blue
+ 0, 0, 0, 1, 0 //alpha
+ };
+
+ return new ColorMatrix(matrix);
+ }
+
+ public static ColorMatrix adjustAlpha(float alpha) {
+ alpha = alpha / 100;
+ ColorMatrix cm = new ColorMatrix();
+ cm.setScale(1, 1, 1, alpha);
+
+ return cm;
+ }
+
+ public static ColorMatrix applyTint(int color) {
+ float alpha = Color.alpha(color) / 255f;
+ float red = Color.red(color) * alpha;
+ float green = Color.green(color) * alpha;
+ float blue = Color.blue(color) * alpha;
+
+ float[] matrix = {
+ 1, 0, 0, 0, red, //red
+ 0, 1, 0, 0, green, //green
+ 0, 0, 1, 0, blue, //blue
+ 0, 0, 0, 1, 0 //alpha
+ };
+
+ return new ColorMatrix(matrix);
+ }
+
+ public static class Builder {
+ private List<ColorMatrix> mMatrixList;
+
+ public Builder() {
+ mMatrixList = new ArrayList<ColorMatrix>();
+ }
+
+ public Builder hue(float value) {
+ mMatrixList.add(adjustHue(value));
+ return this;
+ }
+
+ public Builder saturate(float saturation) {
+ mMatrixList.add(adjustSaturation(saturation));
+ return this;
+ }
+
+ public Builder brightness(float brightness) {
+ mMatrixList.add(adjustBrightness(brightness));
+ return this;
+ }
+
+ public Builder contrast(float contrast) {
+ mMatrixList.add(adjustContrast(contrast));
+ return this;
+ }
+
+ public Builder alpha(float alpha) {
+ mMatrixList.add(adjustAlpha(alpha));
+ return this;
+ }
+
+ public Builder invertColors() {
+ mMatrixList.add(ColorFilterUtils.invertColors());
+ return this;
+ }
+
+ public Builder tint(int color) {
+ mMatrixList.add(applyTint(color));
+ return this;
+ }
+
+ public ColorMatrix build() {
+ if (mMatrixList == null || mMatrixList.size() == 0) return null;
+
+ ColorMatrix colorMatrix = new ColorMatrix();
+ for (ColorMatrix cm : mMatrixList) {
+ colorMatrix.postConcat(cm);
+ }
+ return colorMatrix;
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 69b8b95..cddcd9f 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -374,6 +374,7 @@ public class Instrumentation {
* @see Context#startActivity
*/
public Activity startActivitySync(Intent intent) {
+ android.util.SeempLog.record_str(376, intent.toString());
validateNotAppThread();
synchronized (mSync) {
@@ -1481,6 +1482,7 @@ public class Instrumentation {
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
+ android.util.SeempLog.record_str(377, intent.toString());
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
@@ -1541,6 +1543,7 @@ public class Instrumentation {
public void execStartActivitiesAsUser(Context who, IBinder contextThread,
IBinder token, Activity target, Intent[] intents, Bundle options,
int userId) {
+ android.util.SeempLog.record_str(378, intents.toString());
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
@@ -1604,6 +1607,7 @@ public class Instrumentation {
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
+ android.util.SeempLog.record_str(377, intent.toString());
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
@@ -1664,6 +1668,7 @@ public class Instrumentation {
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options, UserHandle user) {
+ android.util.SeempLog.record_str(377, intent.toString());
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
@@ -1703,6 +1708,7 @@ public class Instrumentation {
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
int userId) {
+ android.util.SeempLog.record_str(379, intent.toString());
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
@@ -1741,6 +1747,7 @@ public class Instrumentation {
public void execStartActivityFromAppTask(
Context who, IBinder contextThread, IAppTask appTask,
Intent intent, Bundle options) {
+ android.util.SeempLog.record_str(380, intent.toString());
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index c2bf28a..76e55b7 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -546,7 +546,8 @@ public final class LoadedApk {
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
- mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
+ mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this,
+ mainThread.getSystemContext(), mPackageName);
}
return mResources;
}
@@ -601,7 +602,7 @@ public final class LoadedApk {
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);
- if (id == 0x01 || id == 0x7f) {
+ if (id == 0x01 || id == 0x7f || id == 0x3f) {
continue;
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 014c069..d8e01cd 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -898,6 +898,13 @@ public class Notification implements Parcelable
private Icon mLargeIcon;
/**
+ * Used by light picker in Settings to force
+ * notification lights on when screen is on
+ * @hide
+ */
+ public static final String EXTRA_FORCE_SHOW_LIGHTS = "android.forceShowLights";
+
+ /**
* Structure to encapsulate a named action that can be shown as part of this notification.
* It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is
* selected by the user.
diff --git a/core/java/android/app/NotificationGroup.aidl b/core/java/android/app/NotificationGroup.aidl
new file mode 100644
index 0000000..44b6290
--- /dev/null
+++ b/core/java/android/app/NotificationGroup.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2012, The CyanogenMod 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;
+
+parcelable NotificationGroup;
diff --git a/core/java/android/app/NotificationGroup.java b/core/java/android/app/NotificationGroup.java
new file mode 100644
index 0000000..bcb70d3
--- /dev/null
+++ b/core/java/android/app/NotificationGroup.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/** @hide */
+public class NotificationGroup implements Parcelable {
+ private static final String TAG = "NotificationGroup";
+
+ private String mName;
+ private int mNameResId;
+
+ private UUID mUuid;
+
+ private Set<String> mPackages = new HashSet<String>();
+
+ private boolean mDirty;
+
+ public static final Parcelable.Creator<NotificationGroup> CREATOR = new Parcelable.Creator<NotificationGroup>() {
+ public NotificationGroup createFromParcel(Parcel in) {
+ return new NotificationGroup(in);
+ }
+
+ @Override
+ public NotificationGroup[] newArray(int size) {
+ return new NotificationGroup[size];
+ }
+ };
+
+ public NotificationGroup(String name) {
+ this(name, -1, null);
+ }
+
+ public NotificationGroup(String name, int nameResId, UUID uuid) {
+ mName = name;
+ mNameResId = nameResId;
+ mUuid = (uuid != null) ? uuid : UUID.randomUUID();
+ mDirty = uuid == null;
+ }
+
+ private NotificationGroup(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public void setName(String name) {
+ mName = name;
+ mNameResId = -1;
+ mDirty = true;
+ }
+
+ public UUID getUuid() {
+ return mUuid;
+ }
+
+ public void addPackage(String pkg) {
+ mPackages.add(pkg);
+ mDirty = true;
+ }
+
+ public String[] getPackages() {
+ return mPackages.toArray(new String[mPackages.size()]);
+ }
+
+ public void removePackage(String pkg) {
+ mPackages.remove(pkg);
+ mDirty = true;
+ }
+
+ public boolean hasPackage(String pkg) {
+ return mPackages.contains(pkg);
+ }
+
+ public boolean isDirty() {
+ return mDirty;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mName);
+ dest.writeInt(mNameResId);
+ dest.writeInt(mDirty ? 1 : 0);
+ new ParcelUuid(mUuid).writeToParcel(dest, 0);
+ dest.writeStringArray(getPackages());
+ }
+
+ public void readFromParcel(Parcel in) {
+ mName = in.readString();
+ mNameResId = in.readInt();
+ mDirty = in.readInt() != 0;
+ mUuid = ParcelUuid.CREATOR.createFromParcel(in).getUuid();
+ mPackages.addAll(Arrays.asList(in.readStringArray()));
+ }
+
+ public void getXmlString(StringBuilder builder, Context context) {
+ builder.append("<notificationGroup ");
+ if (mNameResId > 0) {
+ builder.append("nameres=\"");
+ builder.append(context.getResources().getResourceEntryName(mNameResId));
+ } else {
+ builder.append("name=\"");
+ builder.append(TextUtils.htmlEncode(getName()));
+ }
+ builder.append("\" uuid=\"");
+ builder.append(TextUtils.htmlEncode(getUuid().toString()));
+ builder.append("\">\n");
+ for (String pkg : mPackages) {
+ builder.append("<package>" + TextUtils.htmlEncode(pkg) + "</package>\n");
+ }
+ builder.append("</notificationGroup>\n");
+ mDirty = false;
+ }
+
+ public static NotificationGroup fromXml(XmlPullParser xpp, Context context)
+ throws XmlPullParserException, IOException {
+ String value = xpp.getAttributeValue(null, "nameres");
+ int nameResId = -1;
+ String name = null;
+ UUID uuid = null;
+
+ if (value != null) {
+ nameResId = context.getResources().getIdentifier(value, "string", "android");
+ if (nameResId > 0) {
+ name = context.getResources().getString(nameResId);
+ }
+ }
+
+ if (name == null) {
+ name = xpp.getAttributeValue(null, "name");
+ }
+
+ value = xpp.getAttributeValue(null, "uuid");
+ if (value != null) {
+ try {
+ uuid = UUID.fromString(value);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "UUID not recognized for " + name + ", using new one.");
+ }
+ }
+
+ NotificationGroup notificationGroup = new NotificationGroup(name, nameResId, uuid);
+ int event = xpp.next();
+ while (event != XmlPullParser.END_TAG || !xpp.getName().equals("notificationGroup")) {
+ if (event == XmlPullParser.START_TAG) {
+ if (xpp.getName().equals("package")) {
+ String pkg = xpp.nextText();
+ notificationGroup.addPackage(pkg);
+ }
+ }
+ event = xpp.next();
+ }
+
+ /* we just loaded from XML, no need to save */
+ notificationGroup.mDirty = false;
+
+ return notificationGroup;
+ }
+}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 2117597..e2d0537 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -18,22 +18,38 @@ package android.app;
import static android.app.ActivityThread.DEBUG_CONFIGURATION;
+import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ThemeUtils;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.ThemeConfig;
import android.content.res.Resources;
import android.content.res.ResourcesKey;
+import android.graphics.Typeface;
import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayAdjustments;
import java.lang.ref.WeakReference;
+import java.util.List;
import java.util.Locale;
/** @hide */
@@ -48,9 +64,16 @@ public class ResourcesManager {
new ArrayMap<>();
CompatibilityInfo mResCompatibilityInfo;
+ static IPackageManager sPackageManager;
Configuration mResConfiguration;
+ /**
+ * Number of default assets attached to a Resource object's AssetManager
+ * This currently includes framework and cmsdk resources
+ */
+ private static final int NUM_DEFAULT_ASSETS = 2;
+
public static ResourcesManager getInstance() {
synchronized (ResourcesManager.class) {
if (sResourcesManager == null) {
@@ -156,12 +179,15 @@ public class ResourcesManager {
* @param compatInfo the compatibility info. Must not be null.
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs,
- String[] overlayDirs, String[] libDirs, int displayId,
- Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
+ String[] overlayDirs, String[] libDirs, int displayId, String packageName,
+ Configuration overrideConfiguration, CompatibilityInfo compatInfo, Context context,
+ boolean isThemeable) {
final float scale = compatInfo.applicationScale;
+ ThemeConfig themeConfig = getThemeConfig();
Configuration overrideConfigCopy = (overrideConfiguration != null)
? new Configuration(overrideConfiguration) : null;
- ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
+ ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
+ isThemeable, getThemeConfig());
Resources r;
synchronized (this) {
// Resources is app scale dependent.
@@ -184,6 +210,8 @@ public class ResourcesManager {
//}
AssetManager assets = new AssetManager();
+ assets.setAppName(packageName);
+ assets.setThemeSupport(isThemeable);
// resDir can be null if the 'android' package is creating a new Resources object.
// This is fine, since each AssetManager automatically loads the 'android' package
// already.
@@ -203,7 +231,7 @@ public class ResourcesManager {
if (overlayDirs != null) {
for (String idmapPath : overlayDirs) {
- assets.addOverlayPath(idmapPath);
+ assets.addOverlayPath(idmapPath, null, null, null, null);
}
}
@@ -213,7 +241,7 @@ public class ResourcesManager {
// Avoid opening files we know do not have resources,
// like code-only .jar files.
if (assets.addAssetPath(libDir) == 0) {
- Log.w(TAG, "Asset path '" + libDir +
+ Slog.w(TAG, "Asset path '" + libDir +
"' does not exist or contains no resources.");
}
}
@@ -237,10 +265,38 @@ public class ResourcesManager {
} else {
config = getConfiguration();
}
+
+ boolean iconsAttached = false;
+ /* Attach theme information to the resulting AssetManager when appropriate. */
+ if (config != null && !context.getPackageManager().isSafeMode()) {
+ if (themeConfig == null) {
+ try {
+ themeConfig = ThemeConfig.getBootTheme(context.getContentResolver());
+ } catch (Exception e) {
+ Slog.d(TAG, "ThemeConfig.getBootTheme failed, falling back to system theme", e);
+ themeConfig = ThemeConfig.getSystemTheme();
+ }
+ }
+
+ if (isThemeable) {
+ if (themeConfig != null) {
+ attachThemeAssets(assets, themeConfig);
+ attachCommonAssets(assets, themeConfig);
+ iconsAttached = attachIconAssets(assets, themeConfig);
+ }
+ } else if (themeConfig != null &&
+ !ThemeConfig.SYSTEM_DEFAULT.equals(themeConfig.getFontPkgName())) {
+ // use system fonts if not themeable and a theme font is currently in use
+ Typeface.recreateDefaults(true);
+ }
+ }
+
r = new Resources(assets, dm, config, compatInfo);
+ if (iconsAttached) setActivityIcons(r);
if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
+
synchronized (this) {
WeakReference<Resources> wr = mActiveResources.get(key);
Resources existing = wr != null ? wr.get() : null;
@@ -258,6 +314,152 @@ public class ResourcesManager {
}
}
+ /**
+ * Creates the top level Resources for applications with the given compatibility info.
+ *
+ * @param resDir the resource directory.
+ * @param compatInfo the compability info. Must not be null.
+ *
+ * @hide
+ */
+ public Resources getTopLevelThemedResources(String resDir, int displayId, String packageName,
+ String themePackageName, CompatibilityInfo compatInfo, boolean isThemeable) {
+ Resources r;
+
+ ThemeConfig.Builder builder = new ThemeConfig.Builder();
+ builder.defaultOverlay(themePackageName);
+ builder.defaultIcon(themePackageName);
+ builder.defaultFont(themePackageName);
+ ThemeConfig themeConfig = builder.build();
+
+ ResourcesKey key = new ResourcesKey(resDir, displayId, null, compatInfo.applicationScale,
+ isThemeable, themeConfig);
+
+ synchronized (this) {
+ WeakReference<Resources> wr = mActiveResources.get(key);
+ r = wr != null ? wr.get() : null;
+ if (r != null && r.getAssets().isUpToDate()) {
+ if (false) {
+ Slog.w(TAG, "Returning cached resources " + r + " " + resDir
+ + ": appScale=" + r.getCompatibilityInfo().applicationScale);
+ }
+ return r;
+ }
+ }
+
+ AssetManager assets = new AssetManager();
+ assets.setAppName(packageName);
+ assets.setThemeSupport(isThemeable);
+ if (assets.addAssetPath(resDir) == 0) {
+ return null;
+ }
+
+ //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
+ DisplayMetrics dm = getDisplayMetricsLocked(displayId);
+ Configuration config;
+ boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ final boolean hasOverrideConfig = key.hasOverrideConfiguration();
+ if (!isDefaultDisplay || hasOverrideConfig) {
+ config = new Configuration(getConfiguration());
+ if (!isDefaultDisplay) {
+ applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
+ }
+ if (hasOverrideConfig) {
+ config.updateFrom(key.mOverrideConfiguration);
+ }
+ } else {
+ config = getConfiguration();
+ }
+
+ boolean iconsAttached = false;
+ if (isThemeable) {
+ /* Attach theme information to the resulting AssetManager when appropriate. */
+ attachThemeAssets(assets, themeConfig);
+ attachCommonAssets(assets, themeConfig);
+ iconsAttached = attachIconAssets(assets, themeConfig);
+ }
+ r = new Resources(assets, dm, config, compatInfo);
+ if (iconsAttached) setActivityIcons(r);
+
+ if (false) {
+ Slog.i(TAG, "Created THEMED app resources " + resDir + " " + r + ": "
+ + r.getConfiguration() + " appScale="
+ + r.getCompatibilityInfo().applicationScale);
+ }
+
+ synchronized (this) {
+ WeakReference<Resources> wr = mActiveResources.get(key);
+ Resources existing = wr != null ? wr.get() : null;
+ if (existing != null && existing.getAssets().isUpToDate()) {
+ // Someone else already created the resources while we were
+ // unlocked; go ahead and use theirs.
+ r.getAssets().close();
+ return existing;
+ }
+
+ // XXX need to remove entries when weak references go away
+ mActiveResources.put(key, new WeakReference<Resources>(r));
+ return r;
+ }
+ }
+
+ /**
+ * Creates a map between an activity & app's icon ids to its component info. This map
+ * is then stored in the resource object.
+ * When resource.getDrawable(id) is called it will check this mapping and replace
+ * the id with the themed resource id if one is available
+ * @param r
+ */
+ private void setActivityIcons(Resources r) {
+ SparseArray<PackageItemInfo> iconResources = new SparseArray<PackageItemInfo>();
+ String pkgName = r.getAssets().getAppName();
+ PackageInfo pkgInfo = null;
+ ApplicationInfo appInfo = null;
+
+ try {
+ pkgInfo = getPackageManager().getPackageInfo(pkgName, PackageManager.GET_ACTIVITIES,
+ UserHandle.getCallingUserId());
+ } catch (RemoteException e1) {
+ Slog.e(TAG, "Unable to get pkg " + pkgName, e1);
+ return;
+ }
+
+ final ThemeConfig themeConfig = r.getConfiguration().themeConfig;
+ if (pkgName != null && themeConfig != null &&
+ pkgName.equals(themeConfig.getIconPackPkgName())) {
+ return;
+ }
+
+ //Map application icon
+ if (pkgInfo != null && pkgInfo.applicationInfo != null) {
+ appInfo = pkgInfo.applicationInfo;
+ if (appInfo.themedIcon != 0 || iconResources.get(appInfo.icon) == null) {
+ iconResources.put(appInfo.icon, appInfo);
+ }
+ }
+
+ //Map activity icons.
+ if (pkgInfo != null && pkgInfo.activities != null) {
+ for (ActivityInfo ai : pkgInfo.activities) {
+ if (ai.icon != 0 && (ai.themedIcon != 0 || iconResources.get(ai.icon) == null)) {
+ iconResources.put(ai.icon, ai);
+ } else if (appInfo != null && appInfo.icon != 0 &&
+ (ai.themedIcon != 0 || iconResources.get(appInfo.icon) == null)) {
+ iconResources.put(appInfo.icon, ai);
+ }
+ }
+ }
+
+ r.setIconResources(iconResources);
+ final IPackageManager pm = getPackageManager();
+ try {
+ ComposedIconInfo iconInfo = pm.getComposedIconInfo();
+ r.setComposedIconInfo(iconInfo);
+ } catch (Exception e) {
+ Slog.wtf(TAG, "Failed to retrieve ComposedIconInfo", e);
+ }
+ }
+
final boolean applyConfigurationToResourcesLocked(Configuration config,
CompatibilityInfo compat) {
if (mResConfiguration == null) {
@@ -303,6 +505,22 @@ public class ResourcesManager {
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
DisplayMetrics dm = defaultDisplayMetrics;
final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
+ boolean themeChanged = (changes & ActivityInfo.CONFIG_THEME_RESOURCE) != 0;
+ if (themeChanged) {
+ AssetManager am = r.getAssets();
+ if (am.hasThemeSupport()) {
+ r.setIconResources(null);
+ r.setComposedIconInfo(null);
+ detachThemeAssets(am);
+ if (config.themeConfig != null) {
+ attachThemeAssets(am, config.themeConfig);
+ attachCommonAssets(am, config.themeConfig);
+ if (attachIconAssets(am, config.themeConfig)) {
+ setActivityIcons(r);
+ }
+ }
+ }
+ }
if (!isDefaultDisplay || hasOverrideConfiguration) {
if (tmpConfig == null) {
tmpConfig = new Configuration();
@@ -319,6 +537,9 @@ public class ResourcesManager {
} else {
r.updateConfiguration(config, dm, compat);
}
+ if (themeChanged) {
+ r.updateStringCache();
+ }
//Slog.i(TAG, "Updated app resources " + v.getKey()
// + " " + r + ": " + r.getConfiguration());
} else {
@@ -330,4 +551,242 @@ public class ResourcesManager {
return changes != 0;
}
+ public static IPackageManager getPackageManager() {
+ if (sPackageManager != null) {
+ return sPackageManager;
+ }
+ IBinder b = ServiceManager.getService("package");
+ sPackageManager = IPackageManager.Stub.asInterface(b);
+ return sPackageManager;
+ }
+
+
+ /**
+ * Attach the necessary theme asset paths and meta information to convert an
+ * AssetManager to being globally "theme-aware".
+ *
+ * @param assets
+ * @param theme
+ * @return true if the AssetManager is now theme-aware; false otherwise.
+ * This can fail, for example, if the theme package has been been
+ * removed and the theme manager has yet to revert formally back to
+ * the framework default.
+ */
+ private boolean attachThemeAssets(AssetManager assets, ThemeConfig theme) {
+ PackageInfo piTheme = null;
+ PackageInfo piTarget = null;
+ PackageInfo piAndroid = null;
+
+ // Some apps run in process of another app (eg keyguard/systemUI) so we must get the
+ // package name from the res tables. The 0th base package name will be the android group.
+ // The 1st base package name will be the app group if one is attached. Check if it is there
+ // first or else the system will crash!
+ String basePackageName = null;
+ String resourcePackageName = null;
+ int count = assets.getBasePackageCount();
+ if (count > NUM_DEFAULT_ASSETS) {
+ basePackageName = assets.getBasePackageName(NUM_DEFAULT_ASSETS);
+ resourcePackageName = assets.getBaseResourcePackageName(NUM_DEFAULT_ASSETS);
+ } else if (count == NUM_DEFAULT_ASSETS) {
+ basePackageName = assets.getBasePackageName(0);
+ } else {
+ return false;
+ }
+
+ try {
+ piTheme = getPackageManager().getPackageInfo(
+ theme.getOverlayPkgNameForApp(basePackageName), 0,
+ UserHandle.getCallingUserId());
+ piTarget = getPackageManager().getPackageInfo(
+ basePackageName, 0, UserHandle.getCallingUserId());
+
+ // Handle special case where a system app (ex trebuchet) may have had its pkg name
+ // renamed during an upgrade. basePackageName would be the manifest value which will
+ // fail on getPackageInfo(). resource pkg is assumed to have the original name
+ if (piTarget == null && resourcePackageName != null) {
+ piTarget = getPackageManager().getPackageInfo(resourcePackageName,
+ 0, UserHandle.getCallingUserId());
+ }
+ piAndroid = getPackageManager().getPackageInfo("android", 0,
+ UserHandle.getCallingUserId());
+ } catch (RemoteException e) {
+ }
+
+ if (piTheme == null || piTheme.applicationInfo == null ||
+ piTarget == null || piTarget.applicationInfo == null ||
+ piAndroid == null || piAndroid.applicationInfo == null ||
+ piTheme.mOverlayTargets == null) {
+ return false;
+ }
+
+ String themePackageName = piTheme.packageName;
+ String themePath = piTheme.applicationInfo.publicSourceDir;
+ if (!piTarget.isThemeApk && piTheme.mOverlayTargets.contains(basePackageName)) {
+ String targetPackagePath = piTarget.applicationInfo.sourceDir;
+ String prefixPath = ThemeUtils.getOverlayPathToTarget(basePackageName);
+
+ String resCachePath = ThemeUtils.getTargetCacheDir(piTarget.packageName,
+ piTheme.packageName);
+ String resApkPath = resCachePath + "/resources.apk";
+ String idmapPath = ThemeUtils.getIdmapPath(piTarget.packageName, piTheme.packageName);
+ int cookie = assets.addOverlayPath(idmapPath, themePath, resApkPath,
+ targetPackagePath, prefixPath);
+
+ if (cookie != 0) {
+ assets.setThemePackageName(themePackageName);
+ assets.addThemeCookie(cookie);
+ }
+ }
+
+ if (!piTarget.isThemeApk && !"android".equals(basePackageName) &&
+ piTheme.mOverlayTargets.contains("android")) {
+ String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName,
+ piTheme.packageName);
+ String prefixPath = ThemeUtils.getOverlayPathToTarget(piAndroid.packageName);
+ String targetPackagePath = piAndroid.applicationInfo.publicSourceDir;
+ String resApkPath = resCachePath + "/resources.apk";
+ String idmapPath = ThemeUtils.getIdmapPath("android", piTheme.packageName);
+ int cookie = assets.addOverlayPath(idmapPath, themePath,
+ resApkPath, targetPackagePath, prefixPath);
+ if (cookie != 0) {
+ assets.setThemePackageName(themePackageName);
+ assets.addThemeCookie(cookie);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Attach the necessary icon asset paths. Icon assets should be in a different
+ * namespace than the standard 0x7F.
+ *
+ * @param assets
+ * @param theme
+ * @return true if succes, false otherwise
+ */
+ private boolean attachIconAssets(AssetManager assets, ThemeConfig theme) {
+ PackageInfo piIcon = null;
+ try {
+ piIcon = getPackageManager().getPackageInfo(theme.getIconPackPkgName(), 0,
+ UserHandle.getCallingUserId());
+ } catch (RemoteException e) {
+ }
+
+ if (piIcon == null || piIcon.applicationInfo == null) {
+ return false;
+ }
+
+ String iconPkg = theme.getIconPackPkgName();
+ if (iconPkg != null && !iconPkg.isEmpty()) {
+ String themeIconPath = piIcon.applicationInfo.publicSourceDir;
+ String prefixPath = ThemeUtils.ICONS_PATH;
+ String iconDir = ThemeUtils.getIconPackDir(iconPkg);
+ String resTablePath = iconDir + "/resources.arsc";
+ String resApkPath = iconDir + "/resources.apk";
+
+ // Legacy Icon packs have everything in their APK
+ if (piIcon.isLegacyIconPackApk) {
+ prefixPath = "";
+ resApkPath = "";
+ resTablePath = "";
+ }
+
+ int cookie = assets.addIconPath(themeIconPath, resApkPath, prefixPath,
+ Resources.THEME_ICON_PKG_ID);
+ if (cookie != 0) {
+ assets.setIconPackCookie(cookie);
+ assets.setIconPackageName(iconPkg);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Attach the necessary common asset paths. Common assets should be in a different
+ * namespace than the standard 0x7F.
+ *
+ * @param assets
+ * @param theme
+ * @return true if succes, false otherwise
+ */
+ private boolean attachCommonAssets(AssetManager assets, ThemeConfig theme) {
+ // Some apps run in process of another app (eg keyguard/systemUI) so we must get the
+ // package name from the res tables. The 0th base package name will be the android group.
+ // The 1st base package name will be the app group if one is attached. Check if it is there
+ // first or else the system will crash!
+ String basePackageName;
+ int count = assets.getBasePackageCount();
+ if (count > NUM_DEFAULT_ASSETS) {
+ basePackageName = assets.getBasePackageName(NUM_DEFAULT_ASSETS);
+ } else if (count == NUM_DEFAULT_ASSETS) {
+ basePackageName = assets.getBasePackageName(0);
+ } else {
+ return false;
+ }
+
+ PackageInfo piTheme = null;
+ try {
+ piTheme = getPackageManager().getPackageInfo(
+ theme.getOverlayPkgNameForApp(basePackageName), 0,
+ UserHandle.getCallingUserId());
+ } catch (RemoteException e) {
+ }
+
+ if (piTheme == null || piTheme.applicationInfo == null) {
+ return false;
+ }
+
+ String themePackageName =
+ ThemeUtils.getCommonPackageName(piTheme.applicationInfo.packageName);
+ if (themePackageName != null && !themePackageName.isEmpty()) {
+ String themePath = piTheme.applicationInfo.publicSourceDir;
+ String prefixPath = ThemeUtils.COMMON_RES_PATH;
+ String resCachePath =
+ ThemeUtils.getTargetCacheDir(ThemeUtils.COMMON_RES_TARGET, piTheme.packageName);
+ String resApkPath = resCachePath + "/resources.apk";
+ int cookie = assets.addCommonOverlayPath(themePath, resApkPath,
+ prefixPath);
+ if (cookie != 0) {
+ assets.setCommonResCookie(cookie);
+ assets.setCommonResPackageName(themePackageName);
+ }
+ }
+
+ return true;
+ }
+
+ private void detachThemeAssets(AssetManager assets) {
+ String themePackageName = assets.getThemePackageName();
+ String iconPackageName = assets.getIconPackageName();
+ String commonResPackageName = assets.getCommonResPackageName();
+
+ //Remove Icon pack if it exists
+ if (!TextUtils.isEmpty(iconPackageName) && assets.getIconPackCookie() > 0) {
+ assets.removeOverlayPath(iconPackageName, assets.getIconPackCookie());
+ assets.setIconPackageName(null);
+ assets.setIconPackCookie(0);
+ }
+ //Remove common resources if it exists
+ if (!TextUtils.isEmpty(commonResPackageName) && assets.getCommonResCookie() > 0) {
+ assets.removeOverlayPath(commonResPackageName, assets.getCommonResCookie());
+ assets.setCommonResPackageName(null);
+ assets.setCommonResCookie(0);
+ }
+ final List<Integer> themeCookies = assets.getThemeCookies();
+ if (!TextUtils.isEmpty(themePackageName) && !themeCookies.isEmpty()) {
+ // remove overlays in reverse order
+ for (int i = themeCookies.size() - 1; i >= 0; i--) {
+ assets.removeOverlayPath(themePackageName, themeCookies.get(i));
+ }
+ }
+ assets.getThemeCookies().clear();
+ assets.setThemePackageName(null);
+ }
+
+ private ThemeConfig getThemeConfig() {
+ final Configuration config = getConfiguration();
+ return config != null ? config.themeConfig : null;
+ }
}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 5e8ad68..fad3f62 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -92,6 +92,7 @@ public class StatusBarManager {
public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0;
public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1;
+ public static final int CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE = 2;
private Context mContext;
private IStatusBarService mService;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 3d264c6..34c967f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -254,7 +254,9 @@ final class SystemServiceRegistry {
new StaticServiceFetcher<BatteryManager>() {
@Override
public BatteryManager createService() {
- return new BatteryManager();
+ IBinder b = ServiceManager.getService(Context.BATTERY_SERVICE);
+ IBatteryService service = IBatteryService.Stub.asInterface(b);
+ return new BatteryManager(service);
}});
registerService(Context.NFC_SERVICE, NfcManager.class,
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 22e79b6..045ee39 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -33,6 +33,7 @@ import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
@@ -230,9 +231,10 @@ public class WallpaperManager {
private IWallpaperManager mService;
private Bitmap mWallpaper;
private Bitmap mDefaultWallpaper;
+ private Bitmap mKeyguardWallpaper;
private static final int MSG_CLEAR_WALLPAPER = 1;
-
+
Globals(Looper looper) {
IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
mService = IWallpaperManager.Stub.asInterface(b);
@@ -250,6 +252,12 @@ public class WallpaperManager {
}
}
+ public void onKeyguardWallpaperChanged() {
+ synchronized (this) {
+ mKeyguardWallpaper = null;
+ }
+ }
+
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
synchronized (this) {
if (mService != null) {
@@ -285,6 +293,23 @@ public class WallpaperManager {
}
}
+ /**
+ * @hide
+ */
+ public Bitmap peekKeyguardWallpaperBitmap(Context context) {
+ synchronized (this) {
+ if (mKeyguardWallpaper != null) {
+ return mKeyguardWallpaper;
+ }
+ try {
+ mKeyguardWallpaper = getCurrentKeyguardWallpaperLocked(context);
+ } catch (OutOfMemoryError e) {
+ Log.w(TAG, "No memory load current keyguard wallpaper", e);
+ }
+ return mKeyguardWallpaper;
+ }
+ }
+
public void forgetLoadedWallpaper() {
synchronized (this) {
mWallpaper = null;
@@ -292,6 +317,12 @@ public class WallpaperManager {
}
}
+ public void forgetLoadedKeyguardWallpaper() {
+ synchronized (this) {
+ mKeyguardWallpaper = null;
+ }
+ }
+
private Bitmap getCurrentWallpaperLocked(Context context) {
if (mService == null) {
Log.w(TAG, "WallpaperService not running");
@@ -321,7 +352,37 @@ public class WallpaperManager {
}
return null;
}
-
+
+ private Bitmap getCurrentKeyguardWallpaperLocked(Context context) {
+ if (mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ return null;
+ }
+ try {
+ Bundle params = new Bundle();
+ ParcelFileDescriptor fd = mService.getKeyguardWallpaper(this, params);
+ if (fd != null) {
+ try {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ Bitmap bm = BitmapFactory.decodeFileDescriptor(
+ fd.getFileDescriptor(), null, options);
+ return bm;
+ } catch (OutOfMemoryError e) {
+ Log.w(TAG, "Can't decode file", e);
+ } finally {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ return null;
+ }
+
private Bitmap getDefaultWallpaperLocked(Context context) {
InputStream is = openDefaultWallpaper(context);
if (is != null) {
@@ -340,6 +401,18 @@ public class WallpaperManager {
}
return null;
}
+
+ /** @hide */
+ public void clearKeyguardWallpaper() {
+ synchronized (this) {
+ try {
+ mService.clearKeyguardWallpaper();
+ } catch (RemoteException e) {
+ // ignore
+ }
+ mKeyguardWallpaper = null;
+ }
+ }
}
private static final Object sSync = new Object[0];
@@ -599,6 +672,15 @@ public class WallpaperManager {
return null;
}
+ /** @hide */
+ public Drawable getFastKeyguardDrawable() {
+ Bitmap bm = sGlobals.peekKeyguardWallpaperBitmap(mContext);
+ if (bm != null) {
+ return new FastBitmapDrawable(bm);
+ }
+ return null;
+ }
+
/**
* Like {@link #getFastDrawable()}, but if there is no wallpaper set,
* a null pointer is returned.
@@ -624,6 +706,13 @@ public class WallpaperManager {
}
/**
+ * @hide
+ */
+ public Bitmap getKeyguardBitmap() {
+ return sGlobals.peekKeyguardWallpaperBitmap(mContext);
+ }
+
+ /**
* Remove all internal references to the last loaded wallpaper. Useful
* for apps that want to reduce memory usage when they only temporarily
* need to have the wallpaper. After calling, the next request for the
@@ -636,6 +725,13 @@ public class WallpaperManager {
}
/**
+ * @hide
+ */
+ public void forgetLoadedKeyguardWallpaper() {
+ sGlobals.forgetLoadedKeyguardWallpaper();
+ }
+
+ /**
* If the current wallpaper is a live wallpaper component, return the
* information about that wallpaper. Otherwise, if it is a static image,
* simply return null.
@@ -787,6 +883,36 @@ public class WallpaperManager {
}
/**
+ * @param bitmap
+ * @throws IOException
+ * @hide
+ */
+ public void setKeyguardBitmap(Bitmap bitmap) throws IOException {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ return;
+ }
+ try {
+ ParcelFileDescriptor fd = sGlobals.mService.setKeyguardWallpaper(null,
+ mContext.getOpPackageName());
+ if (fd == null) {
+ return;
+ }
+ FileOutputStream fos = null;
+ try {
+ fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+
+ /**
* Change the current system wallpaper to a specific byte stream. The
* give InputStream is copied into persistent storage and will now be
* used as the wallpaper. Currently it must be either a JPEG or PNG
@@ -826,6 +952,34 @@ public class WallpaperManager {
}
}
+ /**
+ * @hide
+ */
+ public void setKeyguardStream(InputStream data) throws IOException {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ return;
+ }
+ try {
+ ParcelFileDescriptor fd = sGlobals.mService.setKeyguardWallpaper(null,
+ mContext.getOpPackageName());
+ if (fd == null) {
+ return;
+ }
+ FileOutputStream fos = null;
+ try {
+ fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ setWallpaper(data, fos);
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+
private void setWallpaper(InputStream data, FileOutputStream fos)
throws IOException {
byte[] buffer = new byte[32768];
@@ -1088,7 +1242,29 @@ public class WallpaperManager {
mWallpaperXStep = xStep;
mWallpaperYStep = yStep;
}
-
+
+ /** @hide */
+ public int getLastWallpaperX() {
+ try {
+ return WindowManagerGlobal.getWindowSession().getLastWallpaperX();
+ } catch (RemoteException e) {
+ // Ignore.
+ }
+
+ return -1;
+ }
+
+ /** @hide */
+ public int getLastWallpaperY() {
+ try {
+ return WindowManagerGlobal.getWindowSession().getLastWallpaperY();
+ } catch (RemoteException e) {
+ // Ignore.
+ }
+
+ return -1;
+ }
+
/**
* Send an arbitrary command to the current active wallpaper.
*
@@ -1162,7 +1338,25 @@ public class WallpaperManager {
* wallpaper.
*/
public void clear() throws IOException {
- setStream(openDefaultWallpaper(mContext));
+ clear(true);
+ }
+
+ /** @hide */
+ public void clear(boolean setToDefault) throws IOException {
+ if (setToDefault) {
+ setStream(openDefaultWallpaper(mContext));
+ } else {
+ Bitmap blackBmp = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
+ blackBmp.setPixel(0, 0, mContext.getResources().getColor(android.R.color.black));
+ setBitmap(blackBmp);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void clearKeyguardWallpaper() {
+ sGlobals.clearKeyguardWallpaper();
}
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e3414d9..5b9d9d5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4461,4 +4461,24 @@ public class DevicePolicyManager {
return PERMISSION_GRANT_STATE_DEFAULT;
}
}
+
+ /**
+ * CM: check if secure keyguard is required
+ * @hide
+ */
+ public boolean requireSecureKeyguard() {
+ return requireSecureKeyguard(UserHandle.myUserId());
+ }
+
+ /** @hide */
+ public boolean requireSecureKeyguard(int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.requireSecureKeyguard(userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to get secure keyguard requirement");
+ }
+ }
+ return true;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 376a3d8..a40507b 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -234,4 +234,6 @@ interface IDevicePolicyManager {
boolean setPermissionGrantState(in ComponentName admin, String packageName,
String permission, int grantState);
int getPermissionGrantState(in ComponentName admin, String packageName, String permission);
+
+ boolean requireSecureKeyguard(int userHandle);
}
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 7718a36..0335e28 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -21,6 +21,8 @@ import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
import android.os.*;
import android.os.Process;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -207,6 +209,8 @@ public class FullBackup {
final int mFullBackupContent;
final PackageManager mPackageManager;
+ final StorageManager mStorageManager;
+ final StorageVolume[] mVolumes;
final String mPackageName;
/**
@@ -230,6 +234,15 @@ public class FullBackup {
} else {
return null;
}
+ } else if (domainToken.startsWith(FullBackup.SHARED_PREFIX)) {
+ int slash = domainToken.indexOf('/');
+ int i = Integer.parseInt(domainToken.substring(slash + 1));
+
+ if (i < mVolumes.length) {
+ return mVolumes[i].getPath();
+ } else {
+ Log.e(TAG, "Could not find volume for " + domainToken);
+ }
} else if (domainToken.equals(FullBackup.NO_BACKUP_TREE_TOKEN)) {
return NOBACKUP_DIR.getCanonicalPath();
}
@@ -263,6 +276,8 @@ public class FullBackup {
SHAREDPREF_DIR = context.getSharedPrefsFile("foo").getParentFile();
CACHE_DIR = context.getCacheDir();
NOBACKUP_DIR = context.getNoBackupFilesDir();
+ mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+ mVolumes = mStorageManager.getVolumeList();
if (android.os.Process.myUid() != Process.SYSTEM_UID) {
EXTERNAL_DIR = context.getExternalFilesDir(null);
} else {
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 2e27345..74302f2 100644..100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -371,6 +371,89 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
}
/**
+ * Set priority of the profile
+ *
+ * <p> The device should already be paired.
+ * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
+ * {@link #PRIORITY_OFF},
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device Paired bluetooth device
+ * @param priority
+ * @return true if priority is set, false on error
+ * @hide
+ */
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ if (priority != BluetoothProfile.PRIORITY_OFF &&
+ priority != BluetoothProfile.PRIORITY_ON){
+ return false;
+ }
+ try {
+ return mService.setPriority(device, priority);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Get the priority of the profile.
+ *
+ * <p> The priority can be any of:
+ * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
+ * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device Bluetooth device
+ * @return priority of the device
+ * @hide
+ */
+ public int getPriority(BluetoothDevice device) {
+ if (VDBG) log("getPriority(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getPriority(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.PRIORITY_OFF;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.PRIORITY_OFF;
+ }
+
+ /**
+ * Check if A2DP profile is streaming music.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device BluetoothDevice device
+ */
+ public boolean isA2dpPlaying(BluetoothDevice device) {
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.isA2dpPlaying(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
* Helper for converting a state to a string.
*
* For debug use only - strings are not internationalized.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1f3ff51..f924bc1 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2009-2015 The Android Open Source Project
* Copyright (C) 2015 Samsung LSI
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +25,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.app.ActivityThread;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
@@ -92,7 +95,7 @@ import java.util.UUID;
*/
public final class BluetoothAdapter {
private static final String TAG = "BluetoothAdapter";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false;
/**
@@ -538,6 +541,7 @@ public final class BluetoothAdapter {
* @throws IllegalArgumentException if address is invalid
*/
public BluetoothDevice getRemoteDevice(String address) {
+ android.util.SeempLog.record(62);
return new BluetoothDevice(address);
}
@@ -553,6 +557,7 @@ public final class BluetoothAdapter {
* @throws IllegalArgumentException if address is invalid
*/
public BluetoothDevice getRemoteDevice(byte[] address) {
+ android.util.SeempLog.record(62);
if (address == null || address.length != 6) {
throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
}
@@ -762,7 +767,7 @@ public final class BluetoothAdapter {
try {
if (DBG) Log.d(TAG, "Calling enableBLE");
mManagerService.updateBleAppCount(mToken, true);
- return mManagerService.enable();
+ return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -784,6 +789,7 @@ public final class BluetoothAdapter {
@RequiresPermission(Manifest.permission.BLUETOOTH)
@AdapterState
public int getState() {
+ android.util.SeempLog.record(63);
try {
synchronized(mManagerCallback) {
if (mService != null)
@@ -880,6 +886,7 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
+ android.util.SeempLog.record(56);
int state = STATE_OFF;
if (isEnabled() == true){
if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
@@ -898,7 +905,7 @@ public final class BluetoothAdapter {
return true;
}
try {
- return mManagerService.enable();
+ return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -929,6 +936,7 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean disable() {
+ android.util.SeempLog.record(57);
try {
return mManagerService.disable(true);
} catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -946,6 +954,7 @@ public final class BluetoothAdapter {
* @hide
*/
public boolean disable(boolean persist) {
+ android.util.SeempLog.record(57);
try {
return mManagerService.disable(persist);
@@ -1190,6 +1199,7 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean startDiscovery() {
+ android.util.SeempLog.record(58);
if (getState() != STATE_ON) return false;
try {
synchronized(mManagerCallback) {
@@ -1408,6 +1418,7 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public Set<BluetoothDevice> getBondedDevices() {
+ android.util.SeempLog.record(61);
if (getState() != STATE_ON) {
return toDeviceSet(new BluetoothDevice[0]);
}
@@ -1460,6 +1471,7 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getProfileConnectionState(int profile) {
+ android.util.SeempLog.record(64);
if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
try {
synchronized(mManagerCallback) {
@@ -1582,6 +1594,7 @@ public final class BluetoothAdapter {
@RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
throws IOException {
+ android.util.SeempLog.record(59);
return createNewRfcommSocketAndRecord(name, uuid, false, false);
}
@@ -1754,6 +1767,117 @@ public final class BluetoothAdapter {
return listenUsingL2capOn(port, false, false);
}
+
+ /**
+ * Construct an insecure L2CAP server socket.
+ * Call #accept to retrieve connections to this socket.
+ * <p>To auto assign a port without creating a SDP record use
+ * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
+ * @param port the PSM to listen on
+ * @return An L2CAP BluetoothServerSocket
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient permissions.
+ * @hide
+ */
+ public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
+ BluetoothServerSocket socket = new BluetoothServerSocket(
+ BluetoothSocket.TYPE_L2CAP, false, false, port, false, false);
+ int errno = socket.mSocket.bindListen();
+ if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
+ socket.setChannel(socket.mSocket.getPort());
+ }
+ if (errno != 0) {
+ //TODO(BT): Throw the same exception error code
+ // that the previous code was using.
+ //socket.mSocket.throwErrnoNative(errno);
+ throw new IOException("Error: " + errno);
+ }
+ return socket;
+
+ }
+
+ /**
+ * Create a client side Message Access Profile Service Record.
+ * Create the record once, and reuse it for all connections.
+ * If changes to a record is needed remove the old record using {@link removeSdpRecord}
+ * and then create a new one.
+ * WARNING: This API requires removeSdpRecord() to be called, to avoid leaking resources!
+ * A second call to this function - either from two different apps or from the
+ * same app, without first calling removeSdpRecord() - will make the device
+ * break the Bluetooth spec, which could lead to severe IOP issues.
+ * @param serviceName The textual name of the service
+ * @param rfcommChannel The RFCOMM channel that clients can connect to
+ * (obtain from BluetoothServerSocket)
+ * @param l2capPsm The L2CAP PSM channel that clients can connect to
+ * (obtain from BluetoothServerSocket)
+ * Supply -1 to omit the L2CAP PSM from the record.
+ * @param version The Profile version number (As specified in the Bluetooth
+ * MAP specification)
+ * @param features The feature bit mask (As specified in the Bluetooth
+ * MAP specification)
+ * @return a handle to the record created. The record can be removed again
+ * using {@link removeSdpRecord}(). The record is not linked to the
+ * creation/destruction of BluetoothSockets, hence SDP record cleanup
+ * is a separate process.
+ * returns -1 if an error occure and the record was not created.
+ * @hide
+ */
+ public int createMapMnsSdpRecord(String serviceName, int rfcommChannel,
+ int l2capPsm, int version, int features) {
+ try {
+ return mService.createMapMnsSdpRecord(serviceName, rfcommChannel,
+ l2capPsm, version, features);
+ } catch (RemoteException e) {
+ Log.e(TAG, "createMapMnsSdpRecord: ", e);
+ }
+ return -1;
+ }
+
+ /**
+ * Create a client side Phonebook Access Profile Service Record.
+ * Create the record once, and reuse it for all connections.
+ * If changes to a record is needed remove the old record using {@link removeSdpRecord}
+ * and then create a new one.
+ * WARNING: This API requires removeSdpRecord() to be called, to avoid leaking resources!
+ * A second call to this function - either from two different apps or from the
+ * same app, without first calling removeSdpRecord() - will make the device
+ * break the Bluetooth spec, which could lead to severe IOP issues.
+ * @param serviceName The textual name of the service
+ * @param version The Profile version number (As specified in the Bluetooth
+ * PBAP specification)
+ * @return a handle to the record created. The record can be removed again
+ * using {@link removeSdpRecord}(). The record is not linked to the
+ * creation/destruction of BluetoothSockets, hence SDP record cleanup
+ * is a separate process.
+ * returns -1 if an error occure and the record was not created.
+ * @hide
+ */
+ public int createPbapPceSdpRecord(String serviceName, int version) {
+ try {
+ return mService.createPbapPceSdpRecord(serviceName, version);
+ } catch (RemoteException e) {
+ Log.e(TAG, "createPbapPceSdpRecord: ", e);
+ }
+ return -1;
+ }
+
+ /**
+ * Remove a SDP record created using createSdpRecord().
+ * This function shall be called before a new call to createSdpRecord for the same record
+ * type can be made, unless the record type created supports multiple instances.
+ * @param recordHandle handle of the record to remove - provided by createSdpRecord()
+ * @return true if success
+ * @hide
+ */
+ public boolean removeSdpRecord(int recordHandle){
+ try {
+ return mService.removeSdpRecord(recordHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "removeSdpRecord: ", e);
+ }
+ return false;
+ }
+
/**
* Read the local Out of Band Pairing Data
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
@@ -1825,6 +1949,9 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.PAN) {
BluetoothPan pan = new BluetoothPan(context, listener);
return true;
+ } else if (profile == BluetoothProfile.DUN) {
+ BluetoothDun dun = new BluetoothDun(context, listener);
+ return true;
} else if (profile == BluetoothProfile.HEALTH) {
BluetoothHealth health = new BluetoothHealth(context, listener);
return true;
@@ -1837,6 +1964,9 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.SAP) {
BluetoothSap sap = new BluetoothSap(context, listener);
return true;
+ } else if (profile == BluetoothProfile.HID_DEVICE) {
+ BluetoothHidDevice hidd = new BluetoothHidDevice(context, listener);
+ return true;
} else {
return false;
}
@@ -1881,6 +2011,10 @@ public final class BluetoothAdapter {
BluetoothPan pan = (BluetoothPan)proxy;
pan.close();
break;
+ case BluetoothProfile.DUN:
+ BluetoothDun dun = (BluetoothDun)proxy;
+ dun.close();
+ break;
case BluetoothProfile.HEALTH:
BluetoothHealth health = (BluetoothHealth)proxy;
health.close();
@@ -1905,6 +2039,10 @@ public final class BluetoothAdapter {
BluetoothSap sap = (BluetoothSap)proxy;
sap.close();
break;
+ case BluetoothProfile.HID_DEVICE:
+ BluetoothHidDevice hidd = (BluetoothHidDevice) proxy;
+ hidd.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index b53a8fc..4851087 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -210,7 +211,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
}
public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) {
- if (DBG) Log.d(TAG, "sendPassThroughCmd");
+ if (DBG) Log.d(TAG, "sendPassThroughCmd dev = " + device + " key " + keyCode + " State = " + keyState);
if (mService != null && isEnabled()) {
try {
mService.sendPassThroughCmd(device, keyCode, keyState);
@@ -223,6 +224,90 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
if (mService == null) Log.w(TAG, "Proxy not attached to service");
}
+ public void getMetaData(int[] attributeIds) {
+ if (DBG) Log.d(TAG, "getMetaData num requested Ids = " + attributeIds.length);
+ if (mService != null && isEnabled()) {
+ try {
+ mService.getMetaData(attributeIds);
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getMetaData", e);
+ return;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ }
+
+ public void getPlayStatus(int[] playStatusIds) {
+ if (DBG) Log.d(TAG, "getPlayStatus num requested Ids = "+ playStatusIds.length);
+ if (mService != null && isEnabled()) {
+ try {
+ mService.getPlayStatus(playStatusIds);
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getPlayStatus()", e);
+ return;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ }
+
+ public void getPlayerApplicationSetting() {
+ if (DBG) Log.d(TAG, "getPlayerApplicationSetting");
+ if (mService != null && isEnabled()) {
+ try {
+ mService.getPlayerApplicationSetting();
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getPlayerApplicationSetting()", e);
+ return;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ }
+
+ public void setPlayerApplicationSetting(int attributeId, int attributeVal) {
+ if (DBG) Log.d(TAG, "setPlayerApplicationSetting attribId = " + attributeId + " attribVal = " + attributeVal);
+ if (mService != null && isEnabled()) {
+ try {
+ mService.setPlayerApplicationSetting(attributeId, attributeVal);
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting()", e);
+ return;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ }
+
+ public BluetoothAvrcpInfo getSupportedPlayerAppSetting(BluetoothDevice device) {
+ if (DBG) Log.d(TAG, "getSupportedPlayerAppSetting dev = " + device);
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getSupportedPlayerAppSetting(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getSupportedPlayerAppSetting()", e);
+ return null;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return null;
+ }
+
+ public int getSupportedFeatures(BluetoothDevice device) {
+ if (DBG) Log.d(TAG, "getSupportedFeatures dev = " + device);
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getSupportedFeatures(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getSupportedFeatures()", e);
+ return 0;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return 0;
+ }
+
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothAvrcpInfo.aidl b/core/java/android/bluetooth/BluetoothAvrcpInfo.aidl
new file mode 100644
index 0000000..9b85c80
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAvrcpInfo.aidl
@@ -0,0 +1,34 @@
+/*
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothAvrcpInfo;
diff --git a/core/java/android/bluetooth/BluetoothAvrcpInfo.java b/core/java/android/bluetooth/BluetoothAvrcpInfo.java
new file mode 100644
index 0000000..a815d10
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAvrcpInfo.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package android.bluetooth;
+
+import java.util.ArrayList;
+import android.util.Log;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.BaseColumns;
+import android.net.Uri;
+
+/**
+ * Represents the AVRCP Metadata of remote Bluetooth Device.
+ *
+ * {@see BluetoothAvrcpController}
+ *
+ * {@hide}
+ */
+public final class BluetoothAvrcpInfo implements Parcelable, BaseColumns{
+
+ private byte[] supportedPlayerAttributes;// attributes supported
+ private byte[] numSupportedPlayerAttribValues; // number of values of each attribute
+ private String TAG = "BluetoothAvrcpInfo";
+ /*
+ * This would a list of values of all AttributeIds
+ */
+ private byte[] supportedPlayerAtribValues; // actual values lies here.
+
+ /* Default Constructor */
+ public BluetoothAvrcpInfo() {
+ supportedPlayerAttributes = null;
+ numSupportedPlayerAttribValues = null;
+ supportedPlayerAtribValues = null;
+ }
+ public BluetoothAvrcpInfo(byte[] attribIds, byte[] numValueSupported, byte[] valuesSupported) {
+ int numAttributes = attribIds.length;
+ int zz = 0;
+ supportedPlayerAttributes = new byte[numAttributes];
+ numSupportedPlayerAttribValues = new byte[numAttributes];
+ supportedPlayerAtribValues = new byte[valuesSupported.length];
+ for (zz = 0; zz < numAttributes; zz++) {
+ supportedPlayerAttributes[zz] = attribIds[zz];
+ numSupportedPlayerAttribValues[zz] = numValueSupported[zz];
+ }
+ for (zz = 0; zz < supportedPlayerAtribValues.length; zz++)
+ supportedPlayerAtribValues[zz] = valuesSupported[zz];
+ }
+ /*
+ * Reading Structure back from Paracel
+ */
+ public BluetoothAvrcpInfo(Parcel source){
+ ArrayList<Byte> attribs = new ArrayList<Byte>();
+ ArrayList<Byte> numAttribVal = new ArrayList<Byte>();
+ ArrayList<Byte> attribVals = new ArrayList<Byte>();
+ Byte numAttributes = source.readByte();
+ /*
+ * Read from Source
+ */
+ for(int xx = 0; xx < numAttributes ; xx++) {
+ attribs.add(source.readByte());
+ numAttribVal.add(source.readByte());
+ for (int zz = 0; zz < numAttribVal.get(xx); zz++) {
+ attribVals.add(source.readByte());
+ }
+ }
+
+ /*
+ * Write Back to Private Data Structures
+ */
+ supportedPlayerAttributes = new byte[attribs.size()];
+ for (int zz = 0; zz< attribs.size(); zz++) {
+ supportedPlayerAttributes[zz] = attribs.get(zz);
+ }
+
+ numSupportedPlayerAttribValues = new byte[numAttribVal.size()];
+ for (int zz = 0; zz< numAttribVal.size(); zz++) {
+ numSupportedPlayerAttribValues[zz] = numAttribVal.get(zz);
+ }
+
+ supportedPlayerAtribValues = new byte[attribVals.size()];
+ for (int zz = 0; zz< attribVals.size(); zz++) {
+ supportedPlayerAtribValues[zz] = attribVals.get(zz);
+ }
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ /* While flatenning the structure we would use the follwing way
+ * NumAttributes,ID, numValues, Values
+ */
+ public void writeToParcel(Parcel out, int flags) {
+ byte numSuppAttributes = (byte)supportedPlayerAttributes.length;
+ out.writeByte(numSuppAttributes);
+ for (int xx = 0; xx < numSuppAttributes; xx++) {
+ out.writeByte(supportedPlayerAttributes[xx]);
+ out.writeByte(numSupportedPlayerAttribValues[xx]);
+ for (int zz = 0; zz < numSupportedPlayerAttribValues[xx]; zz++) {
+ out.writeByte(supportedPlayerAtribValues[zz]);
+ }
+ }
+ }
+
+ public byte[] getSupportedPlayerAttributes() {
+ return supportedPlayerAttributes;
+ }
+
+ public byte getNumSupportedPlayerAttributeVal(byte playerAttributeId) {
+ for (int zz = 0; zz < supportedPlayerAttributes.length; zz++) {
+ if (playerAttributeId == supportedPlayerAttributes[zz]) {
+ return numSupportedPlayerAttribValues[zz];
+ }
+ }
+ return 0;
+ }
+
+ public byte[] getSupportedPlayerAttributeVlaues (byte playerAttributeId) {
+ int index = 0;
+ int zz = 0;
+ boolean attributeFound = false;
+ for (zz = 0; zz < supportedPlayerAttributes.length; zz++) {
+ if (playerAttributeId == supportedPlayerAttributes[zz]) {
+ attributeFound = true;
+ break;
+ }
+ else
+ index = index + numSupportedPlayerAttribValues[zz];
+ }
+ if (attributeFound) {
+ byte[] supportedValues = new byte[numSupportedPlayerAttribValues[zz]];
+ for (int xx = 0; xx < numSupportedPlayerAttribValues[zz]; xx++)
+ supportedValues[xx] = supportedPlayerAtribValues[xx + index];
+ return supportedValues;
+ }
+ else
+ return new byte[0];
+ }
+ public void putPlayerSettingAttributes(byte[] attribIds, byte[] numValueSupported, byte[] valuesSupported) {
+ int numAttributes = attribIds.length;
+ int zz = 0;
+ supportedPlayerAttributes = new byte[numAttributes];
+ numSupportedPlayerAttribValues = new byte[numAttributes];
+ supportedPlayerAtribValues = new byte[valuesSupported.length];
+ for (zz = 0; zz < numAttributes; zz++) {
+ supportedPlayerAttributes[zz] = attribIds[zz];
+ numSupportedPlayerAttribValues[zz] = numValueSupported[zz];
+ }
+ for (zz = 0; zz < supportedPlayerAtribValues.length; zz++)
+ supportedPlayerAtribValues[zz] = valuesSupported[zz];
+ }
+ public static final Parcelable.Creator<BluetoothAvrcpInfo> CREATOR =
+ new Parcelable.Creator<BluetoothAvrcpInfo>() {
+ public BluetoothAvrcpInfo createFromParcel(Parcel in) {
+ return new BluetoothAvrcpInfo(in);
+ }
+ public BluetoothAvrcpInfo[] newArray(int size) {
+ return new BluetoothAvrcpInfo[size];
+ }
+ };
+
+ public static final String PERMISSION_ACCESS = "android.permission.ACCESS_BLUETOOTH_AVRCP_CT_DATA";
+ public static final Uri CONTENT_URI = Uri.parse("content://com.android.bluetooth.avrcp/btavrcp_ct");
+
+ /*
+ * BaseColumns already has _ID and COUNT values
+ * Below mentioned strings are used to implement different columns
+ * of AVRCP MetaData table.
+ * TRACK_NUM : Ineteger value containing the order number of
+ * the audio-file on its original recording.
+ * Numeric ASCII string converted to Integer
+ * TITLE : Text field representing the title, song name
+ * ARTIST_NAME : Text field representing artist(s), performer(s)
+ * ALBUM_NAME : Text field representing the title of the recording
+ * (source) from which the audio in the file is taken.
+ * TOTAL_TRACKS : Integet value containing the total number of tracks
+ * or elements on the original recording.
+ * GENRE : Text field representing the category of the composition
+ * characterized by a particular style.
+ * PLAYING_TIME : Integer containing the length of the audio file in
+ * milliseconds for eg 02:30 = 150000
+ * PLAY_STATUS : Text feild showing current state of track. Possible
+ * values would be Playing, Stopped, Paused, Forward_Seek
+ * REV_SEEK
+ * REPEAT_STATUS : String describing Repeat mode status on remote Media Player
+ * Posible values "NOT SUPPORTED", "OFF" "Single Track Repeat"
+ * "All Track Repeat" "Group Repeat"
+ * SHUFFLE_STATUS : String describing Shuffle mode status on remote Media Player
+ * Posible values "NOT SUPPORTED", "OFF" "All Track Shuffle"
+ * "Group Shuffle"
+ * SCAN_STAUS : String describing SCAN mode status on remote Media Player
+ * Possible values "NOT SUPPORTED", "OFF","ALL Tracks Scan"
+ * "Group Scan"
+ *
+ * EQUALIZER_STATUS: String describing EQUALIZER mode status on remote Media Player
+ * Possible values "NOT SUPPORTED", "OFF","ON"
+ */
+ public static final String TRACK_NUM = "track_num";
+ public static final String TITLE = "title";
+ public static final String ARTIST_NAME = "artist_name";
+ public static final String ALBUM_NAME = "album_name";
+ public static final String TOTAL_TRACKS = "total_tracks";
+ public static final String GENRE = "genre";
+ public static final String PLAYING_TIME = "playing_time";
+ public static final String TOTAL_TRACK_TIME = "total_track_time";
+ public static final String PLAY_STATUS = "play_status";
+ public static final String REPEAT_STATUS = "repeat_status";
+ public static final String SHUFFLE_STATUS = "shuffle_status";
+ public static final String SCAN_STATUS = "scan_status";
+ public static final String EQUALIZER_STATUS = "equalizer_status";
+
+ /*
+ * Default values for each of the items
+ */
+ public static final int TRACK_NUM_INVALID = 0xFF;
+ public static final String TITLE_INVALID = "NOT_SUPPORTED";
+ public static final String ARTIST_NAME_INVALID = "NOT_SUPPORTED";
+ public static final String ALBUM_NAME_INVALID = "NOT_SUPPORTED";
+ public static final int TOTAL_TRACKS_INVALID = 0xFF;
+ public static final String GENRE_INVALID = "NOT_SUPPORTED";
+ public static final int PLAYING_TIME_INVALID = 0xFF;
+ public static final int TOTAL_TRACK_TIME_INVALID = 0xFF;
+ public static final String PLAY_STATUS_INVALID = "NOT_SUPPORTED";
+ public static final String REPEAT_STATUS_INVALID = "NOT_SUPPORTED";
+ public static final String SHUFFLE_STATUS_INVALID = "NOT_SUPPORTED";
+ public static final String SCAN_STATUS_INVALID = "NOT_SUPPORTED";
+ public static final String EQUALIZER_STATUS_INVALID = "NOT_SUPPORTED";
+
+ /*
+ *Element Id Values for GetMetaData
+ */
+ public static final int MEDIA_ATTRIBUTE_ALL = 0x00;
+ public static final int MEDIA_ATTRIBUTE_TITLE = 0x01;
+ public static final int MEDIA_ATTRIBUTE_ARTIST_NAME = 0x02;
+ public static final int MEDIA_ATTRIBUTE_ALBUM_NAME = 0x03;
+ public static final int MEDIA_ATTRIBUTE_TRACK_NUMBER = 0x04;
+ public static final int MEDIA_ATTRIBUTE_TOTAL_TRACK_NUMBER = 0x05;
+ public static final int MEDIA_ATTRIBUTE_GENRE = 0x06;
+ public static final int MEDIA_ATTRIBUTE_PLAYING_TIME = 0x07;
+
+ /*
+ *PlayStatusId Values for GetPlayStatus
+ */
+ public static final int MEDIA_PLAYSTATUS_ALL = 0x08;
+ public static final int MEDIA_PLAYSTATUS_SONG_TOTAL_LEN = 0x09;
+ public static final int MEDIA_PLAYSTATUS_SONG_CUR_POS = 0x0a;
+ public static final int MEDIA_PLAYSTATUS_SONG_PLAY_STATUS = 0x0b;
+
+ /*
+ * Values for SetPlayerApplicationSettings
+ */
+ public static final byte ATTRIB_EQUALIZER_STATUS = 0x01;
+ public static final byte ATTRIB_REPEAT_STATUS = 0x02;
+ public static final byte ATTRIB_SHUFFLE_STATUS = 0x03;
+ public static final byte ATTRIB_SCAN_STATUS = 0x04;
+
+ public static final byte EQUALIZER_STATUS_OFF = 0x01;
+ public static final byte EQUALIZER_STATUS_ON = 0x02;
+
+ public static final byte REPEAT_STATUS_OFF = 0x01;
+ public static final byte REPEAT_STATUS_SINGLE_TRACK_REPEAT = 0x02;
+ public static final byte REPEAT_STATUS_ALL_TRACK_REPEAT = 0x03;
+ public static final byte REPEAT_STATUS_GROUP_REPEAT = 0x04;
+
+ public static final byte SHUFFLE_STATUS_OFF = 0x01;
+ public static final byte SHUFFLE_STATUS_ALL_TRACK_SHUFFLE = 0x02;
+ public static final byte SHUFFLE_STATUS_GROUP_SHUFFLE = 0x03;
+
+ public static final byte SCAN_STATUS_OFF = 0x01;
+ public static final byte SCAN_STATUS_ALL_TRACK_SCAN = 0x02;
+ public static final byte SCAN_STATUS_GROUP_SCAN = 0x03;
+
+ public static final int BTRC_FEAT_METADATA = 0x01;
+ public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02;
+ public static final int BTRC_FEAT_BROWSE = 0x04;
+
+}
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 54bf4af..4a38287 100644..100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -283,6 +283,8 @@ public final class BluetoothClass implements Parcelable {
public static final int PROFILE_PANU = 4;
/** @hide */
public static final int PROFILE_NAP = 5;
+ /** @hide */
+ public static final int PROFILE_A2DP_SINK = 6;
/**
* Check class bits for possible bluetooth profile support.
@@ -310,6 +312,21 @@ public final class BluetoothClass implements Parcelable {
default:
return false;
}
+ } else if (profile == PROFILE_A2DP_SINK) {
+ if (hasService(Service.CAPTURE)) {
+ return true;
+ }
+ // By the A2DP spec, srcs must indicate the CAPTURE service.
+ // However if some device that do not, we try to
+ // match on some other class bits.
+ switch (getDeviceClass()) {
+ case Device.AUDIO_VIDEO_HIFI_AUDIO:
+ case Device.AUDIO_VIDEO_SET_TOP_BOX:
+ case Device.AUDIO_VIDEO_VCR :
+ return true;
+ default:
+ return false;
+ }
} else if (profile == PROFILE_HEADSET) {
// The render service class is required by the spec for HFP, so is a
// pretty good signal
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index cd5c205..b4006de 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1403,6 +1403,27 @@ public final class BluetoothDevice implements Parcelable {
}
/**
+ * Create an L2cap {@link BluetoothSocket} ready to start an insecure
+ * outgoing connection to this remote device on given channel.
+ * <p>The remote device will be not authenticated and communication on this
+ * socket will not be encrypted.
+ * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
+ * connection.
+ * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+ *
+ * @param channel L2cap PSM/channel to connect to
+ * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
+ * @throws IOException on error, for example Bluetooth not available, or
+ * insufficient permissions
+ * @hide
+ */
+ public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException {
+ return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel,
+ null);
+ }
+
+ /**
* Create an RFCOMM {@link BluetoothSocket} ready to start a secure
* outgoing connection to this remote device using SDP lookup of uuid.
* <p>This is designed to be used with {@link
diff --git a/core/java/android/bluetooth/BluetoothDevicePicker.java b/core/java/android/bluetooth/BluetoothDevicePicker.java
index c794be2..51d14cc 100644
--- a/core/java/android/bluetooth/BluetoothDevicePicker.java
+++ b/core/java/android/bluetooth/BluetoothDevicePicker.java
@@ -44,6 +44,14 @@ public interface BluetoothDevicePicker {
"android.bluetooth.devicepicker.action.DEVICE_SELECTED";
/**
+ * Broadcast when no BT device is selected from BT device picker screen.
+ * This happens when user presses back button.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEVICE_NOT_SELECTED =
+ "org.codeaurora.bluetooth.devicepicker.action.DEVICE_NOT_SELECTED";
+
+ /**
* Broadcast when someone want to select one BT device from devices list.
* This intent contains below extra data:
* - {@link #EXTRA_NEED_AUTH} (boolean): if need authentication
diff --git a/core/java/android/bluetooth/BluetoothDun.java b/core/java/android/bluetooth/BluetoothDun.java
new file mode 100644
index 0000000..0912061
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothDun.java
@@ -0,0 +1,296 @@
+/*
+*Copyright (c) 2013, The Linux Foundation. All rights reserved.
+*
+*Redistribution and use in source and binary forms, with or without
+*modification, are permitted provided that the following conditions are
+*met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+package android.bluetooth;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the APIs to control the Bluetooth Dun
+ * Profile.
+ *
+ *<p>BluetoothDun is a proxy object for controlling the Bluetooth DUN
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothDun proxy object.
+ *
+ *<p>Each method is protected with its appropriate permission.
+ *@hide
+ */
+public final class BluetoothDun implements BluetoothProfile {
+ private static final String TAG = "BluetoothDun";
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+
+ /**
+ * Intent used to broadcast the change in connection state of the Dun
+ * profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTED}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "codeaurora.bluetooth.dun.profile.action.CONNECTION_STATE_CHANGED";
+
+ private Context mContext;
+ private ServiceListener mServiceListener;
+ private BluetoothAdapter mAdapter;
+ private IBluetoothDun mDunService;
+
+ /**
+ * Create a BluetoothDun proxy object for interacting with the local
+ * Bluetooth Service which handles the Dun profile
+ *
+ */
+ /*package*/ BluetoothDun(Context context, ServiceListener l) {
+ mContext = context;
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ try {
+ mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
+ } catch (RemoteException re) {
+ Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re);
+ }
+ Log.d(TAG, "BluetoothDun() call bindService");
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothDun.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ android.os.Process.myUserHandle())) {
+ Log.e(TAG, "Could not bind to Bluetooth Dun Service with " + intent);
+ return false;
+ }
+ return true;
+ }
+
+
+ /*package*/ void close() {
+ if (VDBG) log("close()");
+ mServiceListener = null;
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mStateChangeCallback);
+ } catch (RemoteException re) {
+ Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re);
+ }
+ }
+
+ synchronized (mConnection) {
+ if ( mDunService != null) {
+ try {
+ mDunService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+
+ protected void finalize() {
+ close();
+ }
+
+ private IBluetoothStateChangeCallback mStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+
+ @Override
+ public void onBluetoothStateChange(boolean on) {
+ //Handle enable request to bind again.
+ Log.d(TAG, "onBluetoothStateChange on: " + on);
+ if (on) {
+ try {
+ if (mDunService == null) {
+ Log.d(TAG, "onBluetoothStateChange call bindService");
+ doBind();
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e);
+ }
+ } else {
+ if (VDBG) Log.d(TAG,"Unbinding service...");
+ synchronized (mConnection) {
+ if ( mDunService != null) {
+ try {
+ mDunService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Initiate disconnection from DUN server.
+ *
+ * <p> Once the disconnection is initiated by any device either local host
+ * or remote device, the state will transition from {@link #STATE_CONNECTED}
+ * to {@link #STATE_DISCONNECTED}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean disconnect(BluetoothDevice device) {
+ if (DBG) log("disconnect(" + device + ")");
+ if (mDunService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mDunService.disconnect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mDunService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (VDBG) log("getConnectedDevices()");
+ if (mDunService != null && isEnabled()) {
+ try {
+ return mDunService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mDunService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (VDBG) log("getDevicesMatchingStates()");
+ if (mDunService != null && isEnabled()) {
+ try {
+ return mDunService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mDunService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getConnectionState(BluetoothDevice device) {
+ if (VDBG) log("getState(" + device + ")");
+ if (mDunService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mDunService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mDunService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) Log.d(TAG, "BluetoothDUN Proxy object connected");
+ mDunService = IBluetoothDun.Stub.asInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.DUN,
+ BluetoothDun.this);
+ }
+ }
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) Log.d(TAG, "BluetoothDUN Proxy object disconnected");
+ mDunService = null;
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.DUN);
+ }
+ }
+ };
+
+ private boolean isEnabled() {
+ if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 09a15de..da81032 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -20,11 +20,11 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
-import android.os.Handler;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -47,7 +47,7 @@ import java.util.List;
public final class BluetoothHeadset implements BluetoothProfile {
private static final String TAG = "BluetoothHeadset";
private static final boolean DBG = true;
- private static final boolean VDBG = false;
+ private static final boolean VDBG = true;
/**
* Intent used to broadcast the change in connection state of the Headset
@@ -129,6 +129,13 @@ public final class BluetoothHeadset implements BluetoothProfile {
"android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
/**
+ * @hide Broadcast intent when HF indicator value changed is updated by HS.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_HF_INDICATOR_VALUE_CHANGED =
+ "codeaurora.bluetooth.headset.action.ACTION_HF_INDICATOR_VALUE_CHANGED";
+
+ /**
* A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
* intents that contains the name of the vendor-specific command.
*/
@@ -199,6 +206,20 @@ public final class BluetoothHeadset implements BluetoothProfile {
public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
/**
+ * @hide Used for sharing the HF indicator assigned number.
+ */
+ public static final String HF_INDICATOR_ASSIGNED_NUMBER =
+ "codeaurora.bluetooth.headset.intent.category.anum";
+
+
+ /**
+ * @hide Used for sharing the HF indicator assigned number's value.
+ */
+ public static final String HF_INDICATOR_ASSIGNED_NUMBER_VALUE =
+ "codeaurora.bluetooth.headset.intent.category.anumvalue";
+
+
+ /**
* Headset state when SCO audio is not connected.
* This state can be one of
* {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
@@ -222,8 +243,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
*/
public static final int STATE_AUDIO_CONNECTED = 12;
- private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100;
- private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101;
private Context mContext;
private ServiceListener mServiceListener;
@@ -236,7 +255,14 @@ public final class BluetoothHeadset implements BluetoothProfile {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG,"Unbinding service...");
- doUnbind();
+ synchronized (mConnection) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
} else {
synchronized (mConnection) {
try {
@@ -273,26 +299,15 @@ public final class BluetoothHeadset implements BluetoothProfile {
}
boolean doBind() {
- try {
- return mAdapter.getBluetoothManager().bindBluetoothProfileService(
- BluetoothProfile.HEADSET, mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to bind HeadsetService", e);
- }
- return false;
- }
-
- void doUnbind() {
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mAdapter.getBluetoothManager().unbindBluetoothProfileService(
- BluetoothProfile.HEADSET, mConnection);
- } catch (RemoteException e) {
- Log.e(TAG,"Unable to unbind HeadsetService", e);
- }
- }
+ Intent intent = new Intent(IBluetoothHeadset.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ UserHandle.CURRENT_OR_SELF)) {
+ Log.e(TAG, "Could not bind to Bluetooth Headset Service with " + intent);
+ return false;
}
+ return true;
}
/**
@@ -312,8 +327,18 @@ public final class BluetoothHeadset implements BluetoothProfile {
Log.e(TAG,"",e);
}
}
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
mServiceListener = null;
- doUnbind();
}
/**
@@ -969,21 +994,21 @@ public final class BluetoothHeadset implements BluetoothProfile {
return false;
}
- private final IBluetoothProfileServiceConnection mConnection
- = new IBluetoothProfileServiceConnection.Stub() {
- @Override
+ private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothHeadset.Stub.asInterface(service);
- mHandler.sendMessage(mHandler.obtainMessage(
- MESSAGE_HEADSET_SERVICE_CONNECTED));
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, BluetoothHeadset.this);
+ }
}
- @Override
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
- mHandler.sendMessage(mHandler.obtainMessage(
- MESSAGE_HEADSET_SERVICE_DISCONNECTED));
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
+ }
}
};
@@ -1007,25 +1032,4 @@ public final class BluetoothHeadset implements BluetoothProfile {
private static void log(String msg) {
Log.d(TAG, msg);
}
-
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_HEADSET_SERVICE_CONNECTED: {
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HEADSET,
- BluetoothHeadset.this);
- }
- break;
- }
- case MESSAGE_HEADSET_SERVICE_DISCONNECTED: {
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
- }
- break;
- }
- }
- }
- };
}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 874026f..484a856 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -100,7 +100,9 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* {@link #EXTRA_BATTERY_LEVEL},
* {@link #EXTRA_OPERATOR_NAME},
* {@link #EXTRA_VOICE_RECOGNITION},
- * {@link #EXTRA_IN_BAND_RING}</p>
+ * {@link #EXTRA_IN_BAND_RING}
+ * {@link #EXTRA_MANF_ID}
+ * {@link #EXTRA_MANF_MODEL}</p>
*/
public static final String ACTION_AG_EVENT =
"android.bluetooth.headsetclient.profile.action.AG_EVENT";
@@ -206,6 +208,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
"android.bluetooth.headsetclient.extra.SUBSCRIBER_INFO";
/**
+ * Extra for AG_EVENT intent indicates manufacturer identification.
+ * <p>Value: <code>String</code> containing manufacturer identification.</p>
+ */
+ public static final String EXTRA_MANF_ID =
+ "android.bluetooth.headsetclient.extra.MANF_ID";
+
+ /**
+ * Extra for AG_EVENT intent indicates manufacturer model.
+ * <p>Value: <code>String</code> containing manufacturer model.</p>
+ */
+ public static final String EXTRA_MANF_MODEL =
+ "android.bluetooth.headsetclient.extra.MANF_MODEL";
+
+
+ /**
* Extra for AG_CALL_CHANGED intent indicates the
* {@link BluetoothHeadsetClientCall} object that has changed.
*/
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
new file mode 100644
index 0000000..468df4d
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @hide
+ */
+public final class BluetoothHidDevice implements BluetoothProfile {
+
+ private static final String TAG = BluetoothHidDevice.class.getSimpleName();
+
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "codeaurora.bluetooth.hid.profile.action.CONNECTION_STATE_CHANGED";
+
+ /**
+ * Constants representing device subclass.
+ *
+ * @see #registerApp(String, String, String, byte, byte[],
+ * BluetoothHidDeviceCallback)
+ */
+ public static final byte SUBCLASS1_NONE = (byte) 0x00;
+ public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
+ public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
+ public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
+
+ public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
+ public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
+ public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
+ public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
+ public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
+ public static final byte SUBCLASS2_DIGITIZER_TABLED = (byte) 0x05;
+ public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
+
+ /**
+ * Constants representing report types.
+ *
+ * @see BluetoothHidDeviceCallback#onGetReport(byte, byte, int)
+ * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
+ * @see BluetoothHidDeviceCallback#onIntrData(byte, byte[])
+ */
+ public static final byte REPORT_TYPE_INPUT = (byte) 1;
+ public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
+ public static final byte REPORT_TYPE_FEATURE = (byte) 3;
+
+ /**
+ * Constants representing error response for Set Report.
+ *
+ * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])
+ */
+ public static final byte ERROR_RSP_SUCCESS = (byte) 0;
+ public static final byte ERROR_RSP_NOT_READY = (byte) 1;
+ public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
+ public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
+ public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
+ public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
+
+ /**
+ * Constants representing protocol mode used set by host. Default is always
+ * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise.
+ *
+ * @see BluetoothHidDeviceCallback#onSetProtocol(byte)
+ */
+ public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
+ public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
+
+ private Context mContext;
+
+ private ServiceListener mServiceListener;
+
+ private IBluetoothHidDevice mService;
+
+ private BluetoothAdapter mAdapter;
+
+ private static class BluetoothHidDeviceCallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
+
+ private BluetoothHidDeviceCallback mCallback;
+
+ public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onAppStatusChanged(BluetoothDevice pluggedDevice,
+ BluetoothHidDeviceAppConfiguration config, boolean registered) {
+ mCallback.onAppStatusChanged(pluggedDevice, config, registered);
+ }
+
+ @Override
+ public void onConnectionStateChanged(BluetoothDevice device, int state) {
+ mCallback.onConnectionStateChanged(device, state);
+ }
+
+ @Override
+ public void onGetReport(byte type, byte id, int bufferSize) {
+ mCallback.onGetReport(type, id, bufferSize);
+ }
+
+ @Override
+ public void onSetReport(byte type, byte id, byte[] data) {
+ mCallback.onSetReport(type, id, data);
+ }
+
+ @Override
+ public void onSetProtocol(byte protocol) {
+ mCallback.onSetProtocol(protocol);
+ }
+
+ @Override
+ public void onIntrData(byte reportId, byte[] data) {
+ mCallback.onIntrData(reportId, data);
+ }
+
+ @Override
+ public void onVirtualCableUnplug() {
+ mCallback.onVirtualCableUnplug();
+ }
+ }
+
+ final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+
+ public void onBluetoothStateChange(boolean up) {
+ Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ synchronized (mConnection) {
+ if (!up) {
+ Log.d(TAG,"Unbinding service...");
+ if (mService != null) {
+ mService = null;
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG,"onBluetoothStateChange: could not unbind service:", e);
+ }
+ }
+ } else {
+ try {
+ if (mService == null) {
+ Log.d(TAG,"Binding HID Device service...");
+ doBind();
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e);
+ }
+ }
+ }
+ }
+ };
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.d(TAG, "onServiceConnected()");
+
+ mService = IBluetoothHidDevice.Stub.asInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.HID_DEVICE,
+ BluetoothHidDevice.this);
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ Log.d(TAG, "onServiceDisconnected()");
+
+ mService = null;
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
+ }
+ }
+ };
+
+ BluetoothHidDevice(Context context, ServiceListener listener) {
+ Log.v(TAG, "BluetoothHidDevice");
+
+ mContext = context;
+ mServiceListener = listener;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothHidDevice.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ android.os.Process.myUserHandle())) {
+ Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
+ return false;
+ }
+ Log.d(TAG, "Bound to HID Device Service");
+ return true;
+ }
+
+ void close() {
+ Log.v(TAG, "close()");
+
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ mService = null;
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG,"close: could not unbind HID Dev service: ", e);
+ }
+ }
+ }
+
+ mServiceListener = null;
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices() {
+ Log.v(TAG, "getConnectedDevices()");
+ return null;
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
+ return null;
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device) {
+ Log.v(TAG, "getConnectionState(): device=" + device.getAddress());
+
+ return STATE_DISCONNECTED;
+ }
+
+ /**
+ * Registers application to be used for HID device. Connections to HID
+ * Device are only possible when application is registered. Only one
+ * application can be registered at time. When no longer used, application
+ * should be unregistered using
+ * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}.
+ *
+ * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of
+ * HID Device SDP record.
+ * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of
+ * Incoming QoS Settings.
+ * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of
+ * Outgoing QoS Settings.
+ * @param callback {@link BluetoothHidDeviceCallback} object to which
+ * callback messages will be sent.
+ * @return
+ */
+ public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
+ BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
+ BluetoothHidDeviceCallback callback) {
+ Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
+ + " callback=" + callback);
+
+ boolean result = false;
+
+ if (sdp == null || callback == null) {
+ return false;
+ }
+
+ if (mService != null) {
+ try {
+ BluetoothHidDeviceAppConfiguration config =
+ new BluetoothHidDeviceAppConfiguration();
+ BluetoothHidDeviceCallbackWrapper cbw =
+ new BluetoothHidDeviceCallbackWrapper(callback);
+ result = mService.registerApp(config, sdp, inQos, outQos, cbw);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Unregisters application. Active connection will be disconnected and no
+ * new connections will be allowed until registered again using
+ * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
+ *
+ * @param config {@link BluetoothHidDeviceAppConfiguration} object as
+ * obtained from
+ * {@link BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice,
+ * BluetoothHidDeviceAppConfiguration, boolean)}
+ *
+ * @return
+ */
+ public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) {
+ Log.v(TAG, "unregisterApp()");
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.unregisterApp(config);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Sends report to remote host using interrupt channel.
+ *
+ * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id
+ * are not defined in descriptor.
+ * @param data Report data, not including Report Id.
+ * @return
+ */
+ public boolean sendReport(int id, byte[] data) {
+ Log.v(TAG, "sendReport(): id=" + id);
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.sendReport(id, data);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Sends report to remote host as reply for GET_REPORT request from
+ * {@link BluetoothHidDeviceCallback#onGetReport(byte, byte, int)}.
+ *
+ * @param type Report Type, as in request.
+ * @param id Report Id, as in request.
+ * @param data Report data, not including Report Id.
+ * @return
+ */
+ public boolean replyReport(byte type, byte id, byte[] data) {
+ Log.v(TAG, "replyReport(): type=" + type + " id=" + id);
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.replyReport(type, id, data);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Sends error handshake message as reply for invalid SET_REPORT request
+ * from {@link BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])}.
+ *
+ * @param error Error to be sent for SET_REPORT via HANDSHAKE.
+ * @return
+ */
+ public boolean reportError(byte error) {
+ Log.v(TAG, "reportError(): error = " + error);
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.reportError(error);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Sends Virtual Cable Unplug to currently connected host.
+ *
+ * @return
+ */
+ public boolean unplug() {
+ Log.v(TAG, "unplug()");
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.unplug();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Initiates connection to host which currently has Virtual Cable
+ * established with device.
+ *
+ * @return
+ */
+ public boolean connect() {
+ Log.v(TAG, "connect()");
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.connect();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+
+ /**
+ * Disconnects from currently connected host.
+ *
+ * @return
+ */
+ public boolean disconnect() {
+ Log.v(TAG, "disconnect()");
+
+ boolean result = false;
+
+ if (mService != null) {
+ try {
+ result = mService.disconnect();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return result;
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl
new file mode 100644
index 0000000..1af309c
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl
@@ -0,0 +1,21 @@
+/*
+** Copyright (C) 2013 The Linux Foundation. All rights reserved
+** Not a Contribution.
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHidDeviceAppConfiguration;
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java
new file mode 100644
index 0000000..9f3cd3c
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Random;
+
+/** @hide */
+public final class BluetoothHidDeviceAppConfiguration implements Parcelable {
+ private final long mHash;
+
+ BluetoothHidDeviceAppConfiguration() {
+ Random rnd = new Random();
+ mHash = rnd.nextLong();
+ }
+
+ BluetoothHidDeviceAppConfiguration(long hash) {
+ mHash = hash;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothHidDeviceAppConfiguration) {
+ BluetoothHidDeviceAppConfiguration config = (BluetoothHidDeviceAppConfiguration) o;
+ return mHash == config.mHash;
+ }
+ return false;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothHidDeviceAppConfiguration> CREATOR =
+ new Parcelable.Creator<BluetoothHidDeviceAppConfiguration>() {
+
+ @Override
+ public BluetoothHidDeviceAppConfiguration createFromParcel(Parcel in) {
+ long hash = in.readLong();
+ return new BluetoothHidDeviceAppConfiguration(hash);
+ }
+
+ @Override
+ public BluetoothHidDeviceAppConfiguration[] newArray(int size) {
+ return new BluetoothHidDeviceAppConfiguration[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeLong(mHash);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
new file mode 100644
index 0000000..ae93235
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
@@ -0,0 +1,21 @@
+/*
+** Copyright (C) 2013 The Linux Foundation. All rights reserved
+** Not a Contribution.
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHidDeviceAppQosSettings;
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
new file mode 100644
index 0000000..a4044d9
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Random;
+
+/** @hide */
+public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
+
+ final public int serviceType;
+ final public int tokenRate;
+ final public int tokenBucketSize;
+ final public int peakBandwidth;
+ final public int latency;
+ final public int delayVariation;
+
+ final static public int SERVICE_NO_TRAFFIC = 0x00;
+ final static public int SERVICE_BEST_EFFORT = 0x01;
+ final static public int SERVICE_GUARANTEED = 0x02;
+
+ final static public int MAX = (int) 0xffffffff;
+
+ public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize,
+ int peakBandwidth,
+ int latency, int delayVariation) {
+ this.serviceType = serviceType;
+ this.tokenRate = tokenRate;
+ this.tokenBucketSize = tokenBucketSize;
+ this.peakBandwidth = peakBandwidth;
+ this.latency = latency;
+ this.delayVariation = delayVariation;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothHidDeviceAppQosSettings) {
+ BluetoothHidDeviceAppQosSettings qos = (BluetoothHidDeviceAppQosSettings) o;
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothHidDeviceAppQosSettings> CREATOR =
+ new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() {
+
+ @Override
+ public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) {
+
+ return new BluetoothHidDeviceAppQosSettings(in.readInt(), in.readInt(), in.readInt(),
+ in.readInt(),
+ in.readInt(), in.readInt());
+ }
+
+ @Override
+ public BluetoothHidDeviceAppQosSettings[] newArray(int size) {
+ return new BluetoothHidDeviceAppQosSettings[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(serviceType);
+ out.writeInt(tokenRate);
+ out.writeInt(tokenBucketSize);
+ out.writeInt(peakBandwidth);
+ out.writeInt(latency);
+ out.writeInt(delayVariation);
+ }
+
+ public int[] toArray() {
+ return new int[] {
+ serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation
+ };
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
new file mode 100644
index 0000000..38ac1ec
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
@@ -0,0 +1,21 @@
+/*
+** Copyright (C) 2013 The Linux Foundation. All rights reserved
+** Not a Contribution.
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHidDeviceAppSdpSettings;
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
new file mode 100644
index 0000000..db88f0d
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Random;
+
+/** @hide */
+public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
+
+ final public String name;
+ final public String description;
+ final public String provider;
+ final public byte subclass;
+ final public byte[] descriptors;
+
+ public BluetoothHidDeviceAppSdpSettings(String name, String description, String provider,
+ byte subclass, byte[] descriptors) {
+ this.name = name;
+ this.description = description;
+ this.provider = provider;
+ this.subclass = subclass;
+ this.descriptors = descriptors.clone();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothHidDeviceAppSdpSettings) {
+ BluetoothHidDeviceAppSdpSettings sdp = (BluetoothHidDeviceAppSdpSettings) o;
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothHidDeviceAppSdpSettings> CREATOR =
+ new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() {
+
+ @Override
+ public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) {
+
+ return new BluetoothHidDeviceAppSdpSettings(in.readString(), in.readString(),
+ in.readString(), in.readByte(), in.createByteArray());
+ }
+
+ @Override
+ public BluetoothHidDeviceAppSdpSettings[] newArray(int size) {
+ return new BluetoothHidDeviceAppSdpSettings[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(name);
+ out.writeString(description);
+ out.writeString(provider);
+ out.writeByte(subclass);
+ out.writeByteArray(descriptors);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
new file mode 100644
index 0000000..cc60833
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.util.Log;
+
+/** @hide */
+public abstract class BluetoothHidDeviceCallback {
+
+ private static final String TAG = BluetoothHidDeviceCallback.class.getSimpleName();
+
+ /**
+ * Callback called when application registration state changes. Usually it's
+ * called due to either
+ * {@link BluetoothHidDevice#registerApp(String, String, String, byte, byte[],
+ * BluetoothHidDeviceCallback)}
+ * or
+ * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)}
+ * , but can be also unsolicited in case e.g. Bluetooth was turned off in
+ * which case application is unregistered automatically.
+ *
+ * @param pluggedDevice {@link BluetoothDevice} object which represents host
+ * that currently has Virtual Cable established with device. Only
+ * valid when application is registered, can be <code>null</code>
+ * .
+ * @param config {@link BluetoothHidDeviceAppConfiguration} object which
+ * represents token required to unregister application using
+ * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)}
+ * .
+ * @param registered <code>true</code> if application is registered,
+ * <code>false</code> otherwise.
+ */
+ public void onAppStatusChanged(BluetoothDevice pluggedDevice,
+ BluetoothHidDeviceAppConfiguration config, boolean registered) {
+ Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + (pluggedDevice == null ?
+ null : pluggedDevice.toString()) + " registered=" + registered);
+ }
+
+ /**
+ * Callback called when connection state with remote host was changed.
+ * Application can assume than Virtual Cable is established when called with
+ * {@link BluetoothProfile#STATE_CONNECTED} <code>state</code>.
+ *
+ * @param device {@link BluetoothDevice} object representing host device
+ * which connection state was changed.
+ * @param state Connection state as defined in {@link BluetoothProfile}.
+ */
+ public void onConnectionStateChanged(BluetoothDevice device, int state) {
+ Log.d(TAG, "onConnectionStateChanged: device=" + device.toString() + " state=" + state);
+ }
+
+ /**
+ * Callback called when GET_REPORT is received from remote host. Should be
+ * replied by application using
+ * {@link BluetoothHidDevice#replyReport(byte, byte, byte[])}.
+ *
+ * @param type Requested Report Type.
+ * @param id Requested Report Id, can be 0 if no Report Id are defined in
+ * descriptor.
+ * @param bufferSize Requested buffer size, application shall respond with
+ * at least given number of bytes.
+ */
+ public void onGetReport(byte type, byte id, int bufferSize) {
+ Log.d(TAG, "onGetReport: type=" + type + " id=" + id + " bufferSize=" + bufferSize);
+ }
+
+ /**
+ * Callback called when SET_REPORT is received from remote host. In case
+ * received data are invalid, application shall respond with
+ * {@link BluetoothHidDevice#reportError()}.
+ *
+ * @param type Report Type.
+ * @param id Report Id.
+ * @param data Report data.
+ */
+ public void onSetReport(byte type, byte id, byte[] data) {
+ Log.d(TAG, "onSetReport: type=" + type + " id=" + id);
+ }
+
+ /**
+ * Callback called when SET_PROTOCOL is received from remote host.
+ * Application shall use this information to send only reports valid for
+ * given protocol mode. By default,
+ * {@link BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
+ *
+ * @param protocol Protocol Mode.
+ */
+ public void onSetProtocol(byte protocol) {
+ Log.d(TAG, "onSetProtocol: protocol=" + protocol);
+ }
+
+ /**
+ * Callback called when report data is received over interrupt channel.
+ * Report Type is assumed to be
+ * {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
+ *
+ * @param reportId Report Id.
+ * @param data Report data.
+ */
+ public void onIntrData(byte reportId, byte[] data) {
+ Log.d(TAG, "onIntrData: reportId=" + reportId);
+ }
+
+ /**
+ * Callback called when Virtual Cable is removed. This can be either due to
+ * {@link BluetoothHidDevice#unplug()} or request from remote side. After
+ * this callback is received connection will be disconnected automatically.
+ */
+ public void onVirtualCableUnplug() {
+ Log.d(TAG, "onVirtualCableUnplug");
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 252e3d2..db23ef5 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -96,6 +96,12 @@ public final class BluetoothInputDevice implements BluetoothProfile {
public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
"android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
+ /**
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_IDLE_TIME_CHANGED =
+ "codeaurora.bluetooth.input.profile.action.IDLE_TIME_CHANGED";
/**
* Return codes for the connect and disconnect Bluez / Dbus calls.
@@ -199,6 +205,11 @@ public final class BluetoothInputDevice implements BluetoothProfile {
*/
public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_IDLE_TIME = "codeaurora.bluetooth.BluetoothInputDevice.extra.IDLE_TIME";
+
private Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -658,6 +669,56 @@ public final class BluetoothInputDevice implements BluetoothProfile {
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
+
+ /**
+ * Send Get_Idle_Time command to the connected HID input device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean getIdleTime(BluetoothDevice device) {
+ if (DBG) log("getIdletime(" + device + ")");
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.getIdleTime(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Send Set_Idle_Time command to the connected HID input device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @param idleTime Idle time to be set on HID Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
+ if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.setIdleTime(device, idleTime);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index cbce22c..9ef931e 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -131,6 +131,18 @@ public interface BluetoothProfile {
public static final int HEADSET_CLIENT = 16;
/**
+ * HID device
+ * @hide
+ */
+ public static final int HID_DEVICE = 17;
+
+ /**
+ * DUN
+ * @hide
+ */
+ public static final int DUN = 21;
+
+ /**
* Default priority for devices that we try to auto-connect to and
* and allow incoming connections for the profile
* @hide
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index fb81fd1..2eb4953 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -247,6 +247,7 @@ public final class BluetoothSocket implements Closeable {
as.mSocketOS = as.mSocket.getOutputStream();
as.mAddress = RemoteAddr;
as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr);
+ as.mPort = mPort;
return as;
}
/**
@@ -468,6 +469,61 @@ public final class BluetoothSocket implements Closeable {
return acceptedSocket;
}
+ /**
+ * setSocketOpt for the Buetooth Socket.
+ *
+ * @param optionName socket option name
+ * @param optionVal socket option value
+ * @param optionLen socket option length
+ * @return -1 on immediate error,
+ * 0 otherwise
+ * @hide
+ */
+ public int setSocketOpt(int optionName, byte [] optionVal, int optionLen) throws IOException {
+ int ret = 0;
+ if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
+ IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
+ if (bluetoothProxy == null) {
+ Log.e(TAG, "setSocketOpt fail, reason: bluetooth is off");
+ return -1;
+ }
+ try {
+ if(VDBG) Log.d(TAG, "setSocketOpt(), mType: " + mType + " mPort: " + mPort);
+ ret = bluetoothProxy.setSocketOpt(mType, mPort, optionName, optionVal, optionLen);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return -1;
+ }
+ return ret;
+ }
+
+ /**
+ * getSocketOpt for the Buetooth Socket.
+ *
+ * @param optionName socket option name
+ * @param optionVal socket option value
+ * @return -1 on immediate error,
+ * length of returned socket option otherwise
+ * @hide
+ */
+ public int getSocketOpt(int optionName, byte [] optionVal) throws IOException {
+ int ret = 0;
+ if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
+ IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
+ if (bluetoothProxy == null) {
+ Log.e(TAG, "getSocketOpt fail, reason: bluetooth is off");
+ return -1;
+ }
+ try {
+ if(VDBG) Log.d(TAG, "getSocketOpt(), mType: " + mType + " mPort: " + mPort);
+ ret = bluetoothProxy.getSocketOpt(mType, mPort, optionName, optionVal);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return -1;
+ }
+ return ret;
+ }
+
/*package*/ int available() throws IOException {
if (VDBG) Log.d(TAG, "available: " + mSocketIS);
return mSocketIS.available();
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 66f3418..2f1e8b4 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -70,6 +70,11 @@ interface IBluetooth
boolean fetchRemoteUuids(in BluetoothDevice device);
boolean sdpSearch(in BluetoothDevice device, in ParcelUuid uuid);
+ int createMapMnsSdpRecord(in String serviceName, in int rfcommChannel,
+ in int l2capPsm, in int version, in int features);
+ int createPbapPceSdpRecord(in String serviceName, in int version);
+ boolean removeSdpRecord(in int recordHandle);
+
boolean setPin(in BluetoothDevice device, boolean accept, int len, in byte[] pinCode);
boolean setPasskey(in BluetoothDevice device, boolean accept, int len, in byte[]
passkey);
@@ -106,4 +111,7 @@ interface IBluetooth
void dump(in ParcelFileDescriptor fd);
void onLeServiceUp();
void onBrEdrDown();
+
+ int setSocketOpt(int type, int port, int optionName, in byte [] optionVal, int optionLen);
+ int getSocketOpt(int type, int port, int optionName, out byte [] optionVal);
}
diff --git a/core/java/android/bluetooth/IBluetoothA2dpSink.aidl b/core/java/android/bluetooth/IBluetoothA2dpSink.aidl
index b7c6476..774a1ec 100644..100755
--- a/core/java/android/bluetooth/IBluetoothA2dpSink.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dpSink.aidl
@@ -30,5 +30,8 @@ interface IBluetoothA2dpSink {
List<BluetoothDevice> getConnectedDevices();
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+ boolean isA2dpPlaying(in BluetoothDevice device);
BluetoothAudioConfig getAudioConfig(in BluetoothDevice device);
}
diff --git a/core/java/android/bluetooth/IBluetoothAvrcpController.aidl b/core/java/android/bluetooth/IBluetoothAvrcpController.aidl
index f917a50..fb61c98 100644
--- a/core/java/android/bluetooth/IBluetoothAvrcpController.aidl
+++ b/core/java/android/bluetooth/IBluetoothAvrcpController.aidl
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,6 +18,7 @@
package android.bluetooth;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothAvrcpInfo;
/**
* APIs for Bluetooth AVRCP controller service
@@ -28,4 +30,10 @@ interface IBluetoothAvrcpController {
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
int getConnectionState(in BluetoothDevice device);
void sendPassThroughCmd(in BluetoothDevice device, int keyCode, int keyState);
+ void getMetaData(in int[] attributeIds);
+ void getPlayStatus(in int[] playStatusIds);
+ void getPlayerApplicationSetting();
+ void setPlayerApplicationSetting(in int attributeId, in int attribVal);
+ BluetoothAvrcpInfo getSupportedPlayerAppSetting(in BluetoothDevice device);
+ int getSupportedFeatures(in BluetoothDevice device);
}
diff --git a/core/java/android/bluetooth/IBluetoothDun.aidl b/core/java/android/bluetooth/IBluetoothDun.aidl
new file mode 100644
index 0000000..a4f2017
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothDun.aidl
@@ -0,0 +1,45 @@
+/*
+*Copyright (c) 2013, The Linux Foundation. All rights reserved.
+*
+*Redistribution and use in source and binary forms, with or without
+*modification, are permitted provided that the following conditions are
+*met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Dun service
+ *
+ * {@hide}
+ */
+interface IBluetoothDun {
+ // Public API
+ boolean disconnect(in BluetoothDevice device);
+ int getConnectionState(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+}
diff --git a/core/java/android/bluetooth/IBluetoothHidDevice.aidl b/core/java/android/bluetooth/IBluetoothHidDevice.aidl
new file mode 100644
index 0000000..60358c5
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHidDevice.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDeviceAppConfiguration;
+import android.bluetooth.IBluetoothHidDeviceCallback;
+import android.bluetooth.BluetoothHidDeviceAppSdpSettings;
+import android.bluetooth.BluetoothHidDeviceAppQosSettings;
+
+/** @hide */
+interface IBluetoothHidDevice {
+ boolean registerApp(in BluetoothHidDeviceAppConfiguration config,
+ in BluetoothHidDeviceAppSdpSettings sdp, in BluetoothHidDeviceAppQosSettings inQos,
+ in BluetoothHidDeviceAppQosSettings outQos, in IBluetoothHidDeviceCallback callback);
+ boolean unregisterApp(in BluetoothHidDeviceAppConfiguration config);
+ boolean sendReport(in int id, in byte[] data);
+ boolean replyReport(in byte type, in byte id, in byte[] data);
+ boolean reportError(byte error);
+ boolean unplug();
+ boolean connect();
+ boolean disconnect();
+}
diff --git a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
new file mode 100644
index 0000000..7c71a17
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 The Linux Foundation. All rights reserved
+ * Not a Contribution.
+ * Copyright (C) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDeviceAppConfiguration;
+
+/** @hide */
+interface IBluetoothHidDeviceCallback {
+ void onAppStatusChanged(in BluetoothDevice device, in BluetoothHidDeviceAppConfiguration config, boolean registered);
+ void onConnectionStateChanged(in BluetoothDevice device, in int state);
+ void onGetReport(in byte type, in byte id, in int bufferSize);
+ void onSetReport(in byte type, in byte id, in byte[] data);
+ void onSetProtocol(in byte protocol);
+ void onIntrData(in byte reportId, in byte[] data);
+ void onVirtualCableUnplug();
+}
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
index 1ebb9ca..5bd3f78 100644
--- a/core/java/android/bluetooth/IBluetoothInputDevice.aidl
+++ b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
@@ -56,4 +56,12 @@ interface IBluetoothInputDevice {
* @hide
*/
boolean sendData(in BluetoothDevice device, String report);
+ /**
+ * @hide
+ */
+ boolean getIdleTime(in BluetoothDevice device);
+ /**
+ * @hide
+ */
+ boolean setIdleTime(in BluetoothDevice device, byte idleTime);
}
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
index 0b81ee8..bd8c6c9 100644
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -19,7 +19,6 @@ package android.bluetooth;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManagerCallback;
-import android.bluetooth.IBluetoothProfileServiceConnection;
import android.bluetooth.IBluetoothStateChangeCallback;
/**
@@ -34,14 +33,11 @@ interface IBluetoothManager
void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
boolean isEnabled();
- boolean enable();
+ boolean enable(String callingPackage);
boolean enableNoAutoConnect();
boolean disable(boolean persist);
IBluetoothGatt getBluetoothGatt();
- boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
- void unbindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
-
String getAddress();
String getName();
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 2260d7e..bf0c48d 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -16,6 +16,7 @@
package android.content;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.IActivityManager;
@@ -747,6 +748,17 @@ public abstract class BroadcastReceiver {
return mPendingResult.mSendingUser;
}
+ /** @hide */
+ public String getSendingPackage(Intent intent) {
+ final IActivityManager mgr = ActivityManagerNative.getDefault();
+ try {
+ boolean fg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
+ return mgr.getCallingPackageForBroadcast(fg);
+ } catch (RemoteException ex) {
+ return null;
+ }
+ }
+
/**
* Control inclusion of debugging help for mismatched
* calls to {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 6ede29b..863ca65 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -431,6 +431,7 @@ public abstract class ContentResolver {
public final @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
@Nullable String selection, @Nullable String[] selectionArgs,
@Nullable String sortOrder) {
+ android.util.SeempLog.record_uri(13, uri);
return query(uri, projection, selection, selectionArgs, sortOrder, null);
}
@@ -471,6 +472,7 @@ public abstract class ContentResolver {
public final @Nullable Cursor query(final @NonNull Uri uri, @Nullable String[] projection,
@Nullable String selection, @Nullable String[] selectionArgs,
@Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
+ android.util.SeempLog.record_uri(13, uri);
Preconditions.checkNotNull(uri, "uri");
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
@@ -984,6 +986,7 @@ public abstract class ContentResolver {
stableProvider = acquireProvider(uri);
}
releaseUnstableProvider(unstableProvider);
+ unstableProvider = null;
ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
fd.getParcelFileDescriptor(), stableProvider);
@@ -1128,6 +1131,7 @@ public abstract class ContentResolver {
stableProvider = acquireProvider(uri);
}
releaseUnstableProvider(unstableProvider);
+ unstableProvider = null;
ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
fd.getParcelFileDescriptor(), stableProvider);
@@ -1221,6 +1225,7 @@ public abstract class ContentResolver {
* @return the URL of the newly created row.
*/
public final @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues values) {
+ android.util.SeempLog.record_uri(37, url);
Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
if (provider == null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 758b6ff..7ddda11 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -497,6 +497,9 @@ public abstract class Context {
@ViewDebug.ExportedProperty(deepExport = true)
public abstract Resources.Theme getTheme();
+ /** @hide */
+ public abstract void recreateTheme();
+
/**
* Retrieve styled attribute information in this Context's theme. See
* {@link android.content.res.Resources.Theme#obtainStyledAttributes(int[])}
@@ -3858,6 +3861,26 @@ public abstract class Context {
int flags) throws PackageManager.NameNotFoundException;
/**
+ * Similar to {@link #createPackageContext(String, int)}, but with a
+ * different {@link UserHandle}. For example, {@link #getContentResolver()}
+ * will open any {@link Uri} as the given user. A theme package can be
+ * specified which will be used when adding resources to this context
+ *
+ * @hide
+ */
+ public abstract Context createPackageContextAsUser(
+ String packageName, String themePackageName, int flags, UserHandle user)
+ throws PackageManager.NameNotFoundException;
+
+ /**
+ * Creates a context given an {@link android.content.pm.ApplicationInfo}.
+ *
+ * @hide
+ */
+ public abstract Context createApplicationContext(ApplicationInfo application,
+ String themePackageName, int flags) throws PackageManager.NameNotFoundException;
+
+ /**
* Get the userId associated with this context
* @return user id
*
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 8359edf..795b9ae 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -123,6 +123,12 @@ public class ContextWrapper extends Context {
return mBase.getTheme();
}
+ /** @hide */
+ @Override
+ public void recreateTheme() {
+ mBase.recreateTheme();
+ }
+
@Override
public ClassLoader getClassLoader() {
return mBase.getClassLoader();
@@ -757,7 +763,20 @@ public class ContextWrapper extends Context {
@Override
public Context createApplicationContext(ApplicationInfo application,
int flags) throws PackageManager.NameNotFoundException {
- return mBase.createApplicationContext(application, flags);
+ return createApplicationContext(application, null, flags);
+ }
+
+ /** @hide */
+ public Context createApplicationContext(ApplicationInfo application,
+ String themePackageName, int flags) throws PackageManager.NameNotFoundException {
+ return mBase.createApplicationContext(application, themePackageName, flags);
+ }
+
+ /** @hide */
+ @Override
+ public Context createPackageContextAsUser(String packageName, String themePackageName,
+ int flags, UserHandle user) throws PackageManager.NameNotFoundException {
+ return mBase.createPackageContextAsUser(packageName, themePackageName, flags, user);
}
/** @hide */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5abf047..c06f98a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1846,6 +1847,15 @@ public class Intent implements Parcelable, Cloneable {
*/
public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
/**
+ * Broadcast Action: Update preferences for the power menu dialog. This is to provide a
+ * way for the preferences that need to be enabled/disabled to update because they were
+ * toggled elsewhere in the settings (ie profiles, immersive desktop, etc) so we don't have
+ * to do constant lookups while we wait for the menu to be created. Getting the values once
+ * when necessary is enough.
+ *@hide
+ */
+ public static final String UPDATE_POWER_MENU = "android.intent.action.UPDATE_POWER_MENU";
+ /**
* Broadcast Action: Trigger the download and eventual installation
* of a package.
* <p>Input: {@link #getData} is the URI of the package file to download.
@@ -2121,6 +2131,15 @@ public class Intent implements Parcelable, Cloneable {
*/
@Deprecated @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
+
+ /**
+ * Broadcast Action: The current keyguard wallpaper configuration
+ * has changed and should be re-read.
+ * {@hide}
+ */
+ public static final String ACTION_KEYGUARD_WALLPAPER_CHANGED =
+ "android.intent.action.KEYGUARD_WALLPAPER_CHANGED";
+
/**
* Broadcast Action: The current device {@link android.content.res.Configuration}
* (orientation, locale, etc) has changed. When such a change happens, the
@@ -2705,6 +2724,45 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.GET_RESTRICTION_ENTRIES";
/**
+ * <p>Broadcast Action: The state of the HOTWORD audio input has changed.:</p>
+ * <ul>
+ * <li><em>state</em> - A String value indicating the state of the input.
+ * {@link #EXTRA_HOTWORD_INPUT_STATE}. The value will be one of:
+ * {@link android.media.AudioRecord#RECORDSTATE_RECORDING} or
+ * {@link android.media.AudioRecord#RECORDSTATE_STOPPED}.
+ * </li>
+ * <li><em>package</em> - A String value indicating the package name of the application
+ * that currently holds the HOTWORD input.
+ * {@link #EXTRA_CURRENT_PACKAGE_NAME}
+ * </li>
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system. It can only be received by packages that hold
+ * {@link android.Manifest.permission#CAPTURE_AUDIO_HOTWORD}.
+ *
+ * @hide
+ */
+ //@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_HOTWORD_INPUT_CHANGED
+ = "com.cyanogenmod.intent.action.HOTWORD_INPUT_CHANGED";
+
+ /**
+ * @hide
+ * Activity to challenge the user for a PIN that was configured when setting up
+ * restrictions. Restrictions include blocking of apps and preventing certain user operations,
+ * controlled by {@link android.os.UserManager#setUserRestrictions(Bundle).
+ * Launch the activity using
+ * {@link android.app.Activity#startActivityForResult(Intent, int)} and check if the
+ * result is {@link android.app.Activity#RESULT_OK} for a successful response to the
+ * challenge.<p/>
+ * Before launching this activity, make sure that there is a PIN in effect, by calling
+ * {@link android.os.UserManager#hasRestrictionsChallenge()}.
+ */
+ public static final String ACTION_RESTRICTIONS_CHALLENGE =
+ "android.intent.action.RESTRICTIONS_CHALLENGE";
+
+ /**
* Sent the first time a user is starting, to allow system apps to
* perform one time initialization. (This will not be seen by third
* party applications because a newly initialized user does not have any
@@ -2876,6 +2934,13 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.SHOW_BRIGHTNESS_DIALOG";
/**
+ * Activity Action: Shows the notification brightness setting dialog.
+ * @hide
+ */
+ public static final String ACTION_SHOW_NOTIFICATION_BRIGHTNESS_DIALOG =
+ "android.intent.action.SHOW_NOTIFICATION_BRIGHTNESS_DIALOG";
+
+ /**
* Broadcast Action: A global button was pressed. Includes a single
* extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
* caused the broadcast.
@@ -2964,6 +3029,19 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT";
/**
+ * Broadcast Action: A theme's resources were cached. Includes two extra fields,
+ * {@link #EXTRA_THEME_PACKAGE_NAME}, containing the package name of the theme that was
+ * processed, and {@link #EXTRA_THEME_RESULT}, containing the result code.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.</p>
+ *
+ * @hide
+ */
+ public static final String ACTION_THEME_RESOURCES_CACHED =
+ "android.intent.action.THEME_RESOURCES_CACHED";
+
+ /**
* Activity Action: Allow the user to pick a directory subtree. When
* invoked, the system will display the various {@link DocumentsProvider}
* instances installed on the device, letting the user navigate through
@@ -3030,6 +3108,10 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_PROCESS_TEXT_READONLY =
"android.intent.extra.PROCESS_TEXT_READONLY";
+ /** {@hide} */
+ public static final String ACTION_DOZE_PULSE_STARTING =
+ "android.intent.action.DOZE_PULSE_STARTING";
+
/**
* Broadcast action: reports when a new thermal event has been reached. When the device
* is reaching its maximum temperatue, the thermal level reported
@@ -3881,6 +3963,42 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_SIM_ACTIVATION_RESPONSE =
"android.intent.extra.SIM_ACTIVATION_RESPONSE";
+ /**
+ * Extra for {@link #ACTION_THEME_RESOURCES_CACHED} that provides the return value
+ * from processThemeResources. A value of 0 indicates a successful caching of resources.
+ * Error results are:
+ * {@link android.content.pm.PackageManager#INSTALL_FAILED_THEME_AAPT_ERROR}
+ * {@link android.content.pm.PackageManager#INSTALL_FAILED_THEME_IDMAP_ERROR}
+ * {@link android.content.pm.PackageManager#INSTALL_FAILED_THEME_UNKNOWN_ERROR}
+ *
+ * @hide
+ */
+ public static final String EXTRA_THEME_RESULT = "android.intent.extra.RESULT";
+
+ /**
+ * Extra for {@link #ACTION_THEME_RESOURCES_CACHED} that provides the package name of the
+ * theme that was processed.
+ *
+ * @hide
+ */
+ public static final String EXTRA_THEME_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
+
+ /**
+ * Extra for {@link #ACTION_HOTWORD_INPUT_CHANGED} that provides the state of
+ * the input when the broadcast action was sent.
+ * @hide
+ */
+ public static final String EXTRA_HOTWORD_INPUT_STATE =
+ "com.cyanogenmod.intent.extra.HOTWORD_INPUT_STATE";
+
+ /**
+ * Extra for {@link #ACTION_RECENTS_LONG_PRESS} that provides the package name of the
+ * app in foreground when recents was long pressed. Can be reused for other purposes.
+ * @hide
+ */
+ public static final String EXTRA_CURRENT_PACKAGE_NAME =
+ "com.cyanogenmod.intent.extra.CURRENT_PACKAGE_NAME";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/ThemeVersion.java b/core/java/android/content/ThemeVersion.java
new file mode 100644
index 0000000..05fbc41
--- /dev/null
+++ b/core/java/android/content/ThemeVersion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod 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;
+
+/**
+ * Warning: Careful moving/refactoring this class as our SDK references it.
+ * ThemeVersion 1 = CM11
+ * ThemeVersion 2 = CM12/CM12.1 First Release
+ * ThemeVersion 3 = CM12.1 W/ Wallpaper Packs
+ * @hide
+ */
+public class ThemeVersion {
+ /**
+ * Increment this anytime changes are made to:
+ * 1) Changes to ThemesContract
+ * 2) Changes to ThemeService API
+ * 3) Changes to ThemeManager API
+ */
+ public static int THEME_VERSION = 3;
+
+ /**
+ * Change this if a change to the contract or service would break compatibility.
+ * Example: A client app like chooser might be outdated from the framework.
+ * It could then query the FW for this value and determine whether its safe to proceed.
+ */
+ public static int MIN_SUPPORTED_THEME_VERSION = 2;
+
+ /**
+ * Do not change the order of this. See SDK.
+ * Increment the minSupportedVersion when the fw can no longer support a theme's apk structure
+ * Increment currentVersion when a change to the theme's apk structure is changed
+ * For example, CM11 to CM12 introduces new resources to overlay, so the overlays
+ * version should change. Because the changes are not compatible with CM11, the minVersion
+ * must change as well.
+ *
+ * If a new feature is added to a component (ex rotations in icon packs), the current version
+ * for the ICON component would be incremented. If a new component is created, then add it
+ * to the enum list.
+ *
+ * Wallpaper Version 2: Multi wallpaper ability
+ *
+ */
+ public static enum ComponentVersion {
+ OVERLAY(0, 2, 2),
+ BOOT_ANIM(1, 1, 1),
+ WALLPAPER(2, 1, 2),
+ LOCKSCREEN(3, 1, 1),
+ FONT(4, 1, 2),
+ ICON(5, 1, 1),
+ SOUNDS(6, 1, 1);
+
+ public int id;
+ public int minSupportedVersion;
+ public int currentVersion;
+
+ private ComponentVersion(int id, int minSupportedVersion, int currentVersion) {
+ this.id = id;
+ this.minSupportedVersion = minSupportedVersion;
+ this.currentVersion = currentVersion;
+ }
+ }
+}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e798eb8..0105e09 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007 The Android Open Source Project
- *
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
+
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -545,6 +546,16 @@ public class ActivityInfo extends ComponentInfo
*/
public static final int CONFIG_LAYOUT_DIRECTION = 0x2000;
/**
+ * Bit in {@link #configChanges} that indicates a theme change occurred
+ * @hide
+ */
+ public static final int CONFIG_THEME_RESOURCE = 0x100000;
+ /**
+ * Bit in {@link #configChanges} that indicates a font change occurred
+ * @hide
+ */
+ public static final int CONFIG_THEME_FONT = 0x200000;
+ /**
* Bit in {@link #configChanges} that indicates that the activity
* can itself handle changes to the font scaling factor. Set from the
* {@link android.R.attr#configChanges} attribute. This is
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6feb860..1933fc9 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -654,6 +655,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public int installLocation = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ /**
+ * When true, indicates that any one component within this application is
+ * protected.
+ * @hide
+ */
+ public boolean protect = false;
+
+ /**
+ * Is given application theme agnostic, i.e. behaves properly when default theme is changed.
+ * @hide
+ */
+ public boolean isThemeable = false;
+
public void dump(Printer pw, String prefix) {
super.dumpFront(pw, prefix);
if (className != null) {
@@ -785,6 +799,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
uiOptions = orig.uiOptions;
backupAgentName = orig.backupAgentName;
fullBackupContent = orig.fullBackupContent;
+ protect = orig.protect;
+ isThemeable = orig.isThemeable;
}
@@ -838,6 +854,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(descriptionRes);
dest.writeInt(uiOptions);
dest.writeInt(fullBackupContent);
+ dest.writeInt(protect ? 1 : 0);
+ dest.writeInt(isThemeable ? 1 : 0);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -890,6 +908,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
descriptionRes = source.readInt();
uiOptions = source.readInt();
fullBackupContent = source.readInt();
+ protect = source.readInt() != 0;
+ isThemeable = source.readInt() != 0;
}
/**
diff --git a/core/java/android/content/pm/BaseThemeInfo.java b/core/java/android/content/pm/BaseThemeInfo.java
new file mode 100644
index 0000000..8ece42d
--- /dev/null
+++ b/core/java/android/content/pm/BaseThemeInfo.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010, T-Mobile USA, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+import android.util.AttributeSet;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class BaseThemeInfo implements Parcelable {
+ /**
+ * The theme id, which does not change when the theme is modified.
+ * Specifies an Android UI Style using style name.
+ *
+ * @see themeId attribute
+ *
+ */
+ public String themeId;
+
+ /**
+ * The name of the theme (as displayed by UI).
+ *
+ * @see name attribute
+ *
+ */
+ public String name;
+
+ /**
+ * The author name of the theme package.
+ *
+ * @see author attribute
+ *
+ */
+ public String author;
+
+ /*
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return a bitmask indicating the set of special object types marshalled
+ * by the Parcelable.
+ *
+ * @see android.os.Parcelable#describeContents()
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ /*
+ * Flatten this object in to a Parcel.
+ *
+ * @param dest The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ *
+ * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
+ */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(themeId);
+ dest.writeString(name);
+ dest.writeString(author);
+ }
+
+ /** @hide */
+ public static final Parcelable.Creator<BaseThemeInfo> CREATOR
+ = new Parcelable.Creator<BaseThemeInfo>() {
+ public BaseThemeInfo createFromParcel(Parcel source) {
+ return new BaseThemeInfo(source);
+ }
+
+ public BaseThemeInfo[] newArray(int size) {
+ return new BaseThemeInfo[size];
+ }
+ };
+
+ /** @hide */
+ public final String getResolvedString(Resources res, AttributeSet attrs, int index) {
+ int resId = attrs.getAttributeResourceValue(index, 0);
+ if (resId !=0 ) {
+ return res.getString(resId);
+ }
+ return attrs.getAttributeValue(index);
+ }
+
+ protected BaseThemeInfo() {
+ }
+
+ protected BaseThemeInfo(Parcel source) {
+ themeId = source.readString();
+ name = source.readString();
+ author = source.readString();
+ }
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index fec2c44..6d8b5cb 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -17,6 +17,7 @@
package android.content.pm;
+import android.app.ComposedIconInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -509,4 +510,17 @@ interface IPackageManager {
boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId);
String getPermissionControllerPackageName();
+
+ /** Protected Apps */
+ void setComponentProtectedSetting(in ComponentName componentName,
+ in boolean newState, int userId);
+
+ /** Themes */
+ void updateIconMapping(String pkgName);
+ ComposedIconInfo getComposedIconInfo();
+ int processThemeResources(String themePkgName);
+
+ /** Protected Apps */
+ boolean isComponentProtected(in String callingPackage, in ComponentName componentName,
+ int userId);
}
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 9e6c6b5..0de867e 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +17,11 @@
package android.content.pm;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
import android.os.Parcel;
import android.os.Parcelable;
@@ -254,6 +260,34 @@ public class PackageInfo implements Parcelable {
/** @hide */
public boolean coreApp;
+ // Is Theme Apk
+ /**
+ * {@hide}
+ */
+ public boolean isThemeApk = false;
+
+ /**
+ * {@hide}
+ */
+ public boolean hasIconPack = false;
+
+ /**
+ * {@hide}
+ */
+ public ArrayList<String> mOverlayTargets;
+
+ // Is Legacy Icon Apk
+ /**
+ * {@hide}
+ */
+ public boolean isLegacyIconPackApk = false;
+
+ // ThemeInfo
+ /**
+ * {@hide}
+ */
+ public ThemeInfo themeInfo;
+
/** @hide */
public boolean requiredForAllUsers;
@@ -323,6 +357,13 @@ public class PackageInfo implements Parcelable {
dest.writeString(restrictedAccountType);
dest.writeString(requiredAccountType);
dest.writeString(overlayTarget);
+
+ /* Theme-specific. */
+ dest.writeInt((isThemeApk) ? 1 : 0);
+ dest.writeStringList(mOverlayTargets);
+ dest.writeParcelable(themeInfo, parcelableFlags);
+ dest.writeInt(hasIconPack ? 1 : 0);
+ dest.writeInt((isLegacyIconPackApk) ? 1 : 0);
}
public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -372,5 +413,12 @@ public class PackageInfo implements Parcelable {
restrictedAccountType = source.readString();
requiredAccountType = source.readString();
overlayTarget = source.readString();
+
+ /* Theme-specific. */
+ isThemeApk = (source.readInt() != 0);
+ mOverlayTargets = source.createStringArrayList();
+ themeInfo = source.readParcelable(null);
+ hasIconPack = source.readInt() == 1;
+ isLegacyIconPackApk = source.readInt() == 1;
}
}
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index 1efe082..d4f33fb 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -62,6 +62,7 @@ public class PackageInfoLite implements Parcelable {
*/
public int recommendedInstallLocation;
public int installLocation;
+ public boolean isTheme;
public VerifierInfo[] verifiers;
@@ -87,6 +88,7 @@ public class PackageInfoLite implements Parcelable {
dest.writeInt(recommendedInstallLocation);
dest.writeInt(installLocation);
dest.writeInt(multiArch ? 1 : 0);
+ dest.writeInt(isTheme ? 1 : 0);
if (verifiers == null || verifiers.length == 0) {
dest.writeInt(0);
@@ -116,6 +118,7 @@ public class PackageInfoLite implements Parcelable {
recommendedInstallLocation = source.readInt();
installLocation = source.readInt();
multiArch = (source.readInt() != 0);
+ isTheme = source.readInt() == 1 ? true : false;
final int verifiersLength = source.readInt();
if (verifiersLength == 0) {
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 22a899c..366deb4 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -66,7 +66,14 @@ public class PackageItemInfo {
* component's icon. From the "icon" attribute or, if not set, 0.
*/
public int icon;
-
+
+ /**
+ * A drawable resource identifier in the icon pack's resources
+ * If there isn't an icon pack or not set, then 0.
+ * @hide
+ */
+ public int themedIcon;
+
/**
* A drawable resource identifier (in the package's resources) of this
* component's banner. From the "banner" attribute or, if not set, 0.
@@ -110,6 +117,7 @@ public class PackageItemInfo {
logo = orig.logo;
metaData = orig.metaData;
showUserIcon = orig.showUserIcon;
+ themedIcon = orig.themedIcon;
}
/**
@@ -309,8 +317,9 @@ public class PackageItemInfo {
dest.writeBundle(metaData);
dest.writeInt(banner);
dest.writeInt(showUserIcon);
+ dest.writeInt(themedIcon);
}
-
+
protected PackageItemInfo(Parcel source) {
name = source.readString();
packageName = source.readString();
@@ -322,6 +331,7 @@ public class PackageItemInfo {
metaData = source.readBundle();
banner = source.readInt();
showUserIcon = source.readInt();
+ themedIcon = source.readInt();
}
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c8e9402..529d641 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -830,6 +830,51 @@ public abstract class PackageManager {
public static final int INSTALL_FAILED_ABORTED = -115;
/**
+ * Used by themes
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the theme because aapt could not compile the app
+ * @hide
+ */
+ public static final int INSTALL_FAILED_THEME_AAPT_ERROR = -400;
+
+ /**
+ * Used by themes
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the theme because idmap failed
+ * apps.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_THEME_IDMAP_ERROR = -401;
+
+ /**
+ * Used by themes
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the theme for an unknown reason
+ * apps.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_THEME_UNKNOWN_ERROR = -402;
+
+ /**
+ * Used for prebundles
+ * Installation failed for a prebundled app because the user previously uninstalled it
+ * and we don't want to bring it back
+ * @hide
+ */
+ public static final int INSTALL_FAILED_UNINSTALLED_PREBUNDLE = -403;
+
+ /**
+ * Used for prebundles
+ * Installation failed for a prebundled app because it wasn't needed in the default
+ * mobile country exported by the hardware
+ * @hide
+ */
+ public static final int INSTALL_FAILED_REGION_LOCKED_PREBUNDLE = -404; //bloat not found
+
+ /**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
*
@@ -1912,6 +1957,20 @@ public abstract class PackageManager {
= "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
/**
+ * Flag for {@link #setComponentProtectedSetting(android.content.ComponentName, boolean)}:
+ * This component or application has set to protected status
+ * @hide
+ */
+ public static final boolean COMPONENT_PROTECTED_STATUS = false;
+
+ /**
+ * Flag for {@link #setComponentProtectedSetting(android.content.ComponentName, boolean)}:
+ * This component or application has been explicitly set to visible status
+ * @hide
+ */
+ public static final boolean COMPONENT_VISIBLE_STATUS = true;
+
+ /**
* String extra for {@link PackageInstallObserver} in the 'extras' Bundle in case of
* {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the package which provides
* the existing definition for the permission.
@@ -3511,6 +3570,18 @@ public abstract class PackageManager {
public abstract Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
throws NameNotFoundException;
+ /** @hide */
+ public abstract Resources getThemedResourcesForApplication(ApplicationInfo app,
+ String themePkgName) throws NameNotFoundException;
+
+ /** @hide */
+ public abstract Resources getThemedResourcesForApplication(String appPackageName,
+ String themePkgName) throws NameNotFoundException;
+
+ /** @hide */
+ public abstract Resources getThemedResourcesForApplicationAsUser(String appPackageName,
+ String themePkgName, int userId) throws NameNotFoundException;
+
/**
* Retrieve overall information about an application package defined
* in a package archive file
@@ -4484,6 +4555,19 @@ public abstract class PackageManager {
public abstract @NonNull PackageInstaller getPackageInstaller();
/**
+ * Update Component protection state
+ * @hide
+ */
+ public abstract void setComponentProtectedSetting(ComponentName componentName, boolean newState);
+
+ /**
+ * Return whether or not a specific component is protected
+ * @hide
+ */
+ public abstract boolean isComponentProtected(String callingPackage,
+ ComponentName componentName);
+
+ /**
* Adds a {@link CrossProfileIntentFilter}. After calling this method all intents sent from the
* user with id sourceUserId can also be be resolved by activities in the user with id
* targetUserId if they match the specified intent filter.
@@ -4709,4 +4793,22 @@ public abstract class PackageManager {
}
}
}
+
+ /**
+ * Updates the theme icon res id for the new theme
+ * @hide
+ */
+ public abstract void updateIconMaps(String pkgName);
+
+ /**
+ * Used to compile theme resources for a given theme
+ * @param themePkgName
+ * @return A value of 0 indicates success. Possible errors returned are:
+ * {@link android.content.pm.PackageManager#INSTALL_FAILED_THEME_AAPT_ERROR},
+ * {@link android.content.pm.PackageManager#INSTALL_FAILED_THEME_IDMAP_ERROR}, or
+ * {@link android.content.pm.PackageManager#INSTALL_FAILED_THEME_UNKNOWN_ERROR}
+ *
+ * @hide
+ */
+ public abstract int processThemeResources(String themePkgName);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 99bd390..6a07b31 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,6 +62,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -77,12 +79,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.StrictJarFile;
import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
/**
* Parser for package files (APKs) on disk. This supports apps packaged either
@@ -112,6 +119,17 @@ public class PackageParser {
/** File name in an APK for the Android manifest. */
private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
+ /** Path to overlay directory in a theme APK */
+ private static final String OVERLAY_PATH = "assets/overlays/";
+ /** Path to icon directory in a theme APK */
+ private static final String ICON_PATH = "assets/icons/";
+
+ private static final String PACKAGE_REDIRECTIONS_XML = "res/xml/redirections.xml";
+
+ private static final String TAG_PACKAGE_REDIRECTIONS = "package-redirections";
+ private static final String TAG_RESOURCE_REDIRECTIONS = "resource-redirections";
+ private static final String TAG_ITEM = "item";
+ private static final String ATTRIBUTE_ITEM_NAME = "name";
/** Path prefix for apps on expanded storage */
private static final String MNT_EXPAND = "/mnt/expand/";
@@ -251,6 +269,7 @@ public class PackageParser {
public final int versionCode;
public final int installLocation;
public final VerifierInfo[] verifiers;
+ public boolean isTheme;
/** Names of any split APKs, ordered by parsed splitName */
public final String[] splitNames;
@@ -276,6 +295,7 @@ public class PackageParser {
public final boolean multiArch;
public final boolean extractNativeLibs;
+
public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
String[] splitCodePaths, int[] splitRevisionCodes) {
this.packageName = baseApk.packageName;
@@ -291,6 +311,7 @@ public class PackageParser {
this.coreApp = baseApk.coreApp;
this.multiArch = baseApk.multiArch;
this.extractNativeLibs = baseApk.extractNativeLibs;
+ this.isTheme = baseApk.isTheme;
}
public List<String> getAllCodePaths() {
@@ -318,11 +339,12 @@ public class PackageParser {
public final boolean coreApp;
public final boolean multiArch;
public final boolean extractNativeLibs;
+ public final boolean isTheme;
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Signature[] signatures, boolean coreApp, boolean multiArch,
- boolean extractNativeLibs) {
+ boolean extractNativeLibs, boolean isTheme) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -334,6 +356,7 @@ public class PackageParser {
this.coreApp = coreApp;
this.multiArch = multiArch;
this.extractNativeLibs = extractNativeLibs;
+ this.isTheme = isTheme;
}
}
@@ -424,6 +447,14 @@ public class PackageParser {
pi.versionName = p.mVersionName;
pi.sharedUserId = p.mSharedUserId;
pi.sharedUserLabel = p.mSharedUserLabel;
+ pi.isThemeApk = p.mIsThemeApk;
+ pi.hasIconPack = p.hasIconPack;
+ pi.isLegacyIconPackApk = p.mIsLegacyIconPackApk;
+
+ if (pi.isThemeApk) {
+ pi.mOverlayTargets = p.mOverlayTargets;
+ pi.themeInfo = p.mThemeInfo;
+ }
pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
pi.installLocation = p.installLocation;
pi.coreApp = p.coreApp;
@@ -614,6 +645,7 @@ public class PackageParser {
public final static int PARSE_IS_PRIVILEGED = 1<<7;
public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
+ public final static int PARSE_IS_PREBUNDLED_DIR = 1<<10;
private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
@@ -898,6 +930,18 @@ public class PackageParser {
pkg.baseCodePath = apkPath;
pkg.mSignatures = null;
+ // If the pkg is a theme, we need to know what themes it overlays
+ // and determine if it has an icon pack
+ if (pkg.mIsThemeApk) {
+ //Determine existance of Overlays
+ ArrayList<String> overlayTargets = scanPackageOverlays(apkFile);
+ for(String overlay : overlayTargets) {
+ pkg.mOverlayTargets.add(overlay);
+ }
+
+ pkg.hasIconPack = packageHasIconPack(apkFile);
+ }
+
return pkg;
} catch (PackageParserException e) {
@@ -1020,6 +1064,68 @@ public class PackageParser {
return pkg;
}
+
+ private ArrayList<String> scanPackageOverlays(File originalFile) {
+ Set<String> overlayTargets = new HashSet<String>();
+ ZipFile privateZip = null;
+ try {
+ privateZip = new ZipFile(originalFile.getPath());
+ final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
+ while (privateZipEntries.hasMoreElements()) {
+ final ZipEntry zipEntry = privateZipEntries.nextElement();
+ final String zipEntryName = zipEntry.getName();
+
+ if (zipEntryName.startsWith(OVERLAY_PATH) && zipEntryName.length() > 16) {
+ String[] subdirs = zipEntryName.split("/");
+ overlayTargets.add(subdirs[2]);
+ }
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ overlayTargets.clear();
+ } finally {
+ if (privateZip != null) {
+ try {
+ privateZip.close();
+ } catch (Exception e) {
+ //Ignore
+ }
+ }
+ }
+
+ ArrayList<String> overlays = new ArrayList<String>();
+ overlays.addAll(overlayTargets);
+ return overlays;
+ }
+
+ private boolean packageHasIconPack(File originalFile) {
+ ZipFile privateZip = null;
+ try {
+ privateZip = new ZipFile(originalFile.getPath());
+ final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
+ while (privateZipEntries.hasMoreElements()) {
+ final ZipEntry zipEntry = privateZipEntries.nextElement();
+ final String zipEntryName = zipEntry.getName();
+
+ if (zipEntryName.startsWith(ICON_PATH) &&
+ zipEntryName.length() > ICON_PATH.length()) {
+ return true;
+ }
+ }
+ } catch(Exception e) {
+ Log.e(TAG, "Could not read zip entries while checking if apk has icon pack", e);
+ } finally {
+ if (privateZip != null) {
+ try {
+ privateZip.close();
+ } catch (Exception e) {
+ //Ignore
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Gathers the {@link ManifestDigest} for {@code pkg} if it exists in the
* APK. If it successfully scanned the package and found the
@@ -1027,6 +1133,7 @@ public class PackageParser {
*/
public void collectManifestDigest(Package pkg) throws PackageParserException {
pkg.manifestDigest = null;
+ pkg.manifestHashCode = 0;
// TODO: extend to gather digest for split APKs
try {
@@ -1035,6 +1142,7 @@ public class PackageParser {
final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (je != null) {
pkg.manifestDigest = ManifestDigest.fromInputStream(jarFile.getInputStream(je));
+ pkg.manifestHashCode = ThemeUtils.getPackageHashCode(pkg, jarFile);
}
} finally {
jarFile.close();
@@ -1300,6 +1408,9 @@ public class PackageParser {
// Only search the tree when the tag is directly below <manifest>
int type;
final int searchDepth = parser.getDepth() + 1;
+ // Search for category and actions inside <intent-filter>
+ final int iconPackSearchDepth = parser.getDepth() + 4;
+ boolean isTheme = false;
final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1326,11 +1437,53 @@ public class PackageParser {
}
}
}
+
+ if (parser.getDepth() == searchDepth && "meta-data".equals(parser.getName())) {
+ for (int i=0; i < parser.getAttributeCount(); i++) {
+ if ("name".equals(parser.getAttributeName(i)) &&
+ ThemeInfo.META_TAG_NAME.equals(parser.getAttributeValue(i))) {
+ isTheme = true;
+ installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+ break;
+ }
+ }
+ }
+
+ if (parser.getDepth() == searchDepth && "theme".equals(parser.getName())) {
+ isTheme = true;
+ installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+ }
+
+ if (parser.getDepth() == iconPackSearchDepth && isLegacyIconPack(parser)) {
+ isTheme = true;
+ installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+ }
}
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
- extractNativeLibs);
+ extractNativeLibs, isTheme);
+ }
+
+ private static boolean isLegacyIconPack(XmlPullParser parser) {
+ boolean isAction = "action".equals(parser.getName());
+ boolean isCategory = "category".equals(parser.getName());
+ String[] items = isAction ? ThemeUtils.sSupportedActions
+ : (isCategory ? ThemeUtils.sSupportedCategories : null);
+
+ if (items != null) {
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ if ("name".equals(parser.getAttributeName(i))) {
+ final String value = parser.getAttributeValue(i);
+ for (String item : items) {
+ if (item.equals(value)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
}
/**
@@ -1382,6 +1535,8 @@ public class PackageParser {
}
final Package pkg = new Package(pkgName);
+ Bundle metaDataBundle = new Bundle();
+
boolean foundApp = false;
TypedArray sa = res.obtainAttributes(attrs,
@@ -1794,6 +1949,11 @@ public class PackageParser {
XmlUtils.skipCurrentTag(parser);
continue;
+ } else if (parser.getName().equals("meta-data")) {
+ if ((metaDataBundle=parseMetaData(res, parser, attrs, metaDataBundle,
+ outError)) == null) {
+ return null;
+ }
} else if (RIGID_PARSER) {
outError[0] = "Bad element under <manifest>: "
+ parser.getName();
@@ -1882,6 +2042,17 @@ public class PackageParser {
>= android.os.Build.VERSION_CODES.DONUT)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
}
+ if (pkg.mIsThemeApk || pkg.mIsLegacyIconPackApk) {
+ pkg.applicationInfo.isThemeable = false;
+ }
+
+ //Is this pkg a theme?
+ if (metaDataBundle.containsKey(ThemeInfo.META_TAG_NAME)) {
+ pkg.mIsThemeApk = true;
+ pkg.mTrustedOverlay = true;
+ pkg.mOverlayPriority = 1;
+ pkg.mThemeInfo = new ThemeInfo(metaDataBundle);
+ }
return pkg;
}
@@ -2257,6 +2428,10 @@ public class PackageParser {
perm.info.flags = sa.getInt(
com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
+ perm.info.allowViaWhitelist = sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestPermission_allowViaWhitelist,
+ false);
+
sa.recycle();
if (perm.info.protectionLevel == -1) {
@@ -2409,6 +2584,10 @@ public class PackageParser {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
+ String[] nonThemeablePackages =
+ res.getStringArray(com.android.internal.R.array.non_themeable_packages);
+ ai.isThemeable = isPackageThemeable(pkgName, nonThemeablePackages);
+
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestApplication);
@@ -3238,6 +3417,26 @@ public class PackageParser {
if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
return null;
}
+
+ // Check if package is a legacy icon pack
+ if (!owner.mIsLegacyIconPackApk) {
+ for(String action : ThemeUtils.sSupportedActions) {
+ if (intent.hasAction(action)) {
+ owner.mIsLegacyIconPackApk = true;
+ break;
+ }
+
+ }
+ }
+ if (!owner.mIsLegacyIconPackApk) {
+ for(String category : ThemeUtils.sSupportedCategories) {
+ if (intent.hasCategory(category)) {
+ owner.mIsLegacyIconPackApk = true;
+ break;
+ }
+ }
+ }
+
if (intent.countActions() == 0) {
Slog.w(TAG, "No actions in intent filter at "
+ mArchiveSourcePath + " "
@@ -4247,6 +4446,22 @@ public class PackageParser {
return true;
}
+ /**1
+ * Returns whether the specified package is themeable
+ * @param packageName Name of package to check
+ * @param nonThemeablePackages Array of packages that are declared as non-themeable
+ * @return True if the package is themeable, false otherwise
+ */
+ private static boolean isPackageThemeable(String packageName, String[] nonThemeablePackages) {
+ for (String pkg : nonThemeablePackages) {
+ if (packageName.startsWith(pkg)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
/**
* Representation of a full package parsed from APK files on disk. A package
* consists of a single base APK, and zero or more split APKs.
@@ -4345,6 +4560,17 @@ public class PackageParser {
// For use by package manager to keep track of when a package was last used.
public long mLastPackageUsageTimeInMills;
+ // Is Theme Apk
+ public boolean mIsThemeApk = false;
+ public final ArrayList<String> mOverlayTargets = new ArrayList<String>(0);
+ public Map<String, Map<String, String>> mPackageRedirections
+ = new HashMap<String, Map<String, String>>();
+
+ // Theme info
+ public ThemeInfo mThemeInfo = null;
+
+ // Legacy icon pack
+ public boolean mIsLegacyIconPackApk = false;
// // User set enabled state.
// public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -4387,6 +4613,9 @@ public class PackageParser {
public int mOverlayPriority;
public boolean mTrustedOverlay;
+ public boolean hasIconPack;
+ public int manifestHashCode;
+
/**
* Data used to feed the KeySetManagerService
*/
@@ -4739,6 +4968,12 @@ public class PackageParser {
&& p.usesLibraryFiles != null) {
return true;
}
+ if (state.protectedComponents != null) {
+ boolean protect = state.protectedComponents.size() > 0;
+ if (p.applicationInfo.protect != protect) {
+ return true;
+ }
+ }
return false;
}
@@ -4772,6 +5007,9 @@ public class PackageParser {
ai.enabled = false;
}
ai.enabledSetting = state.enabled;
+ if (state.protectedComponents != null) {
+ ai.protect = state.protectedComponents.size() > 0;
+ }
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 9b28401..7b6d188 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -36,6 +36,8 @@ public class PackageUserState {
public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
+ public ArraySet<String> protectedComponents;
+ public ArraySet<String> visibleComponents;
public int domainVerificationStatus;
public int appLinkGeneration;
@@ -62,5 +64,9 @@ public class PackageUserState {
blockUninstall = o.blockUninstall;
domainVerificationStatus = o.domainVerificationStatus;
appLinkGeneration = o.appLinkGeneration;
+ protectedComponents = o.protectedComponents != null
+ ? new ArraySet<String>(o.protectedComponents) : null;
+ visibleComponents = o.visibleComponents != null
+ ? new ArraySet<String>(o.visibleComponents) : null;
}
}
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 9da2ba9..0fed65f 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -178,6 +178,14 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
*/
public CharSequence nonLocalizedDescription;
+ /**
+ * Whether this permission will be granted to apps signed with white-listed keys in
+ * /system/etc/permissions/someapp.xml
+ *
+ * @hide
+ */
+ public boolean allowViaWhitelist;
+
/** @hide */
public static int fixProtectionLevel(int level) {
if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -237,6 +245,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
group = orig.group;
descriptionRes = orig.descriptionRes;
nonLocalizedDescription = orig.nonLocalizedDescription;
+ allowViaWhitelist = orig.allowViaWhitelist;
}
/**
@@ -279,6 +288,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(flags);
dest.writeString(group);
dest.writeInt(descriptionRes);
+ dest.writeInt(allowViaWhitelist ? 1 : 0);
TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
}
@@ -298,6 +308,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
flags = source.readInt();
group = source.readString();
descriptionRes = source.readInt();
+ allowViaWhitelist = source.readInt() == 1;
nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
}
}
diff --git a/core/java/android/content/pm/ThemeInfo.aidl b/core/java/android/content/pm/ThemeInfo.aidl
new file mode 100644
index 0000000..acbc85e
--- /dev/null
+++ b/core/java/android/content/pm/ThemeInfo.aidl
@@ -0,0 +1,3 @@
+package android.content.pm;
+
+parcelable ThemeInfo;
diff --git a/core/java/android/content/pm/ThemeInfo.java b/core/java/android/content/pm/ThemeInfo.java
new file mode 100644
index 0000000..ab798db
--- /dev/null
+++ b/core/java/android/content/pm/ThemeInfo.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010, T-Mobile USA, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.content.res.Resources;
+
+/**
+ * Overall information about "theme" package. This corresponds
+ * to the information collected from AndroidManifest.xml
+ *
+ * Below is an example of the manifest:
+ *
+ * <meta-data android:name="org.cyanogenmod.theme.name" android:value="Foobar's Theme"/>
+ * <meta-data android:name="org.cyanogenmod.theme.author" android:value="Mr.Foo" />
+ *
+ * @hide
+ */
+public final class ThemeInfo extends BaseThemeInfo {
+
+ public static final String META_TAG_NAME = "org.cyanogenmod.theme.name";
+ public static final String META_TAG_AUTHOR = "org.cyanogenmod.theme.author";
+
+ public ThemeInfo(Bundle bundle) {
+ super();
+ name = bundle.getString(META_TAG_NAME);
+ themeId = name;
+ author = bundle.getString(META_TAG_AUTHOR);
+ }
+
+ public static final Parcelable.Creator<ThemeInfo> CREATOR
+ = new Parcelable.Creator<ThemeInfo>() {
+ public ThemeInfo createFromParcel(Parcel source) {
+ return new ThemeInfo(source);
+ }
+
+ public ThemeInfo[] newArray(int size) {
+ return new ThemeInfo[size];
+ }
+ };
+
+ private ThemeInfo(Parcel source) {
+ super(source);
+ }
+}
diff --git a/core/java/android/content/pm/ThemeUtils.java b/core/java/android/content/pm/ThemeUtils.java
new file mode 100644
index 0000000..07e73b5
--- /dev/null
+++ b/core/java/android/content/pm/ThemeUtils.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.content.res.ThemeConfig;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.jar.StrictJarFile;
+import java.util.zip.ZipEntry;
+
+/**
+ * @hide
+ */
+public class ThemeUtils {
+ private static final String TAG = ThemeUtils.class.getSimpleName();
+
+ /* Path inside a theme APK to the overlay folder */
+ public static final String OVERLAY_PATH = "assets/overlays/";
+ public static final String ICONS_PATH = "assets/icons/";
+ public static final String COMMON_RES_PATH = "assets/overlays/common/";
+ public static final String RESOURCE_CACHE_DIR = "/data/resource-cache/";
+ public static final String COMMON_RES_TARGET = "common";
+
+ // Package name for any app which does not have a specific theme applied
+ private static final String DEFAULT_PKG = "default";
+
+ private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+
+ /**
+ * IDMAP hash version code used to alter the resulting hash and force recreating
+ * of the idmap. This value should be changed whenever there is a need to force
+ * an update to all idmaps.
+ */
+ private static final byte IDMAP_HASH_VERSION = 3;
+
+ // Actions in manifests which identify legacy icon packs
+ public static final String[] sSupportedActions = new String[] {
+ "org.adw.launcher.THEMES",
+ "com.gau.go.launcherex.theme",
+ "com.novalauncher.THEME"
+ };
+
+ // Categories in manifests which identify legacy icon packs
+ public static final String[] sSupportedCategories = new String[] {
+ "com.fede.launcher.THEME_ICONPACK",
+ "com.anddoes.launcher.THEME",
+ "com.teslacoilsw.launcher.THEME"
+ };
+
+
+ /**
+ * Get the root path of the resource cache for the given theme
+ * @param themePkgName
+ * @return Root resource cache path for the given theme
+ */
+ public static String getOverlayResourceCacheDir(String themePkgName) {
+ return RESOURCE_CACHE_DIR + themePkgName;
+ }
+
+ /**
+ * Get the path of the resource cache for the given target and theme
+ * @param targetPkgName Target app package name
+ * @param themePkgName Theme package name
+ * @return Path to the resource cache for this target and theme
+ */
+ public static String getTargetCacheDir(String targetPkgName, String themePkgName) {
+ return getOverlayResourceCacheDir(themePkgName) + File.separator + targetPkgName;
+ }
+
+ /**
+ * Get the path to the icons for the given theme
+ * @param pkgName
+ * @return
+ */
+ public static String getIconPackDir(String pkgName) {
+ return getOverlayResourceCacheDir(pkgName) + File.separator + "icons";
+ }
+
+ public static String getIconPackApkPath(String pkgName) {
+ return getIconPackDir(pkgName) + "/resources.apk";
+ }
+
+ public static String getIdmapPath(String targetPkgName, String overlayPkgName) {
+ return getTargetCacheDir(targetPkgName, overlayPkgName) + File.separator + "idmap";
+ }
+
+ public static String getOverlayPathToTarget(String targetPkgName) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(OVERLAY_PATH);
+ sb.append(targetPkgName);
+ sb.append('/');
+ return sb.toString();
+ }
+
+ public static String getCommonPackageName(String themePackageName) {
+ if (TextUtils.isEmpty(themePackageName)) return null;
+
+ return COMMON_RES_TARGET;
+ }
+
+ /**
+ * Convenience method to determine if a theme component is a per app theme and not a standard
+ * component.
+ * @param component
+ * @return
+ */
+ public static boolean isPerAppThemeComponent(String component) {
+ return !(DEFAULT_PKG.equals(component)
+ || ThemeConfig.SYSTEMUI_STATUS_BAR_PKG.equals(component)
+ || ThemeConfig.SYSTEMUI_NAVBAR_PKG.equals(component));
+ }
+
+ /**
+ * Get a 32 bit hashcode for the given package.
+ * @param pkg
+ * @return
+ */
+ public static int getPackageHashCode(PackageParser.Package pkg, StrictJarFile jarFile) {
+ int hash = pkg.manifestDigest != null ? pkg.manifestDigest.hashCode() : 0;
+ final ZipEntry je = jarFile.findEntry(MANIFEST_NAME);
+ if (je != null) {
+ try {
+ try {
+ ManifestDigest digest = ManifestDigest.fromInputStream(
+ jarFile.getInputStream(je));
+ if (digest != null) {
+ hash += digest.hashCode();
+ }
+ } finally {
+ jarFile.close();
+ }
+ } catch (IOException | RuntimeException e) {
+ // Failed to generate digest from manifest.mf
+ }
+ }
+ hash = 31 * hash + IDMAP_HASH_VERSION;
+ return hash;
+ }
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 8d96f5c..abb1871 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -21,9 +21,11 @@ import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.HashMap;
/**
@@ -77,6 +79,16 @@ public final class AssetManager implements AutoCloseable {
private boolean mOpen = true;
private HashMap<Long, RuntimeException> mRefStacks;
+ private String mAppName;
+
+ private boolean mThemeSupport;
+ private String mThemePackageName;
+ private String mIconPackageName;
+ private String mCommonResPackageName;
+ private ArrayList<Integer> mThemeCookies = new ArrayList<Integer>(2);
+ private int mIconPackCookie;
+ private int mCommonResCookie;
+
/**
* Create a new AssetManager containing only the basic system assets.
* Applications will not generally use this method, instead retrieving the
@@ -252,6 +264,12 @@ public final class AssetManager implements AutoCloseable {
}
}
+ /*package*/ final void recreateStringBlocks() {
+ synchronized (this) {
+ makeStringBlocks(sSystem.mStringBlocks);
+ }
+ }
+
/*package*/ final void makeStringBlocks(StringBlock[] seed) {
final int seedNum = (seed != null) ? seed.length : 0;
final int num = getStringBlockCount();
@@ -612,7 +630,9 @@ public final class AssetManager implements AutoCloseable {
public final int addAssetPath(String path) {
synchronized (this) {
int res = addAssetPathNative(path);
- makeStringBlocks(mStringBlocks);
+ if (mStringBlocks != null) {
+ makeStringBlocks(mStringBlocks);
+ }
return res;
}
}
@@ -627,11 +647,14 @@ public final class AssetManager implements AutoCloseable {
*
* {@hide}
*/
-
- public final int addOverlayPath(String idmapPath) {
+ public final int addOverlayPath(String idmapPath, String themeApkPath,
+ String resApkPath, String targetPkgPath, String prefixPath) {
synchronized (this) {
- int res = addOverlayPathNative(idmapPath);
- makeStringBlocks(mStringBlocks);
+ int res = addOverlayPathNative(idmapPath, themeApkPath, resApkPath, targetPkgPath,
+ prefixPath);
+ if (mStringBlocks != null) {
+ makeStringBlocks(mStringBlocks);
+ }
return res;
}
}
@@ -641,7 +664,59 @@ public final class AssetManager implements AutoCloseable {
*
* {@hide}
*/
- public native final int addOverlayPathNative(String idmapPath);
+ private native final int addOverlayPathNative(String idmapPath, String themeApkPath,
+ String resApkPath, String targetPkgPath, String prefixPath);
+
+ /**
+ * Add a set of common assets.
+ *
+ * {@hide}
+ */
+ public final int addCommonOverlayPath(String themeApkPath,
+ String resApkPath, String prefixPath) {
+ synchronized (this) {
+ return addCommonOverlayPathNative(themeApkPath, resApkPath, prefixPath);
+ }
+ }
+
+ private native final int addCommonOverlayPathNative(String themeApkPath,
+ String resApkPath, String prefixPath);
+
+ /**
+ * Add a set of assets as an icon pack. A pkgIdOverride value will change the package's id from
+ * what is in the resource table to a new value. Manage this carefully, if icon pack has more
+ * than one package then that next package's id will use pkgIdOverride+1.
+ *
+ * Icon packs are different from overlays as they have a different pkg id and
+ * do not use idmap so no targetPkg is required
+ *
+ * {@hide}
+ */
+ public final int addIconPath(String idmapPath, String resApkPath,
+ String prefixPath, int pkgIdOverride) {
+ synchronized (this) {
+ return addIconPathNative(idmapPath, resApkPath, prefixPath, pkgIdOverride);
+ }
+ }
+
+ private native final int addIconPathNative(String idmapPath,
+ String resApkPath, String prefixPath, int pkgIdOverride);
+
+ /**
+ * Delete a set of overlay assets from the asset manager. Not for use by
+ * applications. Returns true if succeeded or false on failure.
+ *
+ * Also works for icon packs
+ *
+ * {@hide}
+ */
+ public final boolean removeOverlayPath(String packageName, int cookie) {
+ synchronized (this) {
+ return removeOverlayPathNative(packageName, cookie);
+ }
+ }
+
+ private native final boolean removeOverlayPathNative(String packageName, int cookie);
/**
* Add multiple sets of assets to the asset manager at once. See
@@ -664,6 +739,126 @@ public final class AssetManager implements AutoCloseable {
}
/**
+ * Sets a flag indicating that this AssetManager should have themes
+ * attached, according to the initial request to create it by the
+ * ApplicationContext.
+ *
+ * {@hide}
+ */
+ public final void setThemeSupport(boolean themeSupport) {
+ mThemeSupport = themeSupport;
+ }
+
+ /**
+ * Should this AssetManager have themes attached, according to the initial
+ * request to create it by the ApplicationContext?
+ *
+ * {@hide}
+ */
+ public final boolean hasThemeSupport() {
+ return mThemeSupport;
+ }
+
+ /**
+ * Get package name of current icon pack (may return null).
+ * {@hide}
+ */
+ public String getIconPackageName() {
+ return mIconPackageName;
+ }
+
+ /**
+ * Sets icon package name
+ * {@hide}
+ */
+ public void setIconPackageName(String packageName) {
+ mIconPackageName = packageName;
+ }
+
+ /**
+ * Get package name of current common resources (may return null).
+ * {@hide}
+ */
+ public String getCommonResPackageName() {
+ return mCommonResPackageName;
+ }
+
+ /**
+ * Sets common resources package name
+ * {@hide}
+ */
+ public void setCommonResPackageName(String packageName) {
+ mCommonResPackageName = packageName;
+ }
+
+ /**
+ * Get package name of current theme (may return null).
+ * {@hide}
+ */
+ public String getThemePackageName() {
+ return mThemePackageName;
+ }
+
+ /**
+ * Sets package name and highest level style id for current theme (null, 0 is allowed).
+ * {@hide}
+ */
+ public void setThemePackageName(String packageName) {
+ mThemePackageName = packageName;
+ }
+
+ /**
+ * Get asset cookie for current theme (may return 0).
+ * {@hide}
+ */
+ public ArrayList<Integer> getThemeCookies() {
+ return mThemeCookies;
+ }
+
+ /** {@hide} */
+ public void setIconPackCookie(int cookie) {
+ mIconPackCookie = cookie;
+ }
+
+ /** {@hide} */
+ public int getIconPackCookie() {
+ return mIconPackCookie;
+ }
+
+ /** {@hide} */
+ public void setCommonResCookie(int cookie) {
+ mCommonResCookie = cookie;
+ }
+
+ /** {@hide} */
+ public int getCommonResCookie() {
+ return mCommonResCookie;
+ }
+
+ /**
+ * Sets asset cookie for current theme (0 if not a themed asset manager).
+ * {@hide}
+ */
+ public void addThemeCookie(int cookie) {
+ mThemeCookies.add(cookie);
+ }
+
+ /** {@hide} */
+ public String getAppName() {
+ return mAppName;
+ }
+
+ /** {@hide} */
+ public void setAppName(String pkgName) {
+ mAppName = pkgName;
+ }
+
+ /** {@hide} */
+ public boolean hasThemedAssets() {
+ return mThemeCookies.size() > 0;
+ }
+
+ /**
* Determine whether the state in this asset manager is up-to-date with
* the files on the filesystem. If false is returned, you need to
* instantiate a new AssetManager class to see the new data.
@@ -800,6 +995,26 @@ public final class AssetManager implements AutoCloseable {
/*package*/ native final int[] getStyleAttributes(int themeRes);
private native final void init(boolean isSystem);
+ /**
+ * {@hide}
+ */
+ public native final int getBasePackageCount();
+
+ /**
+ * {@hide}
+ */
+ public native final String getBasePackageName(int index);
+
+ /**
+ * {@hide}
+ */
+ public native final String getBaseResourcePackageName(int index);
+
+ /**
+ * {@hide}
+ */
+ public native final int getBasePackageId(int index);
+
private native final void destroy();
private final void incRefsLocked(long id) {
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index da35ee9..2b8951e 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -241,8 +241,7 @@ public class CompatibilityInfo implements Parcelable {
mCompatibilityFlags = compatFlags;
}
- private CompatibilityInfo(int compFlags,
- int dens, float scale, float invertedScale) {
+ private CompatibilityInfo(int compFlags, int dens, float scale, float invertedScale) {
mCompatibilityFlags = compFlags;
applicationDensity = dens;
applicationScale = scale;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index fd60476..0bc1ec2 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,6 +83,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public Locale locale;
/**
+ * @hide
+ */
+ public ThemeConfig themeConfig;
+
+ /**
* Locale should persist on setting. This is hidden because it is really
* questionable whether this is the right way to expose the functionality.
* @hide
@@ -441,7 +447,47 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public static final int ORIENTATION_LANDSCAPE = 2;
/** @deprecated Not currently supported or used. */
@Deprecated public static final int ORIENTATION_SQUARE = 3;
-
+
+ /**
+ * @hide
+ * @deprecated
+ */
+ public static final String THEME_PACKAGE_NAME_PERSISTENCE_PROPERTY
+ = "persist.sys.themePackageName";
+
+ /**
+ * @hide
+ * @deprecated
+ */
+ public static final String THEME_ICONPACK_PACKAGE_NAME_PERSISTENCE_PROPERTY
+ = "themeIconPackPkgName";
+
+ /**
+ * @hide
+ * @deprecated
+ */
+ public static final String THEME_FONT_PACKAGE_NAME_PERSISTENCE_PROPERTY
+ = "themeFontPackPkgName";
+
+ /**
+ * @hide
+ * Serialized json structure mapping app pkgnames to their set theme.
+ *
+ * {
+ * "default":{
+ *" stylePkgName":"com.jasonevil.theme.miuiv5dark",
+ * "iconPkgName":"com.cyngn.hexo",
+ * "fontPkgName":"com.cyngn.hexo"
+ * }
+ * }
+
+ * If an app does not have a specific theme set then it will use the 'default' theme+
+ * example: 'default' -> overlayPkgName: 'org.blue.theme'
+ * 'com.android.phone' -> 'com.red.theme'
+ * 'com.google.vending' -> 'com.white.theme'
+ */
+ public static final String THEME_PKG_CONFIGURATION_PERSISTENCE_PROPERTY = "themeConfig";
+
/**
* Overall orientation of the screen. May be one of
* {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
@@ -673,8 +719,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatScreenHeightDp = o.compatScreenHeightDp;
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
seq = o.seq;
+ if (o.themeConfig != null) {
+ themeConfig = (ThemeConfig) o.themeConfig.clone();
+ }
}
-
+
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("{");
@@ -809,6 +858,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
sb.append(" s.");
sb.append(seq);
}
+ sb.append(" themeResource=");
+ sb.append(themeConfig);
sb.append('}');
return sb.toString();
}
@@ -835,6 +886,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
densityDpi = DENSITY_DPI_UNDEFINED;
seq = 0;
+ themeConfig = null;
}
/** {@hide} */
@@ -977,7 +1029,18 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (delta.seq != 0) {
seq = delta.seq;
}
-
+
+ if (delta.themeConfig != null
+ && (themeConfig == null || !themeConfig.equals(delta.themeConfig))) {
+ changed |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ final String fontPkgName = delta.themeConfig.getFontPkgName();
+ if (themeConfig == null ||
+ (fontPkgName != null && !fontPkgName.equals(themeConfig.getFontPkgName()))) {
+ changed |= ActivityInfo.CONFIG_THEME_FONT;
+ }
+ themeConfig = (ThemeConfig)delta.themeConfig.clone();
+ }
+
return changed;
}
@@ -1087,7 +1150,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration
&& densityDpi != delta.densityDpi) {
changed |= ActivityInfo.CONFIG_DENSITY;
}
-
+ if (delta.themeConfig != null &&
+ (themeConfig == null || !themeConfig.equals(delta.themeConfig))) {
+ changed |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ final String fontPkgName = delta.themeConfig.getFontPkgName();
+ if (themeConfig == null ||
+ (fontPkgName != null && !fontPkgName.equals(themeConfig.getFontPkgName()))) {
+ changed |= ActivityInfo.CONFIG_THEME_FONT;
+ }
+ }
return changed;
}
@@ -1103,7 +1174,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* @return Return true if the resource needs to be loaded, else false.
*/
public static boolean needNewResources(int configChanges, int interestingChanges) {
- return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
+ return (configChanges & (interestingChanges |
+ ActivityInfo.CONFIG_FONT_SCALE |
+ ActivityInfo.CONFIG_THEME_RESOURCE)) != 0;
}
/**
@@ -1176,6 +1249,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(compatScreenHeightDp);
dest.writeInt(compatSmallestScreenWidthDp);
dest.writeInt(seq);
+ dest.writeParcelable(themeConfig, flags);
}
public void readFromParcel(Parcel source) {
@@ -1204,6 +1278,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatScreenHeightDp = source.readInt();
compatSmallestScreenWidthDp = source.readInt();
seq = source.readInt();
+ themeConfig = source.readParcelable(ThemeConfig.class.getClassLoader());
}
public static final Parcelable.Creator<Configuration> CREATOR
@@ -1271,7 +1346,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration
n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
if (n != 0) return n;
n = this.densityDpi - that.densityDpi;
- //if (n != 0) return n;
+ if (n != 0) return n;
+ if (this.themeConfig == null) {
+ if (that.themeConfig != null) return 1;
+ } else {
+ n = this.themeConfig.compareTo(that.themeConfig);
+ }
return n;
}
@@ -1308,6 +1388,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
result = 31 * result + screenHeightDp;
result = 31 * result + smallestScreenWidthDp;
result = 31 * result + densityDpi;
+ result = 31 * result + (this.themeConfig != null ?
+ this.themeConfig.hashCode() : 0);
return result;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 8272458..6a404e2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -21,6 +21,9 @@ import android.annotation.ColorInt;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
import com.android.internal.util.GrowingArrayUtils;
+import android.app.ComposedIconInfo;
+import android.app.IconPackHelper;
+import android.app.IconPackHelper.IconCustomizer;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -45,6 +48,7 @@ import android.annotation.RawRes;
import android.annotation.StringRes;
import android.annotation.XmlRes;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageItemInfo;
import android.graphics.Movie;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -59,6 +63,7 @@ import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pools.SynchronizedPool;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ViewDebug;
import android.view.ViewHierarchyEncoder;
@@ -108,6 +113,20 @@ public class Resources {
private static final int ID_OTHER = 0x01000004;
+ // Package IDs for themes. Aapt will compile the res table with this id.
+ /** @hide */
+ public static final int THEME_FRAMEWORK_PKG_ID = 0x60;
+ /** @hide */
+ public static final int THEME_APP_PKG_ID = 0x61;
+ /** @hide */
+ public static final int THEME_ICON_PKG_ID = 0x62;
+ /**
+ * The common resource pkg id needs to be less than the THEME_FRAMEWORK_PKG_ID
+ * otherwise aapt will complain and fail
+ * @hide
+ */
+ public static final int THEME_COMMON_PKG_ID = THEME_FRAMEWORK_PKG_ID - 1;
+
private static final Object sSync = new Object();
// Information about preloaded resources. Note that they are not
@@ -158,6 +177,9 @@ public class Resources {
private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ private SparseArray<PackageItemInfo> mIcons;
+ private ComposedIconInfo mComposedIconInfo;
+
static {
sPreloadedDrawables = new LongSparseArray[2];
sPreloadedDrawables[0] = new LongSparseArray<>();
@@ -268,7 +290,7 @@ public class Resources {
mCompatibilityInfo = compatInfo;
}
updateConfiguration(config, metrics);
- assets.ensureStringBlocks();
+ assets.recreateStringBlocks();
}
/**
@@ -793,6 +815,19 @@ public class Resources {
*/
@Nullable
public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme) throws NotFoundException {
+ return getDrawable(id, theme, true);
+ }
+
+ /** @hide */
+ @Nullable
+ public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme, boolean supportComposedIcons)
+ throws NotFoundException {
+ //Check if an icon is themed
+ PackageItemInfo info = mIcons != null ? mIcons.get(id) : null;
+ if (info != null && info.themedIcon != 0) {
+ id = info.themedIcon;
+ }
+
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -801,9 +836,24 @@ public class Resources {
} else {
mTmpValue = null;
}
- getValue(id, value, true);
+ getValue(id, value, true, supportComposedIcons);
+ }
+ Drawable res = null;
+ try {
+ res = loadDrawable(value, id, theme);
+ } catch (NotFoundException e) {
+ // The below statement will be true if we were trying to load a composed icon.
+ // Since we received a NotFoundException, try to load the original if this
+ // condition is true, otherwise throw the original exception.
+ if (supportComposedIcons && mComposedIconInfo != null && info != null &&
+ info.themedIcon == 0) {
+ Log.e(TAG, "Failed to retrieve composed icon.", e);
+ getValue(id, value, true, false);
+ res = loadDrawable(value, id, theme);
+ } else {
+ throw e;
+ }
}
- final Drawable res = loadDrawable(value, id, theme);
synchronized (mAccessLock) {
if (mTmpValue == null) {
mTmpValue = value;
@@ -860,6 +910,19 @@ public class Resources {
*/
@Nullable
public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
+ return getDrawableForDensity(id, density, theme, true);
+ }
+
+ /** @hide */
+ @Nullable
+ public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme,
+ boolean supportComposedIcons) {
+ //Check if an icon was themed
+ PackageItemInfo info = mIcons != null ? mIcons.get(id) : null;
+ if (info != null && info.themedIcon != 0) {
+ id = info.themedIcon;
+ }
+
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -868,7 +931,7 @@ public class Resources {
} else {
mTmpValue = null;
}
- getValueForDensity(id, density, value, true);
+ getValueForDensity(id, density, value, true, supportComposedIcons);
/*
* Pretend the requested density is actually the display density. If
@@ -1344,8 +1407,24 @@ public class Resources {
*/
public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
+ getValue(id, outValue, resolveRefs, true);
+ }
+
+ /** @hide */
+ public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs,
+ boolean supportComposedIcons) throws NotFoundException {
+ //Check if an icon was themed
+ PackageItemInfo info = mIcons != null ? mIcons.get(id) : null;
+ if (info != null && info.themedIcon != 0) {
+ id = info.themedIcon;
+ }
boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
if (found) {
+ if (supportComposedIcons && IconPackHelper.shouldComposeIcon(mComposedIconInfo)
+ && info != null && info.themedIcon == 0) {
+ Drawable dr = loadDrawable(outValue, id, null);
+ IconCustomizer.getValue(this, id, outValue, dr);
+ }
return;
}
throw new NotFoundException("Resource ID #0x"
@@ -1367,8 +1446,45 @@ public class Resources {
*/
public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
boolean resolveRefs) throws NotFoundException {
+ getValueForDensity(id, density, outValue, resolveRefs, true);
+ }
+
+ /** @hide */
+ public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
+ boolean resolveRefs, boolean supportComposedIcons) throws NotFoundException {
+ //Check if an icon was themed
+ PackageItemInfo info = mIcons != null ? mIcons.get(id) : null;
+ if (info != null && info.themedIcon != 0) {
+ id = info.themedIcon;
+ }
+
boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
if (found) {
+ if (supportComposedIcons && IconPackHelper.shouldComposeIcon(mComposedIconInfo) &&
+ info != null && info.themedIcon == 0) {
+ int tmpDensity = outValue.density;
+ /*
+ * Pretend the requested density is actually the display density. If
+ * the drawable returned is not the requested density, then force it
+ * to be scaled later by dividing its density by the ratio of
+ * requested density to actual device density. Drawables that have
+ * undefined density or no density don't need to be handled here.
+ */
+ if (outValue.density > 0 && outValue.density != TypedValue.DENSITY_NONE) {
+ if (outValue.density == density) {
+ outValue.density = mMetrics.densityDpi;
+ } else {
+ outValue.density = (outValue.density * mMetrics.densityDpi) / density;
+ }
+ }
+ Drawable dr = loadDrawable(outValue, id, null);
+
+ // Return to original density. If we do not do this then
+ // the caller will get the wrong density for the given id and perform
+ // more of its own scaling in loadDrawable
+ outValue.density = tmpDensity;
+ IconCustomizer.getValue(this, id, outValue, dr);
+ }
return;
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
@@ -1968,8 +2084,13 @@ public class Resources {
mConfiguration.setLayoutDirection(mConfiguration.locale);
}
if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
- mMetrics.densityDpi = mConfiguration.densityDpi;
- mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ if (DisplayMetrics.DENSITY_DEVICE_DEFAULT == mCompatibilityInfo.applicationDensity
+ && (config != null
+ && config.densityDpi == DisplayMetrics.DENSITY_DEVICE_DEFAULT)) {
+ mMetrics.setDensity(DisplayMetrics.DENSITY_PREFERRED);
+ } else {
+ mMetrics.setDensity(mConfiguration.densityDpi);
+ }
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
@@ -2046,7 +2167,15 @@ public class Resources {
mTmpConfig.setLayoutDirection(mTmpConfig.locale);
}
configChanges = mConfiguration.updateFrom(mTmpConfig);
- configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+
+ /* This is ugly, but modifying the activityInfoConfigToNative
+ * adapter would be messier */
+ if ((configChanges & ActivityInfo.CONFIG_THEME_RESOURCE) != 0) {
+ configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+ configChanges |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ } else {
+ configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+ }
}
return configChanges;
}
@@ -2391,7 +2520,7 @@ public class Resources {
}
sPreloaded = true;
mPreloading = true;
- sPreloadedDensity = DisplayMetrics.DENSITY_DEVICE;
+ sPreloadedDensity = DisplayMetrics.DENSITY_PREFERRED;
mConfiguration.densityDpi = sPreloadedDensity;
updateConfiguration(null, null);
}
@@ -2489,9 +2618,10 @@ public class Resources {
// attributes.
final ConstantState cs;
if (isColorDrawable) {
- cs = sPreloadedColorDrawables.get(key);
+ cs = mAssets.hasThemedAssets() ? null : sPreloadedColorDrawables.get(key);
} else {
- cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
+ cs = mAssets.hasThemedAssets() ? null :
+ sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
}
Drawable dr;
@@ -2629,7 +2759,7 @@ public class Resources {
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
&& value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
final android.content.res.ConstantState<ColorStateList> factory =
- sPreloadedColorStateLists.get(key);
+ mAssets.hasThemedAssets() ? null : sPreloadedColorStateLists.get(key);
if (factory != null) {
return factory.newInstance();
}
@@ -2653,7 +2783,7 @@ public class Resources {
}
final android.content.res.ConstantState<ColorStateList> factory =
- sPreloadedColorStateLists.get(key);
+ mAssets.hasThemedAssets() ? null : sPreloadedColorStateLists.get(key);
if (factory != null) {
csl = factory.newInstance(this, theme);
}
@@ -2808,6 +2938,28 @@ public class Resources {
return theme.obtainStyledAttributes(set, attrs, 0, 0);
}
+ /** @hide */
+ public void setIconResources(SparseArray<PackageItemInfo> icons) {
+ mIcons = icons;
+ }
+
+ /** @hide */
+ public void setComposedIconInfo(ComposedIconInfo iconInfo) {
+ mComposedIconInfo = iconInfo;
+ }
+
+ /** @hide */
+ public ComposedIconInfo getComposedIconInfo() {
+ return mComposedIconInfo;
+ }
+
+ /** @hide */
+ public final void updateStringCache() {
+ synchronized (mAccessLock) {
+ mAssets.recreateStringBlocks();
+ }
+ }
+
private Resources() {
mAssets = AssetManager.getSystem();
// NOTE: Intentionally leaving this uninitialized (all values set
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 2620571..6cbf1d7 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -24,25 +24,31 @@ import java.util.Objects;
public final class ResourcesKey {
private final String mResDir;
private final float mScale;
+ private final boolean mIsThemeable;
private final int mHash;
+ private final ThemeConfig mThemeConfig;
public final int mDisplayId;
@NonNull
public final Configuration mOverrideConfiguration;
public ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
- float scale) {
+ float scale, boolean isThemeable, ThemeConfig themeConfig) {
mResDir = resDir;
mDisplayId = displayId;
mOverrideConfiguration = overrideConfiguration != null
? overrideConfiguration : Configuration.EMPTY;
mScale = scale;
+ mIsThemeable = isThemeable;
+ mThemeConfig = themeConfig;
int hash = 17;
hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
hash = 31 * hash + mDisplayId;
hash = 31 * hash + mOverrideConfiguration.hashCode();
hash = 31 * hash + Float.floatToIntBits(mScale);
+ hash = 31 * hash + (mIsThemeable ? 1 : 0);
+ hash = 31 * hash + (themeConfig != null ? themeConfig.hashCode() : 0);
mHash = hash;
}
@@ -74,6 +80,17 @@ public final class ResourcesKey {
if (mScale != peer.mScale) {
return false;
}
+ if (mIsThemeable != peer.mIsThemeable) {
+ return false;
+ }
+ if (mThemeConfig != peer.mThemeConfig) {
+ if (mThemeConfig == null || peer.mThemeConfig == null) {
+ return false;
+ }
+ if (!mThemeConfig.equals(peer.mThemeConfig)) {
+ return false;
+ }
+ }
return true;
}
diff --git a/core/java/android/content/res/ThemeConfig.java b/core/java/android/content/res/ThemeConfig.java
new file mode 100644
index 0000000..f304801
--- /dev/null
+++ b/core/java/android/content/res/ThemeConfig.java
@@ -0,0 +1,579 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ * Portions copyright (C) 2014, T-Mobile USA, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.res;
+
+import android.content.ContentResolver;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.JsonReader;
+import android.util.JsonToken;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * The Theme Configuration allows lookup of a theme element (fonts, icon, overlay) for a given
+ * application. If there isn't a particular theme designated to an app, it will fallback on the
+ * default theme. If there isn't a default theme then it will simply fallback to holo.
+ *
+ * @hide
+ */
+public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfig> {
+ public static final String TAG = ThemeConfig.class.getCanonicalName();
+ public static final String SYSTEM_DEFAULT = "system";
+
+ /**
+ * Special package name for theming the navbar separate from the rest of SystemUI
+ */
+ public static final String SYSTEMUI_NAVBAR_PKG = "com.android.systemui.navbar";
+ public static final String SYSTEMUI_STATUS_BAR_PKG = "com.android.systemui";
+
+ // Key for any app which does not have a specific theme applied
+ private static final String KEY_DEFAULT_PKG = "default";
+ private static final SystemConfig mSystemConfig = new SystemConfig();
+ private static final SystemAppTheme mSystemAppTheme = new SystemAppTheme();
+
+ // Maps pkgname to theme (ex com.angry.birds -> red theme)
+ protected final Map<String, AppTheme> mThemes = new ArrayMap<>();
+
+ public ThemeConfig(Map<String, AppTheme> appThemes) {
+ mThemes.putAll(appThemes);
+ }
+
+ public String getOverlayPkgName() {
+ AppTheme theme = getDefaultTheme();
+ return theme.mOverlayPkgName;
+ }
+
+ public String getOverlayForStatusBar() {
+ return getOverlayPkgNameForApp(SYSTEMUI_STATUS_BAR_PKG);
+ }
+
+ public String getOverlayForNavBar() {
+ return getOverlayPkgNameForApp(SYSTEMUI_NAVBAR_PKG);
+ }
+
+ public String getOverlayPkgNameForApp(String appPkgName) {
+ AppTheme theme = getThemeFor(appPkgName);
+ return theme.mOverlayPkgName;
+ }
+
+ public String getIconPackPkgName() {
+ AppTheme theme = getDefaultTheme();
+ return theme.mIconPkgName;
+ }
+
+ public String getIconPackPkgNameForApp(String appPkgName) {
+ AppTheme theme = getThemeFor(appPkgName);
+ return theme.mIconPkgName;
+ }
+
+ public String getFontPkgName() {
+ AppTheme defaultTheme = getDefaultTheme();
+ return defaultTheme.mFontPkgName;
+ }
+
+ public String getFontPkgNameForApp(String appPkgName) {
+ AppTheme theme = getThemeFor(appPkgName);
+ return theme.mFontPkgName;
+ }
+
+ public Map<String, AppTheme> getAppThemes() {
+ return Collections.unmodifiableMap(mThemes);
+ }
+
+ private AppTheme getThemeFor(String pkgName) {
+ AppTheme theme = mThemes.get(pkgName);
+ if (theme == null) theme = getDefaultTheme();
+ return theme;
+ }
+
+ private AppTheme getDefaultTheme() {
+ AppTheme theme = mThemes.get(KEY_DEFAULT_PKG);
+ if (theme == null) theme = mSystemAppTheme;
+ return theme;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof ThemeConfig) {
+ ThemeConfig o = (ThemeConfig) object;
+
+ Map<String, AppTheme> currThemes = (mThemes == null) ?
+ new ArrayMap<String, AppTheme>() : mThemes;
+ Map<String, AppTheme> newThemes = (o.mThemes == null) ?
+ new ArrayMap<String, AppTheme>() : o.mThemes;
+
+ return currThemes.equals(newThemes);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ if (mThemes != null) {
+ result.append("themes:");
+ result.append(mThemes);
+ }
+ return result.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 17;
+ hash = 31 * hash + mThemes.hashCode();
+ return hash;
+ }
+
+ public String toJson() {
+ return JsonSerializer.toJson(this);
+ }
+
+ public static ThemeConfig fromJson(String json) {
+ return JsonSerializer.fromJson(json);
+ }
+
+ /**
+ * Represents the theme that the device booted into. This is used to
+ * simulate a "default" configuration based on the user's last known
+ * preference until the theme is switched at runtime.
+ */
+ public static ThemeConfig getBootTheme(ContentResolver resolver) {
+ return getBootThemeForUser(resolver, UserHandle.USER_OWNER);
+ }
+
+ public static ThemeConfig getBootThemeForUser(ContentResolver resolver, int userHandle) {
+ ThemeConfig bootTheme = mSystemConfig;
+ try {
+ String json = Settings.Secure.getStringForUser(resolver,
+ Configuration.THEME_PKG_CONFIGURATION_PERSISTENCE_PROPERTY, userHandle);
+ bootTheme = ThemeConfig.fromJson(json);
+
+ // Handle upgrade Case: Previously the theme configuration was in separate fields
+ if (bootTheme == null) {
+ String overlayPkgName = Settings.Secure.getStringForUser(resolver,
+ Configuration.THEME_PACKAGE_NAME_PERSISTENCE_PROPERTY, userHandle);
+ String iconPackPkgName = Settings.Secure.getStringForUser(resolver,
+ Configuration.THEME_ICONPACK_PACKAGE_NAME_PERSISTENCE_PROPERTY, userHandle);
+ String fontPkgName = Settings.Secure.getStringForUser(resolver,
+ Configuration.THEME_FONT_PACKAGE_NAME_PERSISTENCE_PROPERTY, userHandle);
+
+ Builder builder = new Builder();
+ builder.defaultOverlay(overlayPkgName);
+ builder.defaultIcon(iconPackPkgName);
+ builder.defaultFont(fontPkgName);
+ bootTheme = builder.build();
+ }
+ } catch (SecurityException e) {
+ Log.w(TAG, "Could not get boot theme");
+ }
+ return bootTheme;
+ }
+
+ /**
+ * Represents the system framework theme, perceived by the system as there
+ * being no theme applied.
+ */
+ public static ThemeConfig getSystemTheme() {
+ return mSystemConfig;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ String json = JsonSerializer.toJson(this);
+ dest.writeString(json);
+ }
+
+ public static final Parcelable.Creator<ThemeConfig> CREATOR =
+ new Parcelable.Creator<ThemeConfig>() {
+ public ThemeConfig createFromParcel(Parcel source) {
+ String json = source.readString();
+ ThemeConfig themeConfig = JsonSerializer.fromJson(json);
+ return themeConfig;
+ }
+
+ public ThemeConfig[] newArray(int size) {
+ return new ThemeConfig[size];
+ }
+ };
+
+ @Override
+ public int compareTo(ThemeConfig o) {
+ if (o == null) return -1;
+ int n = 0;
+ n = mThemes.equals(o.mThemes) ? 0 : 1;
+ return n;
+ }
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ Log.d(TAG, "clone not supported", e);
+ return null;
+ }
+ }
+
+ public static class AppTheme implements Cloneable, Comparable<AppTheme> {
+ // If any field is modified or added here be sure to change the serializer accordingly
+ String mOverlayPkgName;
+ String mIconPkgName;
+ String mFontPkgName;
+
+ public AppTheme(String overlayPkgName, String iconPkgName, String fontPkgName) {
+ mOverlayPkgName = overlayPkgName;
+ mIconPkgName = iconPkgName;
+ mFontPkgName = fontPkgName;
+ }
+
+ public String getIconPackPkgName() {
+ return mIconPkgName;
+ }
+
+ public String getOverlayPkgName() {
+ return mOverlayPkgName;
+ }
+
+ public String getFontPackPkgName() {
+ return mFontPkgName;
+ }
+
+ @Override
+ public synchronized int hashCode() {
+ int hash = 17;
+ hash = 31 * hash + (mOverlayPkgName == null ? 0 : mOverlayPkgName.hashCode());
+ hash = 31 * hash + (mIconPkgName == null ? 0 : mIconPkgName.hashCode());
+ hash = 31 * hash + (mFontPkgName == null ? 0 : mFontPkgName.hashCode());
+ return hash;
+ }
+
+ @Override
+ public int compareTo(AppTheme o) {
+ if (o == null) return -1;
+ int n = 0;
+ n = mIconPkgName.compareTo(o.mIconPkgName);
+ if (n != 0) return n;
+ n = mFontPkgName.compareTo(o.mFontPkgName);
+ if (n != 0) return n;
+ n = mOverlayPkgName.equals(o.mOverlayPkgName) ? 0 : 1;
+ return n;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof AppTheme) {
+ AppTheme o = (AppTheme) object;
+ String currentOverlayPkgName = (mOverlayPkgName == null)? "" : mOverlayPkgName;
+ String newOverlayPkgName = (o.mOverlayPkgName == null)? "" : o.mOverlayPkgName;
+ String currentIconPkgName = (mIconPkgName == null)? "" : mIconPkgName;
+ String newIconPkgName = (o.mIconPkgName == null)? "" : o.mIconPkgName;
+ String currentFontPkgName = (mFontPkgName == null)? "" : mFontPkgName;
+ String newFontPkgName = (o.mFontPkgName == null)? "" : o.mFontPkgName;
+
+
+ return (currentIconPkgName.equals(newIconPkgName) &&
+ currentFontPkgName.equals(newFontPkgName) &&
+ currentOverlayPkgName.equals(newOverlayPkgName));
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ if (mOverlayPkgName != null) {
+ result.append("overlay:");
+ result.append(mOverlayPkgName);
+ }
+
+ if (!TextUtils.isEmpty(mIconPkgName)) {
+ result.append(", iconPack:");
+ result.append(mIconPkgName);
+ }
+
+ if (!TextUtils.isEmpty(mFontPkgName)) {
+ result.append(", fontPkg:");
+ result.append(mFontPkgName);
+ }
+ return result.toString();
+ }
+ }
+
+
+ public static class Builder {
+ private Map<String, String> mOverlays = new ArrayMap<>();
+ private Map<String, String> mIcons = new ArrayMap<>();
+ private Map<String, String> mFonts = new ArrayMap<>();
+
+ public Builder() {}
+
+ public Builder(ThemeConfig theme) {
+ for(Map.Entry<String, AppTheme> entry : theme.mThemes.entrySet()) {
+ String key = entry.getKey();
+ AppTheme appTheme = entry.getValue();
+ mFonts.put(key, appTheme.getFontPackPkgName());
+ mIcons.put(key, appTheme.getIconPackPkgName());
+ mOverlays.put(key, appTheme.getOverlayPkgName());
+ }
+ }
+
+ /**
+ * For uniquely theming a specific app. ex. "Dialer gets red theme,
+ * Calculator gets blue theme"
+ */
+ public Builder defaultOverlay(String themePkgName) {
+ if (themePkgName != null) {
+ mOverlays.put(KEY_DEFAULT_PKG, themePkgName);
+ } else {
+ mOverlays.remove(KEY_DEFAULT_PKG);
+ }
+ return this;
+ }
+
+ public Builder defaultFont(String themePkgName) {
+ if (themePkgName != null) {
+ mFonts.put(KEY_DEFAULT_PKG, themePkgName);
+ } else {
+ mFonts.remove(KEY_DEFAULT_PKG);
+ }
+ return this;
+ }
+
+ public Builder defaultIcon(String themePkgName) {
+ if (themePkgName != null) {
+ mIcons.put(KEY_DEFAULT_PKG, themePkgName);
+ } else {
+ mIcons.remove(KEY_DEFAULT_PKG);
+ }
+ return this;
+ }
+
+ public Builder icon(String appPkgName, String themePkgName) {
+ if (themePkgName != null) {
+ mIcons.put(appPkgName, themePkgName);
+ } else {
+ mIcons.remove(appPkgName);
+ }
+ return this;
+ }
+
+ public Builder overlay(String appPkgName, String themePkgName) {
+ if (themePkgName != null) {
+ mOverlays.put(appPkgName, themePkgName);
+ } else {
+ mOverlays.remove(appPkgName);
+ }
+ return this;
+ }
+
+ public Builder font(String appPkgName, String themePkgName) {
+ if (themePkgName != null) {
+ mFonts.put(appPkgName, themePkgName);
+ } else {
+ mFonts.remove(appPkgName);
+ }
+ return this;
+ }
+
+ public ThemeConfig build() {
+ ArraySet<String> appPkgSet = new ArraySet<>();
+ appPkgSet.addAll(mOverlays.keySet());
+ appPkgSet.addAll(mIcons.keySet());
+ appPkgSet.addAll(mFonts.keySet());
+
+ Map<String, AppTheme> appThemes = new ArrayMap<>();
+ for(String appPkgName : appPkgSet) {
+ String icon = mIcons.get(appPkgName);
+ String overlay = mOverlays.get(appPkgName);
+ String font = mFonts.get(appPkgName);
+
+ // Remove app theme if all items are null
+ if (overlay == null && icon == null && font == null) {
+ if (appThemes.containsKey(appPkgName)) {
+ appThemes.remove(appPkgName);
+ }
+ } else {
+ AppTheme appTheme = new AppTheme(overlay, icon, font);
+ appThemes.put(appPkgName, appTheme);
+ }
+ }
+ ThemeConfig themeConfig = new ThemeConfig(appThemes);
+ return themeConfig;
+ }
+ }
+
+
+ public static class JsonSerializer {
+ private static final String NAME_OVERLAY_PKG = "mOverlayPkgName";
+ private static final String NAME_ICON_PKG = "mIconPkgName";
+ private static final String NAME_FONT_PKG = "mFontPkgName";
+
+ public static String toJson(ThemeConfig theme) {
+ String json = null;
+ Writer writer = null;
+ JsonWriter jsonWriter = null;
+ try {
+ writer = new StringWriter();
+ jsonWriter = new JsonWriter(writer);
+ writeTheme(jsonWriter, theme);
+ json = writer.toString();
+ } catch(IOException e) {
+ Log.e(TAG, "Could not write theme mapping", e);
+ } finally {
+ closeQuietly(writer);
+ closeQuietly(jsonWriter);
+ }
+ return json;
+ }
+
+ private static void writeTheme(JsonWriter writer, ThemeConfig theme)
+ throws IOException {
+ writer.beginObject();
+ for(Map.Entry<String, AppTheme> entry : theme.mThemes.entrySet()) {
+ String appPkgName = entry.getKey();
+ AppTheme appTheme = entry.getValue();
+ writer.name(appPkgName);
+ writeAppTheme(writer, appTheme);
+ }
+ writer.endObject();
+ }
+
+ private static void writeAppTheme(JsonWriter writer, AppTheme appTheme) throws IOException {
+ writer.beginObject();
+ writer.name(NAME_OVERLAY_PKG).value(appTheme.mOverlayPkgName);
+ writer.name(NAME_ICON_PKG).value(appTheme.mIconPkgName);
+ writer.name(NAME_FONT_PKG).value(appTheme.mFontPkgName);
+ writer.endObject();
+ }
+
+ public static ThemeConfig fromJson(String json) {
+ if (json == null) return null;
+ Map<String, AppTheme> map = new ArrayMap<>();
+ StringReader reader = null;
+ JsonReader jsonReader = null;
+ try {
+ reader = new StringReader(json);
+ jsonReader = new JsonReader(reader);
+ jsonReader.beginObject();
+ while (jsonReader.hasNext()) {
+ String appPkgName = jsonReader.nextName();
+ AppTheme appTheme = readAppTheme(jsonReader);
+ map.put(appPkgName, appTheme);
+ }
+ jsonReader.endObject();
+ } catch(Exception e) {
+ Log.e(TAG, "Could not parse ThemeConfig from: " + json, e);
+ } finally {
+ closeQuietly(reader);
+ closeQuietly(jsonReader);
+ }
+ return new ThemeConfig(map);
+ }
+
+ private static AppTheme readAppTheme(JsonReader reader) throws IOException {
+ String overlay = null;
+ String icon = null;
+ String font = null;
+
+ reader.beginObject();
+ while(reader.hasNext()) {
+ String name = reader.nextName();
+ if (NAME_OVERLAY_PKG.equals(name) && reader.peek() != JsonToken.NULL) {
+ overlay = reader.nextString();
+ } else if (NAME_ICON_PKG.equals(name) && reader.peek() != JsonToken.NULL) {
+ icon = reader.nextString();
+ } else if (NAME_FONT_PKG.equals(name) && reader.peek() != JsonToken.NULL) {
+ font = reader.nextString();
+ } else {
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+
+ return new AppTheme(overlay, icon, font);
+ }
+
+ private static void closeQuietly(Reader reader) {
+ try {
+ if (reader != null) reader.close();
+ } catch(IOException e) {
+ }
+ }
+
+ private static void closeQuietly(JsonReader reader) {
+ try {
+ if (reader != null) reader.close();
+ } catch(IOException e) {
+ }
+ }
+
+ private static void closeQuietly(Writer writer) {
+ try {
+ if (writer != null) writer.close();
+ } catch(IOException e) {
+ }
+ }
+
+ private static void closeQuietly(JsonWriter writer) {
+ try {
+ if (writer != null) writer.close();
+ } catch(IOException e) {
+ }
+ }
+ }
+
+ public static class SystemConfig extends ThemeConfig {
+ public SystemConfig() {
+ super(new ArrayMap<String, AppTheme>());
+ }
+ }
+
+ public static class SystemAppTheme extends AppTheme {
+ public SystemAppTheme() {
+ super(SYSTEM_DEFAULT, SYSTEM_DEFAULT, SYSTEM_DEFAULT);
+ }
+
+ @Override
+ public String toString() {
+ return "No Theme Applied (System)";
+ }
+ }
+}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 3cda39a..6ab9637 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -387,6 +387,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
} finally {
execute(success ? "COMMIT" : "ROLLBACK", null, null);
}
+ } catch (SQLiteDatabaseCorruptException ex) {
+ throw ex;
} catch (RuntimeException ex) {
throw new SQLiteException("Failed to change locale for db '" + mConfiguration.label
+ "' to '" + newLocale + "'.", ex);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 73bb426..dd15d38 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -40,6 +40,7 @@ import android.util.Log;
import android.text.TextUtils;
import android.view.Surface;
import android.view.SurfaceHolder;
+import android.os.SystemProperties;
import java.io.IOException;
import java.lang.ref.WeakReference;
@@ -153,6 +154,10 @@ public class Camera {
private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200;
private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400;
private static final int CAMERA_MSG_FOCUS_MOVE = 0x800;
+ /* ### QC ADD-ONS: START */
+ private static final int CAMERA_MSG_STATS_DATA = 0x1000;
+ private static final int CAMERA_MSG_META_DATA = 0x2000;
+ /* ### QC ADD-ONS: END */
private long mNativeContext; // accessed by native methods
private EventHandler mEventHandler;
@@ -180,6 +185,10 @@ public class Camera {
private static final int ENOSYS = -38;
private static final int EUSERS = -87;
private static final int EOPNOTSUPP = -95;
+ /* ### QC ADD-ONS: START */
+ private CameraDataCallback mCameraDataCallback;
+ private CameraMetaDataCallback mCameraMetaDataCallback;
+ /* ### QC ADD-ONS: END */
/**
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -266,6 +275,17 @@ public class Camera {
*/
public static final int CAMERA_FACING_FRONT = 1;
+ /* ### QC ADD-ONS: START TBD*/
+ /** @hide
+ * camera is in ZSL mode.
+ */
+ public static final int CAMERA_SUPPORT_MODE_ZSL = 2;
+
+ /** @hide
+ * camera is in non-ZSL mode.
+ */
+ public static final int CAMERA_SUPPORT_MODE_NONZSL = 3;
+ /* ### QC ADD-ONS: END */
/**
* The direction that the camera faces. It should be
* CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
@@ -450,6 +470,10 @@ public class Camera {
mPostviewCallback = null;
mUsingPreviewAllocation = false;
mZoomListener = null;
+ /* ### QC ADD-ONS: START */
+ mCameraDataCallback = null;
+ mCameraMetaDataCallback = null;
+ /* ### QC ADD-ONS: END */
Looper looper;
if ((looper = Looper.myLooper()) != null) {
@@ -460,8 +484,21 @@ public class Camera {
mEventHandler = null;
}
- return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
- ActivityThread.currentOpPackageName());
+ String packageName = ActivityThread.currentOpPackageName();
+
+ //Force HAL1 if the package name falls in this bucket
+ String packageList = SystemProperties.get("camera.hal1.packagelist", "");
+ if (packageList.length() > 0) {
+ TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
+ splitter.setString(packageList);
+ for (String str : splitter) {
+ if (packageName.equals(str)) {
+ halVersion = CAMERA_HAL_API_VERSION_1_0;
+ break;
+ }
+ }
+ }
+ return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
}
private int cameraInitNormal(int cameraId) {
@@ -766,6 +803,7 @@ public class Camera {
* @see android.media.MediaActionSound
*/
public final void setPreviewCallback(PreviewCallback cb) {
+ android.util.SeempLog.record(66);
mPreviewCallback = cb;
mOneShot = false;
mWithBuffer = false;
@@ -792,6 +830,7 @@ public class Camera {
* @see android.media.MediaActionSound
*/
public final void setOneShotPreviewCallback(PreviewCallback cb) {
+ android.util.SeempLog.record(68);
mPreviewCallback = cb;
mOneShot = true;
mWithBuffer = false;
@@ -830,6 +869,7 @@ public class Camera {
* @see android.media.MediaActionSound
*/
public final void setPreviewCallbackWithBuffer(PreviewCallback cb) {
+ android.util.SeempLog.record(67);
mPreviewCallback = cb;
mOneShot = false;
mWithBuffer = true;
@@ -1152,7 +1192,23 @@ public class Camera {
mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera);
}
return;
+ /* ### QC ADD-ONS: START */
+ case CAMERA_MSG_STATS_DATA:
+ int statsdata[] = new int[257];
+ for(int i =0; i<257; i++ ) {
+ statsdata[i] = byteToInt( (byte[])msg.obj, i*4);
+ }
+ if (mCameraDataCallback != null) {
+ mCameraDataCallback.onCameraData(statsdata, mCamera);
+ }
+ return;
+ case CAMERA_MSG_META_DATA:
+ if (mCameraMetaDataCallback != null) {
+ mCameraMetaDataCallback.onCameraMetaData((byte[])msg.obj, mCamera);
+ }
+ return;
+ /* ### QC ADD-ONS: END */
default:
Log.e(TAG, "Unknown message type " + msg.what);
return;
@@ -1376,6 +1432,7 @@ public class Camera {
*/
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
PictureCallback jpeg) {
+ android.util.SeempLog.record(65);
takePicture(shutter, raw, null, jpeg);
}
private native final void native_takePicture(int msgType);
@@ -1411,6 +1468,7 @@ public class Camera {
*/
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
PictureCallback postview, PictureCallback jpeg) {
+ android.util.SeempLog.record(65);
mShutterCallback = shutter;
mRawImageCallback = raw;
mPostviewCallback = postview;
@@ -1579,6 +1637,20 @@ public class Camera {
private native final boolean _enableShutterSound(boolean enabled);
/**
+ * Send a vendor-specific camera command
+ *
+ * @hide
+ */
+ public final void sendVendorCommand(int cmd, int arg1, int arg2) {
+ if (cmd < 1000) {
+ throw new IllegalArgumentException("Command numbers must be at least 1000");
+ }
+ _sendVendorCommand(cmd, arg1, arg2);
+ }
+
+ private native final void _sendVendorCommand(int cmd, int arg1, int arg2);
+
+ /**
* Callback interface for zoom changes during a smooth zoom operation.
*
* @see #setZoomChangeListener(OnZoomChangeListener)
@@ -1800,6 +1872,23 @@ public class Camera {
* as a set. Either they are all valid, or none of them are.
*/
public Point mouth = null;
+
+ /**
+ * {@hide}
+ */
+ public int smileDegree = 0;
+ /**
+ * {@hide}
+ */
+ public int smileScore = 0;
+ /**
+ * {@hide}
+ */
+ public int blinkDetected = 0;
+ /**
+ * {@hide}
+ */
+ public int faceRecognised = 0;
}
/**
@@ -1892,6 +1981,27 @@ public class Camera {
return p;
}
+ /** @hide
+ * Returns the current cct value of white balance.
+ *
+ * If it's in AWB mode, cct is determined by stats/awb module.
+ *
+ * If it's in Manual WB mode, it actually returns cct value
+ * set by user via {@link #setParameters(Camera.Parameters)}.
+ */
+ public int getWBCurrentCCT() {
+ Parameters p = new Parameters();
+ String s = native_getParameters();
+ p.unflatten(s);
+
+ int cct = 0;
+ if (p.getWBCurrentCCT() != null) {
+ cct = Integer.parseInt(p.getWBCurrentCCT());
+ }
+
+ return cct;
+ }
+
/**
* Returns an empty {@link Parameters} for testing purpose.
*
@@ -1904,6 +2014,166 @@ public class Camera {
return camera.new Parameters();
}
+ /* ### QC ADD-ONS: START */
+ private static int byteToInt(byte[] b, int offset) {
+ int value = 0;
+ for (int i = 0; i < 4; i++) {
+ int shift = (4 - 1 - i) * 8;
+ value += (b[(3-i) + offset] & 0x000000FF) << shift;
+ }
+ return value;
+ }
+ /** @hide
+ * Handles the callback for when Camera Data is available.
+ * data is read from the camera.
+ */
+ public interface CameraDataCallback {
+ /**
+ * Callback for when camera data is available.
+ *
+ * @param data a int array of the camera data
+ * @param camera the Camera service object
+ */
+ void onCameraData(int[] data, Camera camera);
+ };
+
+ /** @hide
+ * Set camera histogram mode and registers a callback function to run.
+ * Only valid after startPreview() has been called.
+ *
+ * @param cb the callback to run
+ */
+ public final void setHistogramMode(CameraDataCallback cb)
+ {
+ mCameraDataCallback = cb;
+ native_setHistogramMode(cb!=null);
+ }
+ private native final void native_setHistogramMode(boolean mode);
+
+ /** @hide
+ * Set camera histogram command to send data.
+ *
+ */
+ public final void sendHistogramData()
+ {
+ native_sendHistogramData();
+ }
+ private native final void native_sendHistogramData();
+
+ /** @hide
+ * Handles the callback for when Camera Meta Data is available.
+ * Meta data is read from the camera.
+ */
+ public interface CameraMetaDataCallback {
+ /**
+ * Callback for when camera meta data is available.
+ *
+ * @param data a byte array of the camera meta data
+ * @param camera the Camera service object
+ */
+ void onCameraMetaData(byte[] data, Camera camera);
+ };
+
+ /** @hide
+ * Set camera meta data and registers a callback function to run.
+ * Only valid after startPreview() has been called.
+ *
+ * @param cb the callback to run
+ */
+ public final void setMetadataCb(CameraMetaDataCallback cb)
+ {
+ mCameraMetaDataCallback = cb;
+ native_setMetadataCb(cb!=null);
+ }
+ private native final void native_setMetadataCb(boolean mode);
+
+ /** @hide
+ * Set camera face detection command to send meta data.
+ */
+ public final void sendMetaData()
+ {
+ native_sendMetaData();
+ }
+ private native final void native_sendMetaData();
+
+ /** @hide
+ * Configure longshot mode. Available only in ZSL.
+ *
+ * @param enable enable/disable this mode
+ */
+ public final void setLongshot(boolean enable)
+ {
+ native_setLongshot(enable);
+ }
+ private native final void native_setLongshot(boolean enable);
+
+ /** @hide
+ * Stop longshot. Available only in ZSL.
+ */
+ public final void stopLongshot()
+ {
+ native_stopLongshot();
+ }
+ private native final void native_stopLongshot();
+
+ /** @hide
+ * Handles the Touch Co-ordinate.
+ */
+ public class Coordinate {
+ /**
+ * Sets the x,y co-ordinates for a touch event
+ *
+ * @param x the x co-ordinate (pixels)
+ * @param y the y co-ordinate (pixels)
+ */
+ public Coordinate(int x, int y) {
+ xCoordinate = x;
+ yCoordinate = y;
+ }
+ /**
+ * Compares {@code obj} to this co-ordinate.
+ *
+ * @param obj the object to compare this co-ordinate with.
+ * @return {@code true} if the xCoordinate and yCoordinate of {@code obj} is the
+ * same as those of this coordinate. {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Coordinate)) {
+ return false;
+ }
+ Coordinate c = (Coordinate) obj;
+ return xCoordinate == c.xCoordinate && yCoordinate == c.yCoordinate;
+ }
+
+ /** x co-ordinate for the touch event*/
+ public int xCoordinate;
+
+ /** y co-ordinate for the touch event */
+ public int yCoordinate;
+ };
+
+ /** @hide
+ * Returns the current focus position.
+ *
+ * If it's in AF mode, it's the lens position after af is done.
+ *
+ * If it's in Manual Focus mode, it actually returns the value
+ * set by user via {@link #setParameters(Camera.Parameters)}.
+ */
+ public int getCurrentFocusPosition() {
+ Parameters p = new Parameters();
+ String s = native_getParameters();
+ p.unflatten(s);
+
+ int focus_pos = -1;
+ if (p.getCurrentFocusPosition() != null) {
+ focus_pos = Integer.parseInt(p.getCurrentFocusPosition());
+ }
+ return focus_pos;
+ }
+
+ /* ### QC ADD-ONS: END */
/**
* Returns a copied {@link Parameters}; for shim use only.
*
@@ -2151,6 +2421,10 @@ public class Camera {
public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
public static final String WHITE_BALANCE_TWILIGHT = "twilight";
public static final String WHITE_BALANCE_SHADE = "shade";
+ /** @hide
+ * wb manual cct mode.
+ */
+ public static final String WHITE_BALANCE_MANUAL_CCT = "manual-cct";
// Values for color effect settings.
public static final String EFFECT_NONE = "none";
@@ -2198,6 +2472,11 @@ public class Camera {
*/
public static final String FLASH_MODE_TORCH = "torch";
+ /** @hide
+ * Scene mode is off.
+ */
+ public static final String SCENE_MODE_ASD = "asd";
+
/**
* Scene mode is off.
*/
@@ -2274,6 +2553,14 @@ public class Camera {
* Capture the naturally warm color of scenes lit by candles.
*/
public static final String SCENE_MODE_CANDLELIGHT = "candlelight";
+ /** @hide
+ * SCENE_MODE_BACKLIGHT
+ **/
+ public static final String SCENE_MODE_BACKLIGHT = "backlight";
+ /** @hide
+ * SCENE_MODE_FLOWERS
+ **/
+ public static final String SCENE_MODE_FLOWERS = "flowers";
/**
* Applications are looking for a barcode. Camera driver will be
@@ -2316,6 +2603,13 @@ public class Camera {
*/
public static final String FOCUS_MODE_FIXED = "fixed";
+ /** @hide
+ * Normal focus mode. Applications should call
+ * {@link #autoFocus(AutoFocusCallback)} to start the focus in this
+ * mode.
+ */
+ public static final String FOCUS_MODE_NORMAL = "normal";
+
/**
* Extended depth of field (EDOF). Focusing is done digitally and
* continuously. Applications should not call {@link
@@ -2368,6 +2662,11 @@ public class Camera {
*/
public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture";
+ /** @hide
+ * manual focus mode
+ */
+ public static final String FOCUS_MODE_MANUAL_POSITION = "manual";
+
// Indices for focus distance array.
/**
* The array index of near focus distance for use with
@@ -2404,11 +2703,15 @@ public class Camera {
// Formats for setPreviewFormat and setPictureFormat.
private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
+ private static final String PIXEL_FORMAT_YUV420SP_ADRENO = "yuv420sp-adreno";
private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv";
private static final String PIXEL_FORMAT_YUV420P = "yuv420p";
private static final String PIXEL_FORMAT_RGB565 = "rgb565";
private static final String PIXEL_FORMAT_JPEG = "jpeg";
private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb";
+ private static final String PIXEL_FORMAT_RAW = "raw";
+ private static final String PIXEL_FORMAT_YV12 = "yv12";
+ private static final String PIXEL_FORMAT_NV12 = "nv12";
/**
* Order matters: Keys that are {@link #set(String, String) set} later
@@ -3196,8 +3499,11 @@ public class Camera {
* parameters.
*/
public void removeGpsData() {
+ remove(KEY_QC_GPS_LATITUDE_REF);
remove(KEY_GPS_LATITUDE);
+ remove(KEY_QC_GPS_LONGITUDE_REF);
remove(KEY_GPS_LONGITUDE);
+ remove(KEY_QC_GPS_ALTITUDE_REF);
remove(KEY_GPS_ALTITUDE);
remove(KEY_GPS_TIMESTAMP);
remove(KEY_GPS_PROCESSING_METHOD);
@@ -4088,6 +4394,7 @@ public class Camera {
splitter.setString(str);
int index = 0;
for (String s : splitter) {
+ s = s.replaceAll("\\s","");
output[index++] = Integer.parseInt(s);
}
}
@@ -4158,7 +4465,7 @@ public class Camera {
// Example string: "(10000,26623),(10000,30000)". Return null if the
// passing string is null or the size is 0.
private ArrayList<int[]> splitRange(String str) {
- if (str == null || str.charAt(0) != '('
+ if (str == null || str.isEmpty() || str.charAt(0) != '('
|| str.charAt(str.length() - 1) != ')') {
Log.e(TAG, "Invalid range list string=" + str);
return null;
@@ -4183,7 +4490,7 @@ public class Camera {
// Example string: "(-10,-10,0,0,300),(0,0,10,10,700)". Return null if
// the passing string is null or the size is 0 or (0,0,0,0,0).
private ArrayList<Area> splitArea(String str) {
- if (str == null || str.charAt(0) != '('
+ if (str == null || str.isEmpty() || str.charAt(0) != '('
|| str.charAt(str.length() - 1) != ')') {
Log.e(TAG, "Invalid area string=" + str);
return null;
@@ -4220,5 +4527,1231 @@ public class Camera {
if (s1 != null && s1.equals(s2)) return true;
return false;
}
+ /* ### QC ADD-ONS: START */
+
+ /* ### QC ADDED PARAMETER KEYS*/
+ private static final String KEY_QC_HFR_SIZE = "hfr-size";
+ private static final String KEY_QC_PREVIEW_FRAME_RATE_MODE = "preview-frame-rate-mode";
+ private static final String KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE = "frame-rate-auto";
+ private static final String KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE = "frame-rate-fixed";
+ private static final String KEY_QC_GPS_LATITUDE_REF = "gps-latitude-ref";
+ private static final String KEY_QC_GPS_LONGITUDE_REF = "gps-longitude-ref";
+ private static final String KEY_QC_GPS_ALTITUDE_REF = "gps-altitude-ref";
+ private static final String KEY_QC_GPS_STATUS = "gps-status";
+ private static final String KEY_QC_EXIF_DATETIME = "exif-datetime";
+ private static final String KEY_QC_TOUCH_AF_AEC = "touch-af-aec";
+ private static final String KEY_QC_TOUCH_INDEX_AEC = "touch-index-aec";
+ private static final String KEY_QC_TOUCH_INDEX_AF = "touch-index-af";
+ private static final String KEY_QC_MANUAL_FOCUS_POSITION = "manual-focus-position";
+ private static final String KEY_QC_MANUAL_FOCUS_POS_TYPE = "manual-focus-pos-type";
+ private static final String KEY_QC_SCENE_DETECT = "scene-detect";
+ private static final String KEY_QC_ISO_MODE = "iso";
+ private static final String KEY_QC_EXPOSURE_TIME = "exposure-time";
+ private static final String KEY_QC_MIN_EXPOSURE_TIME = "min-exposure-time";
+ private static final String KEY_QC_MAX_EXPOSURE_TIME = "max-exposure-time";
+ private static final String KEY_QC_LENSSHADE = "lensshade";
+ private static final String KEY_QC_HISTOGRAM = "histogram";
+ private static final String KEY_QC_SKIN_TONE_ENHANCEMENT = "skinToneEnhancement";
+ private static final String KEY_QC_AUTO_EXPOSURE = "auto-exposure";
+ private static final String KEY_QC_SHARPNESS = "sharpness";
+ private static final String KEY_QC_MAX_SHARPNESS = "max-sharpness";
+ private static final String KEY_QC_CONTRAST = "contrast";
+ private static final String KEY_QC_MAX_CONTRAST = "max-contrast";
+ private static final String KEY_QC_SATURATION = "saturation";
+ private static final String KEY_QC_MAX_SATURATION = "max-saturation";
+ private static final String KEY_QC_DENOISE = "denoise";
+ private static final String KEY_QC_CONTINUOUS_AF = "continuous-af";
+ private static final String KEY_QC_SELECTABLE_ZONE_AF = "selectable-zone-af";
+ private static final String KEY_QC_FACE_DETECTION = "face-detection";
+ private static final String KEY_QC_MEMORY_COLOR_ENHANCEMENT = "mce";
+ private static final String KEY_QC_REDEYE_REDUCTION = "redeye-reduction";
+ private static final String KEY_QC_ZSL = "zsl";
+ private static final String KEY_QC_CAMERA_MODE = "camera-mode";
+ private static final String KEY_QC_VIDEO_HIGH_FRAME_RATE = "video-hfr";
+ private static final String KEY_QC_VIDEO_HDR = "video-hdr";
+ private static final String KEY_QC_POWER_MODE = "power-mode";
+ private static final String KEY_QC_POWER_MODE_SUPPORTED = "power-mode-supported";
+ private static final String KEY_QC_WB_MANUAL_CCT = "wb-manual-cct";
+ private static final String KEY_QC_MIN_WB_CCT = "min-wb-cct";
+ private static final String KEY_QC_MAX_WB_CCT = "max-wb-cct";
+ private static final String KEY_QC_AUTO_HDR_ENABLE = "auto-hdr-enable";
+ private static final String KEY_QC_VIDEO_ROTATION = "video-rotation";
+
+ /** @hide
+ * KEY_QC_AE_BRACKET_HDR
+ **/
+ public static final String KEY_QC_AE_BRACKET_HDR = "ae-bracket-hdr";
+
+ /* ### QC ADDED PARAMETER VALUES*/
+
+ // Values for touch af/aec settings.
+ /** @hide
+ * TOUCH_AF_AEC_OFF
+ **/
+ public static final String TOUCH_AF_AEC_OFF = "touch-off";
+ /** @hide
+ * TOUCH_AF_AEC_ON
+ **/
+ public static final String TOUCH_AF_AEC_ON = "touch-on";
+
+ // Values for auto exposure settings.
+ /** @hide
+ * Auto exposure frame-avg
+ **/
+ public static final String AUTO_EXPOSURE_FRAME_AVG = "frame-average";
+ /** @hide
+ * Auto exposure center weighted
+ **/
+ public static final String AUTO_EXPOSURE_CENTER_WEIGHTED = "center-weighted";
+ /** @hide
+ * Auto exposure spot metering
+ **/
+ public static final String AUTO_EXPOSURE_SPOT_METERING = "spot-metering";
+
+ //Values for ISO settings
+ /** @hide
+ * ISO_AUTO
+ **/
+ public static final String ISO_AUTO = "auto";
+ /** @hide
+ * ISO_HJR
+ **/
+ public static final String ISO_HJR = "ISO_HJR";
+ /** @hide
+ * ISO_100
+ **/
+ public static final String ISO_100 = "ISO100";
+ /** @hide
+ * ISO_200
+ **/
+ public static final String ISO_200 = "ISO200";
+ /** @hide
+ * ISO_400
+ **/
+ public static final String ISO_400 = "ISO400";
+ /** @hide
+ * ISO_800
+ **/
+ public static final String ISO_800 = "ISO800";
+ /** @hide
+ * ISO_1600
+ **/
+ public static final String ISO_1600 = "ISO1600";
+
+ /** @hide
+ * ISO_3200
+ **/
+ public static final String ISO_3200 = "ISO3200";
+
+ //Values for Lens Shading
+ /** @hide
+ * LENSSHADE_ENABLE
+ **/
+ public static final String LENSSHADE_ENABLE = "enable";
+ /** @hide
+ * LENSSHADE_DISABLE
+ **/
+ public static final String LENSSHADE_DISABLE= "disable";
+
+ //Values for Histogram
+ /** @hide
+ * Histogram enable
+ **/
+ public static final String HISTOGRAM_ENABLE = "enable";
+ /** @hide
+ * Histogram disable
+ **/
+ public static final String HISTOGRAM_DISABLE= "disable";
+
+ //Values for Skin Tone Enhancement
+ /** @hide
+ * SKIN_TONE_ENHANCEMENT_ENABLE
+ **/
+ public static final String SKIN_TONE_ENHANCEMENT_ENABLE = "enable";
+ /** @hide
+ * SKIN_TONE_ENHANCEMENT_DISABLE
+ **/
+ public static final String SKIN_TONE_ENHANCEMENT_DISABLE= "disable";
+
+ // Values for MCE settings.
+ /** @hide
+ * MCE_ENaBLE
+ **/
+ public static final String MCE_ENABLE = "enable";
+ /** @hide
+ * MCE_DISABLE
+ **/
+ public static final String MCE_DISABLE = "disable";
+
+ // Values for ZSL settings.
+ /** @hide
+ * ZSL_ON
+ **/
+ public static final String ZSL_ON = "on";
+ /** @hide
+ * ZSL_OFF
+ **/
+ public static final String ZSL_OFF = "off";
+
+ // Values for HDR Bracketing settings.
+
+ /** @hide
+ * AEC bracketing off
+ **/
+ public static final String AE_BRACKET_HDR_OFF = "Off";
+ /** @hide
+ * AEC bracketing hdr
+ **/
+ public static final String AE_BRACKET_HDR = "HDR";
+ /** @hide
+ * AEC bracketing aec-bracket
+ **/
+ public static final String AE_BRACKET = "AE-Bracket";
+
+ // Values for Power mode.
+ /** @hide
+ * LOW_POWER
+ **/
+ public static final String LOW_POWER = "Low_Power";
+ /** @hide
+ * NORMAL_POWER
+ **/
+ public static final String NORMAL_POWER = "Normal_Power";
+
+ // Values for HFR settings.
+ /** @hide
+ * VIDEO_HFR_OFF
+ **/
+ public static final String VIDEO_HFR_OFF = "off";
+ /** @hide
+ * VIDEO_HFR_2X
+ **/
+ public static final String VIDEO_HFR_2X = "60";
+ /** @hide
+ * VIDEO_HFR_3X
+ **/
+ public static final String VIDEO_HFR_3X = "90";
+ /** @hide
+ * VIDEO_HFR_4X
+ **/
+ public static final String VIDEO_HFR_4X = "120";
+
+ // Values for auto scene detection settings.
+ /** @hide
+ * SCENE_DETECT_OFF
+ **/
+ public static final String SCENE_DETECT_OFF = "off";
+ /** @hide
+ * SCENE_DETECT_ON
+ **/
+ public static final String SCENE_DETECT_ON = "on";
+
+ //Values for Continuous AF
+
+ /** @hide
+ * CAF off
+ **/
+ public static final String CONTINUOUS_AF_OFF = "caf-off";
+ /** @hide
+ * CAF on
+ **/
+ public static final String CONTINUOUS_AF_ON = "caf-on";
+ /** @hide
+ * Denoise off
+ **/
+ public static final String DENOISE_OFF = "denoise-off";
+ /** @hide
+ * Denoise on
+ **/
+ public static final String DENOISE_ON = "denoise-on";
+
+ // Values for Redeye Reduction settings.
+ /** @hide
+ * REDEYE_REDUCTION_ENABLE
+ **/
+ public static final String REDEYE_REDUCTION_ENABLE = "enable";
+ /** @hide
+ * REDEYE_REDUCTION_DISABLE
+ **/
+ public static final String REDEYE_REDUCTION_DISABLE = "disable";
+
+ // Values for selectable zone af settings.
+ /** @hide
+ * SELECTABLE_ZONE_AF_AUTO
+ **/
+ public static final String SELECTABLE_ZONE_AF_AUTO = "auto";
+ /** @hide
+ * SELECTABLE_ZONE_AF_SPOTMETERING
+ **/
+ public static final String SELECTABLE_ZONE_AF_SPOTMETERING = "spot-metering";
+ /** @hide
+ * SELECTABLE_ZONE_AF_CENTER_WEIGHTED
+ **/
+ public static final String SELECTABLE_ZONE_AF_CENTER_WEIGHTED = "center-weighted";
+ /** @hide
+ * SELECTABLE_ZONE_AF_FRAME_AVERAGE
+ **/
+ public static final String SELECTABLE_ZONE_AF_FRAME_AVERAGE = "frame-average";
+
+ // Values for Face Detection settings.
+ /** @hide
+ * Face Detection off
+ **/
+ public static final String FACE_DETECTION_OFF = "off";
+ /** @hide
+ * Face Detction on
+ **/
+ public static final String FACE_DETECTION_ON = "on";
+
+ // Values for video rotation settings.
+
+ /** @hide
+ * VIDEO_ROTATION_0
+ **/
+ public static final String VIDEO_ROTATION_0 = "0";
+ /** @hide
+ * VIDEO_ROTATION_90
+ **/
+ public static final String VIDEO_ROTATION_90 = "90";
+ /** @hide
+ * VIDEO_ROTATION_180
+ **/
+ public static final String VIDEO_ROTATION_180 = "180";
+ /** @hide
+ * VIDEO_ROTATION_270
+ **/
+ public static final String VIDEO_ROTATION_270 = "270";
+
+ /* ### QC ADDED PARAMETER APIS*/
+ /** @hide
+ * Gets the supported preview sizes in high frame rate recording mode.
+ *
+ * @return a list of Size object. This method will always return a list
+ * with at least one element.
+ */
+ public List<Size> getSupportedHfrSizes() {
+ String str = get(KEY_QC_HFR_SIZE + SUPPORTED_VALUES_SUFFIX);
+ return splitSize(str);
+ }
+
+ /** @hide
+ * Gets the supported Touch AF/AEC setting.
+ *
+ * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC
+ * setting is not supported.
+ *
+ */
+ public List<String> getSupportedTouchAfAec() {
+ String str = get(KEY_QC_TOUCH_AF_AEC + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /**
+ * Gets the supported Touch AF/AEC setting.
+ *
+ * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC
+ * setting is not supported.
+ *
+ */
+
+ /** @hide
+ * Gets the supported frame rate modes.
+ *
+ * @return a List of FRAME_RATE_XXX_MODE string constant. null if this
+ * setting is not supported.
+ */
+ public List<String> getSupportedPreviewFrameRateModes() {
+ String str = get(KEY_QC_PREVIEW_FRAME_RATE_MODE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported auto scene detection modes.
+ *
+ * @return a List of SCENE_DETECT_XXX string constant. null if scene detection
+ * setting is not supported.
+ *
+ */
+ public List<String> getSupportedSceneDetectModes() {
+ String str = get(KEY_QC_SCENE_DETECT + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported ISO values.
+ *
+ * @return a List of FLASH_MODE_XXX string constants. null if flash mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedIsoValues() {
+ String str = get(KEY_QC_ISO_MODE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported Lensshade modes.
+ *
+ * @return a List of LENS_MODE_XXX string constants. null if lens mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedLensShadeModes() {
+ String str = get(KEY_QC_LENSSHADE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported Histogram modes.
+ *
+ * @return a List of HISTOGRAM_XXX string constants. null if histogram mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedHistogramModes() {
+ String str = get(KEY_QC_HISTOGRAM + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported Skin Tone Enhancement modes.
+ *
+ * @return a List of SKIN_TONE_ENHANCEMENT_XXX string constants. null if skin tone enhancement
+ * setting is not supported.
+ */
+ public List<String> getSupportedSkinToneEnhancementModes() {
+ String str = get(KEY_QC_SKIN_TONE_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported auto exposure setting.
+ *
+ * @return a List of AUTO_EXPOSURE_XXX string constants. null if auto exposure
+ * setting is not supported.
+ */
+ public List<String> getSupportedAutoexposure() {
+ String str = get(KEY_QC_AUTO_EXPOSURE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported MCE modes.
+ *
+ * @return a List of MCE_ENABLE/DISABLE string constants. null if MCE mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedMemColorEnhanceModes() {
+ String str = get(KEY_QC_MEMORY_COLOR_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported ZSL modes.
+ *
+ * @return a List of ZSL_OFF/OFF string constants. null if ZSL mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedZSLModes() {
+ String str = get(KEY_QC_ZSL + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported Video HDR modes.
+ *
+ * @return a List of Video HDR_OFF/OFF string constants. null if
+ * Video HDR mode setting is not supported.
+ */
+ public List<String> getSupportedVideoHDRModes() {
+ String str = get(KEY_QC_VIDEO_HDR + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported HFR modes.
+ *
+ * @return a List of VIDEO_HFR_XXX string constants. null if hfr mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedVideoHighFrameRateModes() {
+ String str = get(KEY_QC_VIDEO_HIGH_FRAME_RATE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported Continuous AF modes.
+ *
+ * @return a List of CONTINUOUS_AF_XXX string constant. null if continuous AF
+ * setting is not supported.
+ *
+ */
+ public List<String> getSupportedContinuousAfModes() {
+ String str = get(KEY_QC_CONTINUOUS_AF + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported DENOISE modes.
+ *
+ * @return a List of DENOISE_XXX string constant. null if DENOISE
+ * setting is not supported.
+ *
+ */
+ public List<String> getSupportedDenoiseModes() {
+ String str = get(KEY_QC_DENOISE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported selectable zone af setting.
+ *
+ * @return a List of SELECTABLE_ZONE_AF_XXX string constants. null if selectable zone af
+ * setting is not supported.
+ */
+ public List<String> getSupportedSelectableZoneAf() {
+ String str = get(KEY_QC_SELECTABLE_ZONE_AF + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported face detection modes.
+ *
+ * @return a List of FACE_DETECTION_XXX string constant. null if face detection
+ * setting is not supported.
+ *
+ */
+ public List<String> getSupportedFaceDetectionModes() {
+ String str = get(KEY_QC_FACE_DETECTION + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Gets the supported redeye reduction modes.
+ *
+ * @return a List of REDEYE_REDUCTION_XXX string constant. null if redeye reduction
+ * setting is not supported.
+ *
+ */
+ public List<String> getSupportedRedeyeReductionModes() {
+ String str = get(KEY_QC_REDEYE_REDUCTION + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /** @hide
+ * Sets GPS altitude reference. This will be stored in JPEG EXIF header.
+ * @param altRef reference GPS altitude in meters.
+ */
+ public void setGpsAltitudeRef(double altRef) {
+ set(KEY_QC_GPS_ALTITUDE_REF, Double.toString(altRef));
+ }
+
+ /** @hide
+ * Sets GPS Status. This will be stored in JPEG EXIF header.
+ *
+ * @param status GPS status (UTC in seconds since January 1,
+ * 1970).
+ */
+ public void setGpsStatus(double status) {
+ set(KEY_QC_GPS_STATUS, Double.toString(status));
+ }
+
+ /** @hide
+ * Sets the touch co-ordinate for Touch AEC.
+ *
+ * @param x the x co-ordinate of the touch event
+ * @param y the y co-ordinate of the touch event
+ *
+ */
+ public void setTouchIndexAec(int x, int y) {
+ String v = Integer.toString(x) + "x" + Integer.toString(y);
+ set(KEY_QC_TOUCH_INDEX_AEC, v);
+ }
+
+ /** @hide
+ * Returns the touch co-ordinates of the touch event.
+ *
+ * @return a Index object with the x and y co-ordinated
+ * for the touch event
+ *
+ */
+ public Coordinate getTouchIndexAec() {
+ String pair = get(KEY_QC_TOUCH_INDEX_AEC);
+ return strToCoordinate(pair);
+ }
+
+ /** @hide
+ * Sets the touch co-ordinate for Touch AF.
+ *
+ * @param x the x co-ordinate of the touch event
+ * @param y the y co-ordinate of the touch event
+ *
+ */
+ public void setTouchIndexAf(int x, int y) {
+ String v = Integer.toString(x) + "x" + Integer.toString(y);
+ set(KEY_QC_TOUCH_INDEX_AF, v);
+ }
+
+ /** @hide
+ * Returns the touch co-ordinates of the touch event.
+ *
+ * @return a Index object with the x and y co-ordinated
+ * for the touch event
+ *
+ */
+ public Coordinate getTouchIndexAf() {
+ String pair = get(KEY_QC_TOUCH_INDEX_AF);
+ return strToCoordinate(pair);
+ }
+ /** @hide
+ * Set Sharpness Level
+ *
+ * @param sharpness level
+ */
+ public void setSharpness(int sharpness){
+ if((sharpness < 0) || (sharpness > getMaxSharpness()) )
+ throw new IllegalArgumentException(
+ "Invalid Sharpness " + sharpness);
+
+ set(KEY_QC_SHARPNESS, String.valueOf(sharpness));
+ }
+
+ /** @hide
+ * Set Contrast Level
+ *
+ * @param contrast level
+ */
+ public void setContrast(int contrast){
+ if((contrast < 0 ) || (contrast > getMaxContrast()))
+ throw new IllegalArgumentException(
+ "Invalid Contrast " + contrast);
+
+ set(KEY_QC_CONTRAST, String.valueOf(contrast));
+ }
+
+ /** @hide
+ * Set Saturation Level
+ *
+ * @param saturation level
+ */
+ public void setSaturation(int saturation){
+ if((saturation < 0 ) || (saturation > getMaxSaturation()))
+ throw new IllegalArgumentException(
+ "Invalid Saturation " + saturation);
+
+ set(KEY_QC_SATURATION, String.valueOf(saturation));
+ }
+
+ /** @hide
+ * @return true if full size video snapshot is supported.
+ */
+ public boolean isPowerModeSupported() {
+ String str = get(KEY_QC_POWER_MODE_SUPPORTED);
+ return TRUE.equals(str);
+ }
+
+ /** @hide
+ * Get Sharpness level
+ *
+ * @return sharpness level
+ */
+ public int getSharpness(){
+ return getInt(KEY_QC_SHARPNESS);
+ }
+
+ /** @hide
+ * Get Max Sharpness Level
+ *
+ * @return max sharpness level
+ */
+ public int getMaxSharpness(){
+ return getInt(KEY_QC_MAX_SHARPNESS);
+ }
+
+ /** @hide
+ * Get Contrast level
+ *
+ * @return contrast level
+ */
+ public int getContrast(){
+ return getInt(KEY_QC_CONTRAST);
+ }
+
+ /** @hide
+ * Get Max Contrast Level
+ *
+ * @return max contrast level
+ */
+ public int getMaxContrast(){
+ return getInt(KEY_QC_MAX_CONTRAST);
+ }
+
+ /** @hide
+ * Get Saturation level
+ *
+ * @return saturation level
+ */
+ public int getSaturation(){
+ return getInt(KEY_QC_SATURATION);
+ }
+
+ /** @hide
+ * Get Max Saturation Level
+ *
+ * @return max contrast level
+ */
+ public int getMaxSaturation(){
+ return getInt(KEY_QC_MAX_SATURATION);
+ }
+
+ /** @hide
+ * Sets GPS latitude reference coordinate. This will be stored in JPEG EXIF
+ * header.
+ * @param latRef GPS latitude reference coordinate.
+ */
+ public void setGpsLatitudeRef(String latRef) {
+ set(KEY_QC_GPS_LATITUDE_REF, latRef);
+ }
+
+ /** @hide
+ * Sets GPS longitude reference coordinate. This will be stored in JPEG EXIF
+ * header.
+ * @param lonRef GPS longitude reference coordinate.
+ */
+ public void setGpsLongitudeRef(String lonRef) {
+ set(KEY_QC_GPS_LONGITUDE_REF, lonRef);
+ }
+
+ /** @hide
+ * Sets system timestamp. This will be stored in JPEG EXIF header.
+ *
+ * @param dateTime current timestamp (UTC in seconds since January 1,
+ * 1970).
+ */
+ public void setExifDateTime(String dateTime) {
+ set(KEY_QC_EXIF_DATETIME, dateTime);
+ }
+
+ /** @hide
+ * Gets the current Touch AF/AEC setting.
+ *
+ * @return one of TOUCH_AF_AEC_XXX string constant. null if Touch AF/AEC
+ * setting is not supported.
+ *
+ */
+ public String getTouchAfAec() {
+ return get(KEY_QC_TOUCH_AF_AEC);
+ }
+
+ /** @hide
+ * Sets the current TOUCH AF/AEC setting.
+ *
+ * @param value TOUCH_AF_AEC_XXX string constants.
+ *
+ */
+ public void setTouchAfAec(String value) {
+ set(KEY_QC_TOUCH_AF_AEC, value);
+ }
+
+ /** @hide
+ * Gets the current redeye reduction setting.
+ *
+ * @return one of REDEYE_REDUCTION_XXX string constant. null if redeye reduction
+ * setting is not supported.
+ *
+ */
+ public String getRedeyeReductionMode() {
+ return get(KEY_QC_REDEYE_REDUCTION);
+ }
+
+ /** @hide
+ * Sets the redeye reduction. Other parameters may be changed after changing
+ * redeye reduction. After setting redeye reduction,
+ * applications should call getParameters to know if some parameters are
+ * changed.
+ *
+ * @param value REDEYE_REDUCTION_XXX string constants.
+ *
+ */
+ public void setRedeyeReductionMode(String value) {
+ set(KEY_QC_REDEYE_REDUCTION, value);
+ }
+
+ /** @hide
+ * Gets the frame rate mode setting.
+ *
+ * @return one of FRAME_RATE_XXX_MODE string constant. null if this
+ * setting is not supported.
+ */
+ public String getPreviewFrameRateMode() {
+ return get(KEY_QC_PREVIEW_FRAME_RATE_MODE);
+ }
+
+ /** @hide
+ * Sets the frame rate mode.
+ *
+ * @param value FRAME_RATE_XXX_MODE string constants.
+ */
+ public void setPreviewFrameRateMode(String value) {
+ set(KEY_QC_PREVIEW_FRAME_RATE_MODE, value);
+ }
+
+ /** @hide
+ * Gets the current auto scene detection setting.
+ *
+ * @return one of SCENE_DETECT_XXX string constant. null if auto scene detection
+ * setting is not supported.
+ *
+ */
+ public String getSceneDetectMode() {
+ return get(KEY_QC_SCENE_DETECT);
+ }
+
+ /** @hide
+ * Sets the auto scene detect. Other parameters may be changed after changing
+ * scene detect. After setting auto scene detection,
+ * applications should call getParameters to know if some parameters are
+ * changed.
+ *
+ * @param value SCENE_DETECT_XXX string constants.
+ *
+ */
+ public void setSceneDetectMode(String value) {
+ set(KEY_QC_SCENE_DETECT, value);
+ }
+
+ /** @hide
+ * Gets the current hdr bracketing mode setting.
+ *
+ * @return current hdr bracketing mode.
+ * @see #KEY_AE_BRACKET_OFF
+ * @see #KEY_AE_BRACKET_HDR
+ * @see #KEY_AE_BRACKET_BRACKATING
+ */
+ public String getAEBracket() {
+ return get(KEY_QC_AE_BRACKET_HDR);
+ }
+
+ /** @hide
+ * Sets the Power mode.
+ *
+ * @param value Power mode.
+ * @see #getPowerMode()
+ */
+ public void setPowerMode(String value) {
+ set(KEY_QC_POWER_MODE, value);
+ }
+
+ /** @hide
+ * Gets the current power mode setting.
+ *
+ * @return current power mode. null if power mode setting is not
+ * supported.
+ * @see #POWER_MODE_LOW
+ * @see #POWER_MODE_NORMAL
+ */
+ public String getPowerMode() {
+ return get(KEY_QC_POWER_MODE);
+ }
+
+ /** @hide
+ * Set HDR-Bracketing Level
+ *
+ * @param value HDR-Bracketing
+ */
+ public void setAEBracket(String value){
+ set(KEY_QC_AE_BRACKET_HDR, value);
+ }
+
+ /** @hide
+ * Gets the current ISO setting.
+ *
+ * @return one of ISO_XXX string constant. null if ISO
+ * setting is not supported.
+ */
+ public String getISOValue() {
+ return get(KEY_QC_ISO_MODE);
+ }
+
+ /** @hide
+ * Sets the ISO.
+ *
+ * @param iso ISO_XXX string constant.
+ */
+ public void setISOValue(String iso) {
+ set(KEY_QC_ISO_MODE, iso);
+ }
+
+ /** @hide
+ * Sets the exposure time.
+ *
+ * @param value exposure time.
+ */
+ public void setExposureTime(int value) {
+ set(KEY_QC_EXPOSURE_TIME, Integer.toString(value));
+ }
+
+ /** @hide
+ * Gets the current exposure time.
+ *
+ * @return exposure time.
+ */
+ public String getExposureTime() {
+ return get(KEY_QC_EXPOSURE_TIME);
+ }
+
+ /** @hide
+ * Gets the min supported exposure time.
+ *
+ * @return min supported exposure time.
+ */
+ public String getMinExposureTime() {
+ return get(KEY_QC_MIN_EXPOSURE_TIME);
+ }
+
+ /** @hide
+ * Gets the max supported exposure time.
+ *
+ * @return max supported exposure time.
+ */
+ public String getMaxExposureTime() {
+ return get(KEY_QC_MAX_EXPOSURE_TIME);
+ }
+
+ /** @hide
+ * Gets the current LensShade Mode.
+ *
+ * @return LensShade Mode
+ */
+ public String getLensShade() {
+ return get(KEY_QC_LENSSHADE);
+ }
+
+ /** @hide
+ * Sets the current LensShade Mode.
+ *
+ * @return LensShade Mode
+ */
+ public void setLensShade(String lensshade) {
+ set(KEY_QC_LENSSHADE, lensshade);
+ }
+
+ /** @hide
+ * Gets the current auto exposure setting.
+ *
+ * @return one of AUTO_EXPOSURE_XXX string constant. null if auto exposure
+ * setting is not supported.
+ */
+ public String getAutoExposure() {
+ return get(KEY_QC_AUTO_EXPOSURE);
+ }
+
+ /** @hide
+ * Sets the current auto exposure setting.
+ *
+ * @param value AUTO_EXPOSURE_XXX string constants.
+ */
+ public void setAutoExposure(String value) {
+ set(KEY_QC_AUTO_EXPOSURE, value);
+ }
+
+ /** @hide
+ * Gets the current MCE Mode.
+ *
+ * @return MCE value
+ */
+ public String getMemColorEnhance() {
+ return get(KEY_QC_MEMORY_COLOR_ENHANCEMENT);
+ }
+
+ /** @hide
+ * Sets the current MCE Mode.
+ *
+ * @return MCE Mode
+ */
+ public void setMemColorEnhance(String mce) {
+ set(KEY_QC_MEMORY_COLOR_ENHANCEMENT, mce);
+ }
+
+ /** @hide
+ * Set white balance manual cct value.
+ *
+ * @param cct user CCT setting.
+ */
+ public void setWBManualCCT(int cct) {
+ set(KEY_QC_WB_MANUAL_CCT, Integer.toString(cct));
+ }
+
+ /** @hide
+ * Gets the WB min supported CCT.
+ *
+ * @return min cct value.
+ */
+ public String getWBMinCCT() {
+ return get(KEY_QC_MIN_WB_CCT);
+ }
+
+ /** @hide
+ * Gets the WB max supported CCT.
+ *
+ * @return max cct value.
+ */
+ public String getMaxWBCCT() {
+ return get(KEY_QC_MAX_WB_CCT);
+ }
+
+ /** @hide
+ * Gets the current WB CCT.
+ *
+ * @return CCT value
+ */
+ public String getWBCurrentCCT() {
+ return get(KEY_QC_WB_MANUAL_CCT);
+ }
+
+ /** @hide
+ * Gets the current ZSL Mode.
+ *
+ * @return ZSL mode value
+ */
+ public String getZSLMode() {
+ return get(KEY_QC_ZSL);
+ }
+
+ /** @hide
+ * Sets the current ZSL Mode. ZSL mode is set as a 0th bit in KEY_CAMERA_MODE.
+ *
+ * @return null
+ */
+ public void setZSLMode(String zsl) {
+ set(KEY_QC_ZSL, zsl);
+ }
+
+ /** @hide
+ * Sets the current Auto HDR Mode.
+ * @ auto_hdr auto hdr string for enable/disable
+ * @return null
+ */
+ public void setAutoHDRMode(String auto_hdr){
+ set(KEY_QC_AUTO_HDR_ENABLE,auto_hdr);
+ }
+
+ /** @hide
+ * Gets the current Camera Mode Flag. Camera mode includes a
+ * flag(byte) which indicates different camera modes.
+ * For now support for ZSL added at bit0
+ *
+ * @return Camera Mode.
+ */
+ public String getCameraMode() {
+ return get(KEY_QC_CAMERA_MODE);
+ }
+
+ /** @hide
+ * Sets the current Camera Mode.
+ *
+ * @return null
+ */
+ public void setCameraMode(int cameraMode) {
+ set(KEY_QC_CAMERA_MODE, cameraMode);
+ }
+
+ private static final int MANUAL_FOCUS_POS_TYPE_INDEX = 0;
+ private static final int MANUAL_FOCUS_POS_TYPE_DAC = 1;
+ /** @hide
+ * Set focus position.
+ *
+ * @param pos user setting of focus position.
+ */
+ public void setFocusPosition(int type, int pos) {
+ set(KEY_QC_MANUAL_FOCUS_POS_TYPE, Integer.toString(type));
+ set(KEY_QC_MANUAL_FOCUS_POSITION, Integer.toString(pos));
+ }
+
+ /** @hide
+ * Gets the current focus position.
+ *
+ * @return current focus position
+ */
+ public String getCurrentFocusPosition() {
+ return get(KEY_QC_MANUAL_FOCUS_POSITION);
+ }
+
+
+ /** @hide
+ * Gets the current HFR Mode.
+ *
+ * @return VIDEO_HFR_XXX string constants
+ */
+ public String getVideoHighFrameRate() {
+ return get(KEY_QC_VIDEO_HIGH_FRAME_RATE);
+ }
+
+ /** @hide
+ * Sets the current HFR Mode.
+ *
+ * @param hfr VIDEO_HFR_XXX string constants
+ */
+ public void setVideoHighFrameRate(String hfr) {
+ set(KEY_QC_VIDEO_HIGH_FRAME_RATE, hfr);
+ }
+
+ /** @hide
+ * Gets the current Video HDR Mode.
+ *
+ * @return Video HDR mode value
+ */
+ public String getVideoHDRMode() {
+ return get(KEY_QC_VIDEO_HDR);
+ }
+
+ /** @hide
+ * Sets the current Video HDR Mode.
+ *
+ * @return null
+ */
+ public void setVideoHDRMode(String videohdr) {
+ set(KEY_QC_VIDEO_HDR, videohdr);
+ }
+
+ /** @hide
+ * Gets the current DENOISE setting.
+ *
+ * @return one of DENOISE_XXX string constant. null if Denoise
+ * setting is not supported.
+ *
+ */
+ public String getDenoise() {
+ return get(KEY_QC_DENOISE);
+ }
+
+ /** @hide
+ * Gets the current Continuous AF setting.
+ *
+ * @return one of CONTINUOUS_AF_XXX string constant. null if continuous AF
+ * setting is not supported.
+ *
+ */
+ public String getContinuousAf() {
+ return get(KEY_QC_CONTINUOUS_AF);
+ }
+
+ /** @hide
+ * Sets the current Denoise mode.
+ * @param value DENOISE_XXX string constants.
+ *
+ */
+
+ public void setDenoise(String value) {
+ set(KEY_QC_DENOISE, value);
+ }
+
+ /** @hide
+ * Sets the current Continuous AF mode.
+ * @param value CONTINUOUS_AF_XXX string constants.
+ *
+ */
+ public void setContinuousAf(String value) {
+ set(KEY_QC_CONTINUOUS_AF, value);
+ }
+
+ /** @hide
+ * Gets the current selectable zone af setting.
+ *
+ * @return one of SELECTABLE_ZONE_AF_XXX string constant. null if selectable zone af
+ * setting is not supported.
+ */
+ public String getSelectableZoneAf() {
+ return get(KEY_QC_SELECTABLE_ZONE_AF);
+ }
+
+ /** @hide
+ * Sets the current selectable zone af setting.
+ *
+ * @param value SELECTABLE_ZONE_AF_XXX string constants.
+ */
+ public void setSelectableZoneAf(String value) {
+ set(KEY_QC_SELECTABLE_ZONE_AF, value);
+ }
+
+ /** @hide
+ * Gets the current face detection setting.
+ *
+ * @return one of FACE_DETECTION_XXX string constant. null if face detection
+ * setting is not supported.
+ *
+ */
+ public String getFaceDetectionMode() {
+ return get(KEY_QC_FACE_DETECTION);
+ }
+
+ /** @hide
+ * Sets the auto scene detect. Other settings like Touch AF/AEC might be
+ * changed after setting face detection.
+ *
+ * @param value FACE_DETECTION_XXX string constants.
+ *
+ */
+ public void setFaceDetectionMode(String value) {
+ set(KEY_QC_FACE_DETECTION, value);
+ }
+
+ /** @hide
+ * Gets the current video rotation setting.
+ *
+ * @return one of VIDEO_QC_ROTATION_XXX string constant. null if video rotation
+ * setting is not supported.
+ */
+ public String getVideoRotation() {
+ return get(KEY_QC_VIDEO_ROTATION);
+ }
+
+ /** @hide
+ * Sets the current video rotation setting.
+ *
+ * @param value VIDEO_QC_ROTATION_XXX string constants.
+ */
+ public void setVideoRotation(String value) {
+ set(KEY_QC_VIDEO_ROTATION, value);
+ }
+ /** @hide
+ * Gets the supported video rotation modes.
+ *
+ * @return a List of VIDEO_QC_ROTATION_XXX string constant. null if this
+ * setting is not supported.
+ */
+ public List<String> getSupportedVideoRotationValues() {
+ String str = get(KEY_QC_VIDEO_ROTATION + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ // Splits a comma delimited string to an ArrayList of Coordinate.
+ // Return null if the passing string is null or the Coordinate is 0.
+ private ArrayList<Coordinate> splitCoordinate(String str) {
+ if (str == null) return null;
+ TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
+ splitter.setString(str);
+ ArrayList<Coordinate> coordinateList = new ArrayList<Coordinate>();
+ for (String s : splitter) {
+ Coordinate coordinate = strToCoordinate(s);
+ if (coordinate != null) coordinateList.add(coordinate);
+ }
+ if (coordinateList.size() == 0) return null;
+ return coordinateList;
+ }
+
+ // Parses a string (ex: "500x500") to Coordinate object.
+ // Return null if the passing string is null.
+ private Coordinate strToCoordinate(String str) {
+ if (str == null) return null;
+
+ int pos = str.indexOf('x');
+ if (pos != -1) {
+ String x = str.substring(0, pos);
+ String y = str.substring(pos + 1);
+ return new Coordinate(Integer.parseInt(x),
+ Integer.parseInt(y));
+ }
+ Log.e(TAG, "Invalid Coordinate parameter string=" + str);
+ return null;
+ }
+ /* ### QC ADD-ONS: END */
};
}
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 2fe8fb6..ba0d5be 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -101,6 +101,7 @@ public class SystemSensorManager extends SensorManager {
@Override
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
+ android.util.SeempLog.record_sensor_rate(381, sensor, delayUs);
if (listener == null || sensor == null) {
Log.e(TAG, "sensor or listener is null");
return false;
@@ -142,6 +143,7 @@ public class SystemSensorManager extends SensorManager {
/** @hide */
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
+ android.util.SeempLog.record_sensor(382, sensor);
// Trigger Sensors should use the cancelTriggerSensor call.
if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
return;
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 4866598..a0a03b1 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -920,6 +920,9 @@ public class RequestThreadManager {
mDeviceState.setError(
CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
}
+ if (mPreviewTexture != null) {
+ mPreviewTexture.setOnFrameAvailableListener(null);
+ }
if (mGLThreadManager != null) {
mGLThreadManager.quit();
mGLThreadManager = null;
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index bc80fc1..86eb01d 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -433,6 +433,20 @@ public class SurfaceTextureRenderer {
EGL14.eglChooseConfig(mEGLDisplay, attribList, /*offset*/ 0, configs, /*offset*/ 0,
configs.length, numConfigs, /*offset*/ 0);
checkEglError("eglCreateContext RGB888+recordable ES2");
+ if (numConfigs[0] == 0) {
+ Log.w(TAG, "eglChooseConfig returned no configs, retrying without EGL_RECORDABLE_ANDROID");
+ int[] attribList2 = {
+ EGL14.EGL_RED_SIZE, EGL_COLOR_BITLENGTH,
+ EGL14.EGL_GREEN_SIZE, EGL_COLOR_BITLENGTH,
+ EGL14.EGL_BLUE_SIZE, EGL_COLOR_BITLENGTH,
+ EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
+ EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT | EGL14.EGL_WINDOW_BIT,
+ EGL14.EGL_NONE
+ };
+ EGL14.eglChooseConfig(mEGLDisplay, attribList2, /*offset*/ 0, configs, /*offset*/ 0,
+ configs.length, numConfigs, /*offset*/ 0);
+ checkEglError("eglCreateContext RGB888 ES2");
+ }
mConfigs = configs[0];
int[] attrib_list = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ff7a300..5e9cd97 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -317,6 +317,11 @@ public class InputMethodService extends AbstractInputMethodService {
final Insets mTmpInsets = new Insets();
final int[] mTmpLocation = new int[2];
+ int mVolumeKeyCursorControl;
+ private static final int VOLUME_CURSOR_OFF = 0;
+ private static final int VOLUME_CURSOR_ON = 1;
+ private static final int VOLUME_CURSOR_ON_REVERSE = 2;
+
final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
new ViewTreeObserver.OnComputeInternalInsetsListener() {
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
@@ -1856,6 +1861,26 @@ public class InputMethodService extends AbstractInputMethodService {
}
return false;
}
+ if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) {
+ mVolumeKeyCursorControl = Settings.System.getInt(getContentResolver(),
+ Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0);
+ if (isInputViewShown() && (mVolumeKeyCursorControl != VOLUME_CURSOR_OFF)) {
+ sendDownUpKeyEvents((mVolumeKeyCursorControl == VOLUME_CURSOR_ON_REVERSE)
+ ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT);
+ return true;
+ }
+ return false;
+ }
+ if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ mVolumeKeyCursorControl = Settings.System.getInt(getContentResolver(),
+ Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0);
+ if (isInputViewShown() && (mVolumeKeyCursorControl != VOLUME_CURSOR_OFF)) {
+ sendDownUpKeyEvents((mVolumeKeyCursorControl == VOLUME_CURSOR_ON_REVERSE)
+ ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT);
+ return true;
+ }
+ return false;
+ }
return doMovementKey(keyCode, event, MOVEMENT_DOWN);
}
@@ -1906,6 +1931,15 @@ public class InputMethodService extends AbstractInputMethodService {
return handleBack(true);
}
}
+ if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
+ || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ mVolumeKeyCursorControl = Settings.System.getInt(getContentResolver(),
+ Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0);
+ if (isInputViewShown() && (mVolumeKeyCursorControl != VOLUME_CURSOR_OFF)) {
+ return true;
+ }
+ return false;
+ }
return doMovementKey(keyCode, event, MOVEMENT_UP);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4d9b759..6bbd9c8 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.NetworkUtils;
+import android.net.wifi.WifiDevice;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
@@ -49,6 +50,7 @@ import com.android.internal.util.Protocol;
import java.net.InetAddress;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.HashMap;
+import java.util.List;
import libcore.net.event.NetworkEventDispatcher;
@@ -283,6 +285,15 @@ public class ConnectivityManager {
"android.net.conn.TETHER_STATE_CHANGED";
/**
+ * Broadcast intent action indicating that a Station is connected
+ * or disconnected.
+ *
+ * @hide
+ */
+ public static final String TETHER_CONNECT_STATE_CHANGED =
+ "codeaurora.net.conn.TETHER_CONNECT_STATE_CHANGED";
+
+ /**
* @hide
* gives a String[] listing all the interfaces configured for
* tethering and currently available for tethering.
@@ -1838,6 +1849,20 @@ public class ConnectivityManager {
}
}
+ /**
+ * Get the list of Stations connected to Hotspot.
+ *
+ * @return a list of {@link WifiDevice} objects.
+ * {@hide}
+ */
+ public List<WifiDevice> getTetherConnectedSta() {
+ try {
+ return mService.getTetherConnectedSta();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
/** {@hide} */
public static final int TETHER_ERROR_NO_ERROR = 0;
/** {@hide} */
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index d4dd669..c6de7a5 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -26,6 +26,7 @@ import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.ProxyInfo;
+import android.net.wifi.WifiDevice;
import android.os.IBinder;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
@@ -36,6 +37,8 @@ import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
+import java.util.List;
+
/**
* Interface that answers queries about, and allows changing, the
* state of network connectivity.
@@ -92,6 +95,8 @@ interface IConnectivityManager
int setUsbTethering(boolean enable);
+ List<WifiDevice> getTetherConnectedSta();
+
void reportInetCondition(int networkType, int percentage);
void reportNetworkConnectivity(in Network network, boolean hasConnectivity);
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index b7af374..5a70ff1 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -92,6 +92,13 @@ interface INetworkManagementEventObserver {
void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos);
/**
+ * Message is received from network interface.
+ *
+ * @param message The message
+ */
+ void interfaceMessageRecevied(String message);
+
+ /**
* Information about available DNS servers has been received.
*
* @param iface The interface on which the information was received.
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index c4de4a2..49dc93b 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -57,6 +57,8 @@ public final class LinkProperties implements Parcelable {
private int mMtu;
// in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
private String mTcpBufferSizes;
+ private int mTcpDelayedAckSegments = 1;
+ private int mTcpUserCfg = 0;
private static final int MIN_MTU = 68;
private static final int MIN_MTU_V6 = 1280;
@@ -156,6 +158,8 @@ public final class LinkProperties implements Parcelable {
}
setMtu(source.getMtu());
mTcpBufferSizes = source.mTcpBufferSizes;
+ mTcpDelayedAckSegments = source.mTcpDelayedAckSegments;
+ mTcpUserCfg = source.mTcpUserCfg;
}
}
@@ -439,6 +443,45 @@ public final class LinkProperties implements Parcelable {
return mTcpBufferSizes;
}
+ /**
+ * Number of full MSS to receive before Acking RFC2581
+ * @param segments The number of segments to receive
+ *
+ * @hide
+ */
+ public void setTcpDelayedAckSegments(int segments) {
+ mTcpDelayedAckSegments = segments;
+ }
+
+ /**
+ * Gets the number of segments before acking
+ *
+ * @hide
+ */
+ public int getTcpDelayedAckSegments() {
+ return mTcpDelayedAckSegments;
+ }
+
+ /**
+ * Sets the value for TCP usercfg
+ *
+ * @param value 0/1 currently to disable/enable
+ *
+ * @hide
+ */
+ public void setTcpUserCfg(int value) {
+ mTcpUserCfg = value;
+ }
+
+ /**
+ * Gets the value of TCP usercfg
+ *
+ * @hide
+ */
+ public int getTcpUserCfg() {
+ return mTcpUserCfg;
+ }
+
private RouteInfo routeWithInterface(RouteInfo route) {
return new RouteInfo(
route.getDestination(),
@@ -599,6 +642,8 @@ public final class LinkProperties implements Parcelable {
mStackedLinks.clear();
mMtu = 0;
mTcpBufferSizes = null;
+ mTcpDelayedAckSegments = 1;
+ mTcpUserCfg = 0;
}
/**
diff --git a/core/java/android/net/wimax/WimaxHelper.java b/core/java/android/net/wimax/WimaxHelper.java
new file mode 100644
index 0000000..9a6727e
--- /dev/null
+++ b/core/java/android/net/wimax/WimaxHelper.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011-2015 The CyanogenMod 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.net.wimax;
+
+import dalvik.system.DexClassLoader;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.provider.Settings;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * {@hide}
+ */
+public class WimaxHelper {
+
+ private static final String TAG = "WimaxHelper";
+
+ private static final String WIMAX_CONTROLLER_CLASSNAME = "com.htc.net.wimax.WimaxController";
+ private static final String WIMAX_MANAGER_CLASSNAME = "android.net.fourG.wimax.Wimax4GManager";
+
+ private static DexClassLoader sWimaxClassLoader;
+ private static String sWimaxManagerClassname, sIsWimaxEnabledMethodname,
+ sSetWimaxEnabledMethodname, sGetWimaxStateMethodname;
+
+ public static boolean isWimaxSupported(Context context) {
+ return context.getResources().getBoolean(
+ com.android.internal.R.bool.config_wimaxEnabled);
+ }
+
+ public static DexClassLoader getWimaxClassLoader(Context context) {
+ if (isWimaxSupported(context)) {
+ if (sWimaxClassLoader == null) {
+ sWimaxManagerClassname = context.getResources().getString(
+ com.android.internal.R.string.config_wimaxManagerClassname);
+
+ // WimaxController::getWimaxState == Wimax4GManager::get4GState.
+ // However, Wimax4GManager also implements a different getWimaxState
+ // method, which returns a WimaxState object describing the connection
+ // state, not the enabled state. Other methods are similarly renamed.
+ if (sWimaxManagerClassname.equals(WIMAX_CONTROLLER_CLASSNAME)) {
+ sIsWimaxEnabledMethodname = "isWimaxEnabled";
+ sSetWimaxEnabledMethodname = "setWimaxEnabled";
+ sGetWimaxStateMethodname = "getWimaxState";
+ } else if (sWimaxManagerClassname.equals(WIMAX_MANAGER_CLASSNAME)) {
+ sIsWimaxEnabledMethodname = "is4GEnabled";
+ sSetWimaxEnabledMethodname = "set4GEnabled";
+ sGetWimaxStateMethodname = "get4GState";
+ }
+
+ String wimaxJarLocation = context.getResources().getString(
+ com.android.internal.R.string.config_wimaxServiceJarLocation);
+ String wimaxLibLocation = context.getResources().getString(
+ com.android.internal.R.string.config_wimaxNativeLibLocation);
+ sWimaxClassLoader = new DexClassLoader(wimaxJarLocation,
+ new ContextWrapper(context).getCacheDir().getAbsolutePath(),
+ wimaxLibLocation,ClassLoader.getSystemClassLoader());
+ }
+ return sWimaxClassLoader;
+ }
+ return null;
+ }
+
+ public static Object createWimaxService(Context context, Handler handler) {
+ Object controller = null;
+
+ try {
+ DexClassLoader wimaxClassLoader = getWimaxClassLoader(context);
+ if (sWimaxManagerClassname.equals(WIMAX_CONTROLLER_CLASSNAME)) {
+ // Load supersonic's and speedy's WimaxController.
+ IBinder b = ServiceManager.getService(WimaxManagerConstants.WIMAX_SERVICE);
+ if (b != null) {
+ Class<?> klass = wimaxClassLoader.loadClass("com.htc.net.wimax.IWimaxController$Stub");
+ if (klass != null) {
+ Method asInterface = klass.getMethod("asInterface", IBinder.class);
+ Object wc = asInterface.invoke(null, b);
+ if (wc != null) {
+ klass = wimaxClassLoader.loadClass(WIMAX_CONTROLLER_CLASSNAME);
+ if (klass != null) {
+ Constructor<?> ctor = klass.getDeclaredConstructors()[1];
+ controller = ctor.newInstance(wc, handler);
+ }
+ }
+ }
+ }
+ } else if (sWimaxManagerClassname.equals(WIMAX_MANAGER_CLASSNAME)) {
+ // Load crespo4g's (and epicmtd's) Wimax4GManager.
+ // Note that crespo4g's implementation grabs WIMAX_SERVICE internally, so
+ // it doesn't need to be passed in. Other implementations (may) require
+ // WIMAX_SERVICE to be grabbed externally, so check Wimax4GManager::<init>.
+ Class<?> klass = wimaxClassLoader.loadClass(WIMAX_MANAGER_CLASSNAME);
+ if (klass != null) {
+ Constructor<?> ctor = klass.getDeclaredConstructors()[0];
+ controller = ctor.newInstance();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to create WimaxController instance", e);
+ }
+
+ return controller;
+ }
+
+ public static boolean isWimaxEnabled(Context context) {
+ boolean ret = false;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method m = wimaxService.getClass().getMethod(sIsWimaxEnabledMethodname);
+ ret = (Boolean) m.invoke(wimaxService);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to get WiMAX enabled state!", e);
+ }
+ return ret;
+ }
+
+ public static boolean setWimaxEnabled(Context context, boolean enabled) {
+ boolean ret = false;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method m = wimaxService.getClass().getMethod(sSetWimaxEnabledMethodname, boolean.class);
+ ret = (Boolean) m.invoke(wimaxService, enabled);
+ if (ret)
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.WIMAX_ON, (Boolean) enabled ? 1 : 0);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to set WiMAX state!", e);
+ }
+ return ret;
+ }
+
+ public static int getWimaxState(Context context) {
+ int ret = 0;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method m = wimaxService.getClass().getMethod(sGetWimaxStateMethodname);
+ ret = (Integer) m.invoke(wimaxService);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to get WiMAX state!", e);
+ }
+ return ret;
+ }
+
+ public static boolean wimaxRescan(Context context) {
+ boolean ret = false;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method wimaxRescan = wimaxService.getClass().getMethod("wimaxRescan");
+ if (wimaxRescan != null) {
+ wimaxRescan.invoke(wimaxService);
+ ret = true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to perform WiMAX rescan!", e);
+ }
+ return ret;
+ }
+
+ private static Object getWimaxInfo(Context context) {
+ Object wimaxInfo = null;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method getConnectionInfo = wimaxService.getClass().getMethod("getConnectionInfo");
+ wimaxInfo = getConnectionInfo.invoke(wimaxService);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to get a WimaxInfo object!", e);
+ }
+ return wimaxInfo;
+ }
+} \ No newline at end of file
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 7678678..09487d7 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -48,53 +48,53 @@ import java.util.Map;
/**
* @hide
*/
-public final class ApduServiceInfo implements Parcelable {
+public class ApduServiceInfo implements Parcelable {
static final String TAG = "ApduServiceInfo";
/**
* The service that implements this
*/
- final ResolveInfo mService;
+ protected ResolveInfo mService;
/**
* Description of the service
*/
- final String mDescription;
+ protected String mDescription;
/**
* Whether this service represents AIDs running on the host CPU
*/
- final boolean mOnHost;
+ protected boolean mOnHost;
/**
* Mapping from category to static AID group
*/
- final HashMap<String, AidGroup> mStaticAidGroups;
+ protected HashMap<String, AidGroup> mStaticAidGroups;
/**
* Mapping from category to dynamic AID group
*/
- final HashMap<String, AidGroup> mDynamicAidGroups;
+ protected HashMap<String, AidGroup> mDynamicAidGroups;
/**
* Whether this service should only be started when the device is unlocked.
*/
- final boolean mRequiresDeviceUnlock;
+ protected boolean mRequiresDeviceUnlock;
/**
* The id of the service banner specified in XML.
*/
- final int mBannerResourceId;
+ protected int mBannerResourceId;
/**
* The uid of the package the service belongs to
*/
- final int mUid;
+ protected int mUid;
/**
* Settings Activity for this service
*/
- final String mSettingsActivityName;
+ protected String mSettingsActivityName;
/**
* @hide
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 1f3e9a7..050820c 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +17,7 @@
package android.os;
+import android.app.IBatteryService;
import android.content.Context;
import android.os.BatteryProperty;
import android.os.IBatteryPropertiesRegistrar;
@@ -95,6 +97,79 @@ public class BatteryManager {
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock status constant.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_STATUS = "dock_status";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock health constant.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_HEALTH = "dock_health";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * boolean indicating whether a dock battery is present.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_PRESENT = "dock_present";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer field containing the current dock battery level, from 0 to
+ * {@link #EXTRA_SCALE}.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_LEVEL = "dock_level";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the maximum dock battery level.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_SCALE = "dock_scale";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the resource ID of a small status bar icon
+ * indicating the current dock battery state.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_ICON_SMALL = "dock_icon-small";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer indicating whether the device is plugged in to a dock power
+ * source.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_PLUGGED = "dock_plugged";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock battery voltage level.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_VOLTAGE = "dock_voltage";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the current dock battery temperature.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_TEMPERATURE = "dock_temperature";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * String describing the technology of the current dock battery.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_TECHNOLOGY = "dock_technology";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
* Int value set to nonzero if an unsupported charger is attached
* to the device.
* {@hide}
@@ -133,10 +208,23 @@ public class BatteryManager {
/** Power source is wireless. */
public static final int BATTERY_PLUGGED_WIRELESS = 4;
+ // values of the "dock_plugged" field in the ACTION_BATTERY_CHANGED intent.
+ // These must be powers of 2.
+ /** Power source is an DockAC charger.
+ * @hide*/
+ public static final int BATTERY_DOCK_PLUGGED_AC = 1;
+ /** Power source is an DockUSB charger.
+ * @hide*/
+ public static final int BATTERY_DOCK_PLUGGED_USB = 2;
+
/** @hide */
public static final int BATTERY_PLUGGED_ANY =
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+ /** @hide */
+ public static final int BATTERY_DOCK_PLUGGED_ANY =
+ BATTERY_DOCK_PLUGGED_AC | BATTERY_DOCK_PLUGGED_USB;
+
/**
* Sent when the device's battery has started charging (or has reached full charge
* and the device is on power). This is a good time to do work that you would like to
@@ -191,6 +279,7 @@ public class BatteryManager {
*/
public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5;
+ private final IBatteryService mBatteryService;
private final IBatteryStats mBatteryStats;
private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
@@ -202,6 +291,27 @@ public class BatteryManager {
ServiceManager.getService(BatteryStats.SERVICE_NAME));
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(
ServiceManager.getService("batteryproperties"));
+ mBatteryService = null;
+ }
+
+ /** @hide */
+ public BatteryManager(IBatteryService service) {
+ super();
+ mBatteryStats = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
+ mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(
+ ServiceManager.getService("batteryproperties"));
+ mBatteryService = service;
+ }
+
+ /** @hide */
+ public boolean isDockBatterySupported() {
+ try {
+ return mBatteryService != null && mBatteryService.isDockBatterySupported();
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+ return false;
}
/**
@@ -223,8 +333,10 @@ public class BatteryManager {
*
* Returns the requested value, or Long.MIN_VALUE if property not
* supported on this system or on other error.
+ * fromDock determines if the property is query from the normal battery
+ * or the dock battery.
*/
- private long queryProperty(int id) {
+ private long queryProperty(int id, boolean fromDock) {
long ret;
if (mBatteryPropertiesRegistrar == null) {
@@ -234,7 +346,13 @@ public class BatteryManager {
try {
BatteryProperty prop = new BatteryProperty();
- if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0)
+ final int callResult;
+ if (!fromDock) {
+ callResult = mBatteryPropertiesRegistrar.getProperty(id, prop);
+ } else {
+ callResult = mBatteryPropertiesRegistrar.getDockProperty(id, prop);
+ }
+ if (callResult == 0)
ret = prop.getLong();
else
ret = Long.MIN_VALUE;
@@ -255,7 +373,7 @@ public class BatteryManager {
* @return the property value, or Integer.MIN_VALUE if not supported.
*/
public int getIntProperty(int id) {
- return (int)queryProperty(id);
+ return (int)queryProperty(id, false);
}
/**
@@ -268,6 +386,40 @@ public class BatteryManager {
* @return the property value, or Long.MIN_VALUE if not supported.
*/
public long getLongProperty(int id) {
- return queryProperty(id);
+ return queryProperty(id, false);
+ }
+
+ /**
+ * Return the value of a dock battery property of integer type. If the
+ * platform does not provide the property queried, this value will
+ * be Integer.MIN_VALUE.
+ *
+ * @param id identifier of the requested property
+ *
+ * @return the property value, or Integer.MIN_VALUE if not supported.
+ * @hide
+ */
+ public int getIntDockProperty(int id) {
+ if (!isDockBatterySupported()) {
+ return Integer.MIN_VALUE;
+ }
+ return (int)queryProperty(id, true);
+ }
+
+ /**
+ * Return the value of a dock battery property of long type If the
+ * platform does not provide the property queried, this value will
+ * be Long.MIN_VALUE.
+ *
+ * @param id identifier of the requested property
+ *
+ * @return the property value, or Long.MIN_VALUE if not supported.
+ * @hide
+ */
+ public long getLongDockProperty(int id) {
+ if (!isDockBatterySupported()) {
+ return Long.MIN_VALUE;
+ }
+ return queryProperty(id, true);
}
}
diff --git a/core/java/android/os/BatteryManagerInternal.java b/core/java/android/os/BatteryManagerInternal.java
index f3a95b9..1abb3d5 100644
--- a/core/java/android/os/BatteryManagerInternal.java
+++ b/core/java/android/os/BatteryManagerInternal.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +44,26 @@ public abstract class BatteryManagerInternal {
public abstract boolean getBatteryLevelLow();
/**
+ * Returns whether dock batteries is supported
+ */
+ public abstract boolean isDockBatterySupported();
+
+ /**
+ * Returns the current dock plug type.
+ */
+ public abstract int getDockPlugType();
+
+ /**
+ * Returns dock battery level as a percentage.
+ */
+ public abstract int getDockBatteryLevel();
+
+ /**
+ * Returns whether we currently consider the dock battery level to be low.
+ */
+ public abstract boolean getDockBatteryLevelLow();
+
+ /**
* Returns a non-zero value if an unsupported charger is attached.
*/
public abstract int getInvalidCharger();
diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java
index 29e868c..cad741a 100644
--- a/core/java/android/os/BatteryProperties.java
+++ b/core/java/android/os/BatteryProperties.java
@@ -1,4 +1,5 @@
/* Copyright 2013, The Android Open Source Project
+ * Copyright 2016, The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +32,16 @@ public class BatteryProperties implements Parcelable {
public int batteryTemperature;
public String batteryTechnology;
+ public boolean dockBatterySupported;
+ public boolean chargerDockAcOnline;
+ public int dockBatteryStatus;
+ public int dockBatteryHealth;
+ public boolean dockBatteryPresent;
+ public int dockBatteryLevel;
+ public int dockBatteryVoltage;
+ public int dockBatteryTemperature;
+ public String dockBatteryTechnology;
+
public BatteryProperties() {
}
@@ -46,6 +57,16 @@ public class BatteryProperties implements Parcelable {
batteryVoltage = other.batteryVoltage;
batteryTemperature = other.batteryTemperature;
batteryTechnology = other.batteryTechnology;
+
+ dockBatterySupported = other.dockBatterySupported;
+ chargerDockAcOnline = other.chargerDockAcOnline;
+ dockBatteryStatus = other.dockBatteryStatus;
+ dockBatteryHealth = other.dockBatteryHealth;
+ dockBatteryPresent = other.dockBatteryPresent;
+ dockBatteryLevel = other.dockBatteryLevel;
+ dockBatteryVoltage = other.dockBatteryVoltage;
+ dockBatteryTemperature = other.dockBatteryTemperature;
+ dockBatteryTechnology = other.dockBatteryTechnology;
}
/*
@@ -65,6 +86,27 @@ public class BatteryProperties implements Parcelable {
batteryVoltage = p.readInt();
batteryTemperature = p.readInt();
batteryTechnology = p.readString();
+
+ dockBatterySupported = p.readInt() == 1 ? true : false;
+ if (dockBatterySupported) {
+ chargerDockAcOnline = p.readInt() == 1 ? true : false;
+ dockBatteryStatus = p.readInt();
+ dockBatteryHealth = p.readInt();
+ dockBatteryPresent = p.readInt() == 1 ? true : false;
+ dockBatteryLevel = p.readInt();
+ dockBatteryVoltage = p.readInt();
+ dockBatteryTemperature = p.readInt();
+ dockBatteryTechnology = p.readString();
+ } else {
+ chargerDockAcOnline = false;
+ dockBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+ dockBatteryHealth = BatteryManager.BATTERY_HEALTH_UNKNOWN;
+ dockBatteryPresent = false;
+ dockBatteryLevel = 0;
+ dockBatteryVoltage = 0;
+ dockBatteryTemperature = 0;
+ dockBatteryTechnology = "";
+ }
}
public void writeToParcel(Parcel p, int flags) {
@@ -79,6 +121,18 @@ public class BatteryProperties implements Parcelable {
p.writeInt(batteryVoltage);
p.writeInt(batteryTemperature);
p.writeString(batteryTechnology);
+
+ p.writeInt(dockBatterySupported ? 1 : 0);
+ if (dockBatterySupported) {
+ p.writeInt(chargerDockAcOnline ? 1 : 0);
+ p.writeInt(dockBatteryStatus);
+ p.writeInt(dockBatteryHealth);
+ p.writeInt(dockBatteryPresent ? 1 : 0);
+ p.writeInt(dockBatteryLevel);
+ p.writeInt(dockBatteryVoltage);
+ p.writeInt(dockBatteryTemperature);
+ p.writeString(dockBatteryTechnology);
+ }
}
public static final Parcelable.Creator<BatteryProperties> CREATOR
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f346fe7..a800ed6 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -37,6 +37,7 @@ public class Environment {
private static final String ENV_ANDROID_STORAGE = "ANDROID_STORAGE";
private static final String ENV_OEM_ROOT = "OEM_ROOT";
private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
+ private static final String ENV_PREBUNDLED_ROOT = "PREBUNDLED_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -55,6 +56,7 @@ public class Environment {
private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
+ private static final File DIR_PREBUNDLED_ROOT = getDirectory(ENV_PREBUNDLED_ROOT, "/bundled-app");
private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
@@ -165,6 +167,15 @@ public class Environment {
}
/**
+ * Return the root directory for "prebundled" apps. These apps will be installed directly
+ * from this partition but will not be marked as system apps and will hence be uninstallable.
+ * @hide
+ */
+ public static File getPrebundledDirectory() {
+ return DIR_PREBUNDLED_ROOT;
+ }
+
+ /**
* Gets the system directory available for secure storage.
* If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
* Otherwise, it returns the unencrypted /data/system directory.
diff --git a/core/java/android/os/IBatteryPropertiesRegistrar.aidl b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
index fd01802..43b9650 100644
--- a/core/java/android/os/IBatteryPropertiesRegistrar.aidl
+++ b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
@@ -1,5 +1,6 @@
/*
** Copyright 2013, The Android Open Source Project
+** Copyright 2016, The CyanogenMod Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -27,4 +28,5 @@ interface IBatteryPropertiesRegistrar {
void registerListener(IBatteryPropertiesListener listener);
void unregisterListener(IBatteryPropertiesListener listener);
int getProperty(in int id, out BatteryProperty prop);
+ int getDockProperty(in int id, out BatteryProperty prop);
}
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index f55883a..6c7cd6d 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -35,4 +35,5 @@ interface IDeviceIdleController {
long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
long addPowerSaveTempWhitelistAppForSms(String name, int userId, String reason);
void exitIdle(String reason);
+ int getIdleStateDetailed();
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 0f37ac7..4e0f329 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -60,4 +60,14 @@ interface IPowerManager
// sets the attention light (used by phone app only)
void setAttentionLight(boolean on, int color);
+ // update the uids being synchronized by network socket request manager
+ void updateBlockedUids(int uid, boolean isBlocked);
+
+ void setKeyboardVisibility(boolean visible);
+
+ void setKeyboardLight(boolean on, int key);
+
+ oneway void cpuBoost(int duration);
+
+ void wakeUpWithProximityCheck(long time, String reason, String opPackageName);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 9a1a03e..bbee5a3 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -18,7 +18,10 @@ package android.os;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
import android.util.Log;
/**
@@ -387,7 +390,7 @@ public final class PowerManager {
* @hide
*/
public static final String REBOOT_RECOVERY = "recovery";
-
+
final Context mContext;
final IPowerManager mService;
final Handler mHandler;
@@ -674,6 +677,19 @@ public final class PowerManager {
}
/**
+ * Forces the device to wake up from sleep only if
+ * nothing is blocking the proximity sensor
+ * @see #wakeUp
+ * @hide
+ */
+ public void wakeUpWithProximityCheck(long time, String reason) {
+ try {
+ mService.wakeUpWithProximityCheck(time, reason, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Forces the device to start napping.
* <p>
* If the device is currently awake, starts dreaming, otherwise does nothing.
@@ -1235,4 +1251,68 @@ public final class PowerManager {
}
}
}
+
+ /**
+ * @hide
+ */
+ public void setKeyboardVisibility(boolean visible)
+ {
+ try {
+ if (mService != null) {
+ mService.setKeyboardVisibility(visible);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * sets the keyboard LED state
+ *
+ * @param on boolean state
+ * @param key 1 for caps, 2 for fn
+ *
+ * {@hide}
+ */
+ public void setKeyboardLight(boolean on, int key)
+ {
+ try {
+ mService.setKeyboardLight(on, key);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Gets the default button brightness value.
+ * @hide
+ */
+ public int getDefaultButtonBrightness() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_buttonBrightnessSettingDefault);
+ }
+
+ /**
+ * Gets the default keyboard brightness value.
+ * @hide
+ */
+ public int getDefaultKeyboardBrightness() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_keyboardBrightnessSettingDefault);
+ }
+
+ /**
+ * Boost the CPU. Boosts the cpu for the given duration in microseconds.
+ *
+ * @param duration in microseconds to boost the CPU
+ *
+ * @hide
+ */
+ public void cpuBoost(int duration)
+ {
+ try {
+ if (mService != null) {
+ mService.cpuBoost(duration);
+ }
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index b6d0fcb..39c12f0 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -159,4 +159,11 @@ public abstract class PowerManagerInternal {
public abstract void uidGone(int uid);
public abstract void powerHint(int hintId, int data);
+
+ public abstract boolean setPowerSaveMode(boolean mode);
+
+ public abstract void setFeature(int featureId, int data);
+
+ public abstract int getFeature(int featureId);
+
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7234e98..65b09eb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -487,11 +487,12 @@ public class Process {
String abi,
String instructionSet,
String appDataDir,
+ boolean refreshTheme,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
- abi, instructionSet, appDataDir, zygoteArgs);
+ abi, instructionSet, appDataDir, refreshTheme, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -610,6 +611,7 @@ public class Process {
String abi,
String instructionSet,
String appDataDir,
+ boolean refreshTheme,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
@@ -648,6 +650,9 @@ public class Process {
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
+ if (refreshTheme) {
+ argsForZygote.add("--refresh_theme");
+ }
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 0c79094..4b6e6c1 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -341,6 +341,10 @@ public class RecoverySystem {
} finally {
uncryptFile.close();
}
+ // UNCRYPT_FILE needs to be readable by system server on bootup.
+ if (!UNCRYPT_FILE.setReadable(true, false)) {
+ Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath());
+ }
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
// If the package is on the /data partition, write the block map file
@@ -368,21 +372,21 @@ public class RecoverySystem {
* @throws SecurityException if the current user is not allowed to wipe data.
*/
public static void rebootWipeUserData(Context context) throws IOException {
- rebootWipeUserData(context, false, context.getPackageName());
+ rebootWipeUserData(context, false, context.getPackageName(), false);
}
/** {@hide} */
public static void rebootWipeUserData(Context context, String reason) throws IOException {
- rebootWipeUserData(context, false, reason);
+ rebootWipeUserData(context, false, reason, false);
}
/** {@hide} */
public static void rebootWipeUserData(Context context, boolean shutdown)
throws IOException {
- rebootWipeUserData(context, shutdown, context.getPackageName());
+ rebootWipeUserData(context, shutdown, context.getPackageName(), false);
}
- /**
+ /**
* Reboots the device and wipes the user data and cache
* partitions. This is sometimes called a "factory reset", which
* is something of a misnomer because the system partition is not
@@ -400,8 +404,8 @@ public class RecoverySystem {
*
* @hide
*/
- public static void rebootWipeUserData(Context context, boolean shutdown, String reason)
- throws IOException {
+ public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
+ boolean wipeMedia) throws IOException {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
throw new SecurityException("Wiping data is not allowed for this user.");
@@ -433,7 +437,13 @@ public class RecoverySystem {
}
final String localeArg = "--locale=" + Locale.getDefault().toString();
- bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);
+
+ String cmd = "--wipe_data\n";
+ if (wipeMedia) {
+ cmd += "--wipe_media\n";
+ }
+
+ bootCommand(context, shutdownArg, cmd, reasonArg, localeArg);
}
/**
@@ -501,6 +511,25 @@ public class RecoverySystem {
Log.e(TAG, "Error reading recovery log", e);
}
+ if (UNCRYPT_FILE.exists()) {
+ String filename = null;
+ try {
+ filename = FileUtils.readTextFile(UNCRYPT_FILE, 0, null);
+ } catch (IOException e) {
+ Log.e(TAG, "Error reading uncrypt file", e);
+ }
+
+ // Remove the OTA package on /data that has been (possibly
+ // partially) processed. (Bug: 24973532)
+ if (filename != null && filename.startsWith("/data")) {
+ if (UNCRYPT_FILE.delete()) {
+ Log.i(TAG, "Deleted: " + filename);
+ } else {
+ Log.e(TAG, "Can't delete: " + filename);
+ }
+ }
+ }
+
// Delete everything in RECOVERY_DIR except those beginning
// with LAST_PREFIX
String[] names = RECOVERY_DIR.list();
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f10b982..f76a7c2 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1928,9 +1928,9 @@ public final class StrictMode {
// so we'll report it and bail on all of the current strict mode violations
// we currently are maintaining for this thread.
// First, drain the remaining violations from the parcel.
- while (i < numViolations) {
+ i++; // Skip the current entry.
+ for (; i < numViolations; i++) {
info = new ViolationInfo(p, !currentlyGathering);
- i++;
}
// Next clear out all gathered violations.
clearGatheredViolations();
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 045c1e8..5b532a3 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -489,6 +489,18 @@ public class UserManager {
*/
public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+ /**
+ * Specifies if the user is not allowed to use SU commands.
+ * The default value is <code>false</code>.
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ * @hide
+ */
+ public static final String DISALLOW_SU = "no_su";
+
/** @hide */
public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
/** @hide */
@@ -853,6 +865,7 @@ public class UserManager {
Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
guestRestrictions.putBoolean(DISALLOW_SMS, true);
guestRestrictions.putBoolean(DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+ guestRestrictions.putBoolean(DISALLOW_SU, true);
mService.setUserRestrictions(guestRestrictions, guest.id);
} catch (RemoteException re) {
Log.w(TAG, "Could not update guest restrictions");
@@ -892,6 +905,7 @@ public class UserManager {
private static void addDefaultUserRestrictions(Bundle restrictions) {
restrictions.putBoolean(DISALLOW_OUTGOING_CALLS, true);
restrictions.putBoolean(DISALLOW_SMS, true);
+ restrictions.putBoolean(DISALLOW_SU, true);
}
/**
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 9114107..db0b0fd 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -47,6 +47,8 @@ public class DiskInfo implements Parcelable {
public static final int FLAG_DEFAULT_PRIMARY = 1 << 1;
public static final int FLAG_SD = 1 << 2;
public static final int FLAG_USB = 1 << 3;
+ public static final int FLAG_EMMC = 1 << 4;
+ public static final int FLAG_NON_REMOVABLE = 1 << 5;
public final String id;
public final int flags;
@@ -128,6 +130,10 @@ public class DiskInfo implements Parcelable {
return (flags & FLAG_USB) != 0;
}
+ public boolean isNonRemovable() {
+ return (flags & FLAG_NON_REMOVABLE) != 0;
+ }
+
@Override
public String toString() {
final CharArrayWriter writer = new CharArrayWriter();
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 9f71ce1..5f84351 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -645,6 +645,24 @@ public interface IMountService extends IInterface {
return _result;
}
+ public int encryptWipeStorage(int type, String password) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(type);
+ _data.writeString(password);
+ mRemote.transact(Stub.TRANSACTION_encryptWipeStorage, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
public int changeEncryptionPassword(int type, String password) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -1326,6 +1344,8 @@ public interface IMountService extends IInterface {
static final int TRANSACTION_benchmark = IBinder.FIRST_CALL_TRANSACTION + 59;
static final int TRANSACTION_setDebugFlags = IBinder.FIRST_CALL_TRANSACTION + 60;
+ static final int TRANSACTION_encryptWipeStorage = IBinder.FIRST_CALL_TRANSACTION + 61;
+
static final int TRANSACTION_createNewUserDir = IBinder.FIRST_CALL_TRANSACTION + 62;
static final int TRANSACTION_deleteUserKey = IBinder.FIRST_CALL_TRANSACTION + 63;
@@ -1631,6 +1651,15 @@ public interface IMountService extends IInterface {
reply.writeInt(result);
return true;
}
+ case TRANSACTION_encryptWipeStorage: {
+ data.enforceInterface(DESCRIPTOR);
+ int type = data.readInt();
+ String password = data.readString();
+ int result = encryptWipeStorage(type, password);
+ reply.writeNoException();
+ reply.writeInt(result);
+ return true;
+ }
case TRANSACTION_changeEncryptionPassword: {
data.enforceInterface(DESCRIPTOR);
int type = data.readInt();
@@ -2065,7 +2094,8 @@ public interface IMountService extends IInterface {
* Returns whether or not the external storage is emulated.
*/
public boolean isExternalStorageEmulated() throws RemoteException;
-
+ /** The volume has been encrypted succesfully and MDTP state is 'activated'. */
+ static final int ENCRYPTION_STATE_OK_MDTP_ACTIVATED = 2;
/** The volume is not encrypted. */
static final int ENCRYPTION_STATE_NONE = 1;
/** The volume has been encrypted succesfully. */
@@ -2078,6 +2108,8 @@ public interface IMountService extends IInterface {
static final int ENCRYPTION_STATE_ERROR_INCONSISTENT = -3;
/** Underlying data is corrupt */
static final int ENCRYPTION_STATE_ERROR_CORRUPT = -4;
+ /** The volume is in a bad state and MDTP state is 'activated'.*/
+ static final int ENCRYPTION_STATE_ERROR_MDTP_ACTIVATED = -5;
/**
* Determines the encryption state of the volume.
@@ -2096,6 +2128,11 @@ public interface IMountService extends IInterface {
public int encryptStorage(int type, String password) throws RemoteException;
/**
+ * Encrypts and wipes storage.
+ */
+ public int encryptWipeStorage(int type, String password) throws RemoteException;
+
+ /**
* Changes the encryption password.
*/
public int changeEncryptionPassword(int type, String password)
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 1408202..4dbd0a6 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -196,15 +196,20 @@ public class StorageVolume implements Parcelable {
}
/**
- * Parse and return volume UUID as FAT volume ID, or return -1 if unable to
+ * Parse and return volume UUID as volume ID, or return -1 if unable to
* parse or UUID is unknown.
*/
- public int getFatVolumeId() {
- if (mFsUuid == null || mFsUuid.length() != 9) {
+ public int getVolumeId() {
+ String id = mFsUuid;
+ if (id == null) {
return -1;
}
+ id = id.replace("-", "");
+ if (id.length() > 8) {
+ id = id.substring(0, 8);
+ }
try {
- return (int) Long.parseLong(mFsUuid.replace("-", ""), 16);
+ return (int) Long.parseLong(id, 16);
} catch (NumberFormatException e) {
return -1;
}
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 3d57b4d..1aec3ec 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -285,6 +285,22 @@ public abstract class DialogPreference extends Preference implements
* @param state Optional instance state to restore on the dialog
*/
protected void showDialog(Bundle state) {
+ // Create the dialog
+ final Dialog dialog = mDialog = createDialog();
+ if (state != null) {
+ dialog.onRestoreInstanceState(state);
+ }
+ if (needInputMethod()) {
+ requestInputMethod(dialog);
+ }
+ dialog.setOnDismissListener(this);
+ dialog.show();
+ }
+
+ /**
+ * @hide
+ */
+ protected Dialog createDialog() {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
@@ -306,17 +322,8 @@ public abstract class DialogPreference extends Preference implements
onPrepareDialogBuilder(mBuilder);
getPreferenceManager().registerOnActivityDestroyListener(this);
-
- // Create the dialog
- final Dialog dialog = mDialog = mBuilder.create();
- if (state != null) {
- dialog.onRestoreInstanceState(state);
- }
- if (needInputMethod()) {
- requestInputMethod(dialog);
- }
- dialog.setOnDismissListener(this);
- dialog.show();
+
+ return mBuilder.create();
}
/**
diff --git a/core/java/android/preference/MultiSelectListPreference.java b/core/java/android/preference/MultiSelectListPreference.java
index 138bd87..6acfd8d 100644..100755
--- a/core/java/android/preference/MultiSelectListPreference.java
+++ b/core/java/android/preference/MultiSelectListPreference.java
@@ -220,7 +220,7 @@ public class MultiSelectListPreference extends DialogPreference {
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
final CharSequence[] defaultValues = a.getTextArray(index);
- final int valueCount = defaultValues.length;
+ final int valueCount = defaultValues != null ? defaultValues.length : 0;
final Set<String> result = new HashSet<String>();
for (int i = 0; i < valueCount; i++) {
@@ -247,7 +247,20 @@ public class MultiSelectListPreference extends DialogPreference {
myState.values = getValues();
return myState;
}
-
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (!state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ setValues(myState.values);
+ }
+
private static class SavedState extends BaseSavedState {
Set<String> values;
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 3b482eb..b15a7e5 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1377,10 +1377,18 @@ public class Preference implements Comparable<Preference> {
mDefaultValue = defaultValue;
}
+ /**
+ * Returns whether the preference can be found in persistent storage
+ * @hide
+ */
+ protected boolean isPersisted() {
+ return getSharedPreferences().contains(mKey);
+ }
+
private void dispatchSetInitialValue() {
// By now, we know if we are persistent.
final boolean shouldPersist = shouldPersist();
- if (!shouldPersist || !getSharedPreferences().contains(mKey)) {
+ if (!shouldPersist || !isPersisted()) {
if (mDefaultValue != null) {
onSetInitialValue(false, mDefaultValue);
}
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 66642de..db04c71 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -214,6 +214,9 @@ public abstract class PreferenceFragment extends Fragment implements
@Override
public void onDestroyView() {
+ if (mList != null) {
+ mList.setOnKeyListener(null);
+ }
mList = null;
mHandler.removeCallbacks(mRequestFocus);
mHandler.removeMessages(MSG_BIND_PREFERENCES);
diff --git a/core/java/android/preference/PreferenceGroup.java b/core/java/android/preference/PreferenceGroup.java
index 5e84086..f17506b 100644
--- a/core/java/android/preference/PreferenceGroup.java
+++ b/core/java/android/preference/PreferenceGroup.java
@@ -148,16 +148,15 @@ public abstract class PreferenceGroup extends Preference implements GenericInfla
}
}
- int insertionIndex = Collections.binarySearch(mPreferenceList, preference);
- if (insertionIndex < 0) {
- insertionIndex = insertionIndex * -1 - 1;
- }
-
if (!onPrepareAddPreference(preference)) {
return false;
}
synchronized(this) {
+ int insertionIndex = Collections.binarySearch(mPreferenceList, preference);
+ if (insertionIndex < 0) {
+ insertionIndex = insertionIndex * -1 - 1;
+ }
mPreferenceList.add(insertionIndex, preference);
}
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
index a76bb09..c730329 100644
--- a/core/java/android/preference/RingtonePreference.java
+++ b/core/java/android/preference/RingtonePreference.java
@@ -48,8 +48,10 @@ public class RingtonePreference extends Preference implements
private int mRingtoneType;
private boolean mShowDefault;
private boolean mShowSilent;
+ private int mDialogStyle;
private int mRequestCode;
+ private int mSubscriptionID = 0; /* Sub-1 by default */
public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
@@ -62,6 +64,8 @@ public class RingtonePreference extends Preference implements
true);
mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent,
true);
+ mDialogStyle = a.getResourceId(
+ com.android.internal.R.styleable.RingtonePreference_dialogStyle, 0);
a.recycle();
}
@@ -98,6 +102,28 @@ public class RingtonePreference extends Preference implements
}
/**
+ * Returns the subscription ID.
+ *
+ * @return The current subscription ID.
+ * @see #setSubId(int)
+ * @hide
+ */
+ public int getSubId() {
+ return mSubscriptionID;
+ }
+
+ /**
+ * Sets the subscription ID.
+ *
+ * @param subId subscription ID.
+ * @see #getSubId(int)
+ * @hide
+ */
+ public void setSubId(int subId) {
+ mSubscriptionID = subId;
+ }
+
+ /**
* Returns whether to a show an item for the default sound/ringtone.
*
* @return Whether to show an item for the default sound/ringtone.
@@ -136,6 +162,27 @@ public class RingtonePreference extends Preference implements
mShowSilent = showSilent;
}
+ /**
+ * Returns the resource id style of the ringtone dialog.
+ *
+ * @return The resource id of the style
+ * @hide
+ */
+ public int getDialogStyle() {
+ return mDialogStyle;
+ }
+
+ /**
+ * Sets the resource id style of the ringtone dialog.
+ *
+ * @param dialogStyle The resource id of the style.
+ * @see RingtoneManager#EXTRA_RINGTONE_DIALOG_THEME
+ * @hide
+ */
+ public void setDialogStyle(int dialogStyle) {
+ mDialogStyle = dialogStyle;
+ }
+
@Override
protected void onClick() {
// Launch the ringtone picker
@@ -163,8 +210,17 @@ public class RingtonePreference extends Preference implements
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
if (mShowDefault) {
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
+ if (getRingtoneType() == RingtoneManager.TYPE_RINGTONE) {
+ ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
+ RingtoneManager.getActualRingtoneUriBySubId(getContext(), getSubId()));
+ } else {
+ ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
RingtoneManager.getDefaultUri(getRingtoneType()));
+ }
+ }
+ if (mDialogStyle != 0) {
+ ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DIALOG_THEME,
+ mDialogStyle);
}
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 2445bc2..72f5de5 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -59,6 +59,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private final NotificationManager mNotificationManager;
private final int mStreamType;
private final int mMaxStreamVolume;
+ private final boolean mVoiceCapable;
private boolean mAffectedByRingerMode;
private boolean mNotificationOrRing;
private final Receiver mReceiver = new Receiver();
@@ -110,12 +111,19 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
}
}
mDefaultUri = defaultUri;
+ mVoiceCapable = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_voice_capable);
}
private static boolean isNotificationOrRing(int stream) {
return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
}
+ private boolean isNotificationStreamLinked() {
+ return mVoiceCapable && Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1;
+ }
+
public void setSeekBar(SeekBar seekBar) {
if (mSeekBar != null) {
mSeekBar.setOnSeekBarChangeListener(null);
@@ -139,13 +147,19 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
mSeekBar.setProgress(mLastAudibleStreamVolume);
} else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
mSeekBar.setProgress(0);
+ mSeekBar.setEnabled(mStreamType == AudioManager.STREAM_RING);
} else if (mMuted) {
mSeekBar.setProgress(0);
} else {
+ mSeekBar.setEnabled(enableSeekBar());
mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume);
}
}
+ private boolean enableSeekBar() {
+ return !(mStreamType == AudioManager.STREAM_NOTIFICATION && isNotificationStreamLinked());
+ }
+
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
@@ -250,7 +264,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
- if (fromTouch) {
+ if (fromTouch && enableSeekBar()) {
postSetVolume(progress);
}
if (mCallback != null) {
@@ -415,7 +429,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
}
private void updateVolumeSlider(int streamType, int streamValue) {
- final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType)
+ final boolean streamMatch = mNotificationOrRing && isNotificationStreamLinked()
+ ? isNotificationOrRing(streamType)
: (streamType == mStreamType);
if (mSeekBar != null && streamMatch && streamValue != -1) {
final boolean muted = mAudioManager.isStreamMute(mStreamType)
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 7d05522..299a95c 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -244,6 +244,7 @@ public class Browser {
*/
public static final Cursor getAllBookmarks(ContentResolver cr) throws
IllegalStateException {
+ android.util.SeempLog.record(32);
return new MatrixCursor(new String[]{Bookmarks.URL}, 0);
}
@@ -256,6 +257,7 @@ public class Browser {
*/
public static final Cursor getAllVisitedUrls(ContentResolver cr) throws
IllegalStateException {
+ android.util.SeempLog.record(33);
return new MatrixCursor(new String[]{Combined.URL}, 0);
}
@@ -264,6 +266,7 @@ public class Browser {
}
private static final Cursor getVisitedLike(ContentResolver cr, String url) {
+ android.util.SeempLog.record(34);
boolean secure = false;
String compareString = url;
if (compareString.startsWith("http://")) {
@@ -324,6 +327,7 @@ public class Browser {
*/
@Deprecated
public static final String[] getVisitedHistory(ContentResolver cr) {
+ android.util.SeempLog.record(35);
return new String[0];
}
@@ -359,6 +363,7 @@ public class Browser {
* @removed
*/
public static final void clearHistory(ContentResolver cr) {
+ android.util.SeempLog.record(37);
}
@@ -420,6 +425,7 @@ public class Browser {
*/
public static final void requestAllIcons(ContentResolver cr, String where,
WebIconDatabase.IconListener listener) {
+ android.util.SeempLog.record(36);
// Do nothing: this is no longer used.
}
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index aa22041..2ede026 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -871,6 +871,7 @@ public final class CalendarContract {
* @return A Cursor containing all attendees for the event
*/
public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
+ android.util.SeempLog.record(54);
String[] attArgs = {Long.toString(eventId)};
return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */,
null /* sort order */);
@@ -1750,6 +1751,7 @@ public final class CalendarContract {
*/
public static final Cursor query(ContentResolver cr, String[] projection,
long begin, long end) {
+ android.util.SeempLog.record(54);
Uri.Builder builder = CONTENT_URI.buildUpon();
ContentUris.appendId(builder, begin);
ContentUris.appendId(builder, end);
@@ -1779,6 +1781,7 @@ public final class CalendarContract {
*/
public static final Cursor query(ContentResolver cr, String[] projection,
long begin, long end, String searchQuery) {
+ android.util.SeempLog.record(54);
Uri.Builder builder = CONTENT_SEARCH_URI.buildUpon();
ContentUris.appendId(builder, begin);
ContentUris.appendId(builder, end);
@@ -2029,6 +2032,7 @@ public final class CalendarContract {
*/
public static final Cursor query(ContentResolver cr, int startDay, int numDays,
String[] projection) {
+ android.util.SeempLog.record(54);
if (numDays < 1) {
return null;
}
@@ -2112,6 +2116,7 @@ public final class CalendarContract {
* @return A Cursor containing all reminders for the event
*/
public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
+ android.util.SeempLog.record(54);
String[] remArgs = {Long.toString(eventId)};
return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/,
null /* sort order */);
@@ -2262,6 +2267,7 @@ public final class CalendarContract {
*/
public static final Uri insert(ContentResolver cr, long eventId,
long begin, long end, long alarmTime, int minutes) {
+ android.util.SeempLog.record(51);
ContentValues values = new ContentValues();
values.put(CalendarAlerts.EVENT_ID, eventId);
values.put(CalendarAlerts.BEGIN, begin);
@@ -2289,6 +2295,7 @@ public final class CalendarContract {
* @hide
*/
public static final long findNextAlarmTime(ContentResolver cr, long millis) {
+ android.util.SeempLog.record(53);
String selection = ALARM_TIME + ">=" + millis;
// TODO: construct an explicit SQL query so that we can add
// "LIMIT 1" to the end and get just one result.
@@ -2412,6 +2419,7 @@ public final class CalendarContract {
*/
public static final boolean alarmExists(ContentResolver cr, long eventId,
long begin, long alarmTime) {
+ android.util.SeempLog.record(52);
// TODO: construct an explicit SQL query so that we can add
// "LIMIT 1" to the end and get just one result.
String[] projection = new String[] { ALARM_TIME };
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 4f880b1..3a3eca4 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -164,6 +164,10 @@ public class CallLog {
public static final int MISSED_TYPE = 3;
/** Call log type for voicemails. */
public static final int VOICEMAIL_TYPE = 4;
+ /** Call log type for blacklisted calls
+ * @hide
+ */
+ public static final int BLACKLIST_TYPE = 5;
/**
* Bit-mask describing features of the call (e.g. video).
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 8ce1cbf..0e7f487 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1119,7 +1119,15 @@ public final class ContactsContract {
public static final String SORT_KEY_ALTERNATIVE = "sort_key_alt";
}
- interface ContactCounts {
+ /**
+ * URI parameter and cursor extras that return counts of rows grouped by the
+ * address book index, which is usually the first letter of the sort key.
+ * When this parameter is supplied, the row counts are returned in the
+ * cursor extras bundle.
+ *
+ * @hide
+ */
+ public interface ContactCounts {
/**
* Add this query parameter to a URI to get back row counts grouped by the address book
@@ -1497,6 +1505,7 @@ public final class ContactsContract {
* {@link #CONTENT_LOOKUP_URI} to attempt refreshing.
*/
public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) {
+ android.util.SeempLog.record(86);
final Cursor c = resolver.query(contactUri, new String[] {
Contacts.LOOKUP_KEY, Contacts._ID
}, null, null, null);
@@ -1524,6 +1533,7 @@ public final class ContactsContract {
* provided parameters.
*/
public static Uri getLookupUri(long contactId, String lookupKey) {
+ android.util.SeempLog.record(86);
if (TextUtils.isEmpty(lookupKey)) {
return null;
}
@@ -1537,6 +1547,7 @@ public final class ContactsContract {
* Returns null if the contact cannot be found.
*/
public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) {
+ android.util.SeempLog.record(87);
if (lookupUri == null) {
return null;
}
@@ -1999,6 +2010,7 @@ public final class ContactsContract {
*/
public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri,
boolean preferHighres) {
+ android.util.SeempLog.record(88);
if (preferHighres) {
final Uri displayPhotoUri = Uri.withAppendedPath(contactUri,
Contacts.Photo.DISPLAY_PHOTO);
@@ -2046,6 +2058,7 @@ public final class ContactsContract {
* of the thumbnail the high-res picture is preferred
*/
public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
+ android.util.SeempLog.record(88);
return openContactPhotoInputStream(cr, contactUri, false);
}
}
@@ -2738,6 +2751,7 @@ public final class ContactsContract {
* entry of the given {@link RawContacts} entry.
*/
public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) {
+ android.util.SeempLog.record(89);
// TODO: use a lighter query by joining rawcontacts with contacts in provider
final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY);
final Cursor cursor = resolver.query(dataUri, new String[] {
@@ -4684,6 +4698,7 @@ public final class ContactsContract {
* </p>
*/
public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) {
+ android.util.SeempLog.record(89);
final Cursor cursor = resolver.query(dataUri, new String[] {
RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY
}, null, null, null);
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index b2d9b93..961eb19 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -593,6 +593,11 @@ public final class Downloads {
public static final int STATUS_QUEUED_FOR_WIFI = 196;
/**
+ * This download is paused by manual.
+ */
+ public static final int STATUS_PAUSED_BY_MANUAL = 197;
+
+ /**
* This download couldn't be completed due to insufficient storage
* space. Typically, this is because the SD card is full.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 87922b0..f6642d8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -64,11 +64,14 @@ import com.android.internal.widget.ILockSettings;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Pattern;
/**
* The Settings provider contains global system-level device preferences.
@@ -657,6 +660,19 @@ public final class Settings {
/**
* @hide
+ * Activity Action: Show the "app ops" details screen.
+ * <p>
+ * Input: The Intent's data URI specifies the application package name
+ * to be shown, with the "package" scheme. That is "package:com.my.app".
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_APP_OPS_DETAILS_SETTINGS =
+ "android.settings.APP_OPS_DETAILS_SETTINGS";
+
+ /**
+ * @hide
* Activity Action: Show the "app ops" settings screen.
* <p>
* Input: Nothing.
@@ -1492,6 +1508,12 @@ public final class Settings {
// At one time in System, then Global, but now back in Secure
MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
+
+ MOVED_TO_SECURE.add(System.DEV_FORCE_SHOW_NAVBAR);
+ MOVED_TO_SECURE.add(System.KEYBOARD_BRIGHTNESS);
+ MOVED_TO_SECURE.add(System.BUTTON_BRIGHTNESS);
+ MOVED_TO_SECURE.add(System.BUTTON_BACKLIGHT_TIMEOUT);
+ MOVED_TO_SECURE.add(Secure.VOLUME_LINK_NOTIFICATION);
}
private static final HashSet<String> MOVED_TO_GLOBAL;
@@ -1583,6 +1605,44 @@ public final class Settings {
}
};
+ /**
+ * Put a delimited list as a string
+ * @param resolver to access the database with
+ * @param name to store
+ * @param delimiter to split
+ * @param list to join and store
+ * @hide
+ */
+ public static void putListAsDelimitedString(ContentResolver resolver, String name,
+ String delimiter, List<String> list) {
+ String store = TextUtils.join(delimiter, list);
+ putString(resolver, name, store);
+ }
+
+ /**
+ * Get a delimited string returned as a list
+ * @param resolver to access the database with
+ * @param name to store
+ * @param delimiter to split the list with
+ * @return list of strings for a specific Settings.Secure item
+ * @hide
+ */
+ public static List<String> getDelimitedStringAsList(ContentResolver resolver, String name,
+ String delimiter) {
+ String baseString = getString(resolver, name);
+ List<String> list = new ArrayList<String>();
+ if (!TextUtils.isEmpty(baseString)) {
+ final String[] array = TextUtils.split(baseString, Pattern.quote(delimiter));
+ for (String item : array) {
+ if (TextUtils.isEmpty(item)) {
+ continue;
+ }
+ list.add(item);
+ }
+ }
+ return list;
+ }
+
/** @hide */
public static void getMovedToGlobalSettings(Set<String> outKeySet) {
outKeySet.addAll(MOVED_TO_GLOBAL);
@@ -1612,6 +1672,7 @@ public final class Settings {
/** @hide */
public static String getStringForUser(ContentResolver resolver, String name,
int userHandle) {
+ android.util.SeempLog.record(android.util.SeempLog.getSeempGetApiIdFromValue(name));
if (MOVED_TO_SECURE.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+ " to android.provider.Settings.Secure, returning read-only value.");
@@ -1639,6 +1700,7 @@ public final class Settings {
/** @hide */
public static boolean putStringForUser(ContentResolver resolver, String name, String value,
int userHandle) {
+ android.util.SeempLog.record(android.util.SeempLog.getSeempPutApiIdFromValue(name));
if (MOVED_TO_SECURE.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+ " to android.provider.Settings.Secure, value is unchanged.");
@@ -2433,6 +2495,31 @@ public final class Settings {
public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
/**
+ * The keyboard brightness to be used while the screen is on.
+ * Valid value range is between 0 and {@link PowerManager#getMaximumKeyboardBrightness()}
+ * @deprecated
+ * @hide
+ */
+ public static final String KEYBOARD_BRIGHTNESS = "keyboard_brightness";
+
+ /**
+ * The button brightness to be used while the screen is on or after a button press,
+ * depending on the value of {@link BUTTON_BACKLIGHT_TIMEOUT}.
+ * Valid value range is between 0 and {@link PowerManager#getMaximumButtonBrightness()}
+ * @deprecated
+ * @hide
+ */
+ public static final String BUTTON_BRIGHTNESS = "button_brightness";
+
+ /**
+ * The time in ms to keep the button backlight on after pressing a button.
+ * A value of 0 will keep the buttons on for as long as the screen is on.
+ * @deprecated
+ * @hide
+ */
+ public static final String BUTTON_BACKLIGHT_TIMEOUT = "button_backlight_timeout";
+
+ /**
* Control whether the process CPU usage meter should be shown.
*
* @deprecated Use {@link Global#SHOW_PROCESSES} instead
@@ -2596,6 +2683,55 @@ public final class Settings {
private static final Validator NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR = sBooleanValidator;
/**
+ * Whether the blacklisting feature for phone calls is enabled
+ * @hide
+ */
+ public static final String PHONE_BLACKLIST_ENABLED = "phone_blacklist_enabled";
+
+ /**
+ * Whether a notification should be shown when a call/message is blocked
+ * @hide
+ */
+ public static final String PHONE_BLACKLIST_NOTIFY_ENABLED = "phone_blacklist_notify_enabled";
+
+ /**
+ * Whether the blacklisting feature for phone calls from private numbers is enabled
+ * @hide
+ */
+ public static final String PHONE_BLACKLIST_PRIVATE_NUMBER_MODE = "phone_blacklist_private_number_enabled";
+
+ /**
+ * Whether the blacklisting feature for phone calls from unknown numbers is enabled
+ * @hide
+ */
+ public static final String PHONE_BLACKLIST_UNKNOWN_NUMBER_MODE = "phone_blacklist_unknown_number_enabled";
+
+ /**
+ * Constants to be used for {@link PHONE_BLACKLIST_PRIVATE_NUMBER_MODE} and
+ * {@link PHONE_BLACKLIST_UNKNOWN_NUMBER_MODE}.
+ * @hide
+ */
+ public static final int BLACKLIST_DO_NOT_BLOCK = 0;
+ /**
+ * @hide
+ */
+ public static final int BLACKLIST_BLOCK = 1;
+ /**
+ * @hide
+ */
+ public static final int BLACKLIST_PHONE_SHIFT = 0;
+ /**
+ * @hide
+ */
+ public static final int BLACKLIST_MESSAGE_SHIFT = 4;
+
+ /**
+ * Whether the regex blacklisting feature for phone calls is enabled
+ * @hide
+ */
+ public static final String PHONE_BLACKLIST_REGEX_ENABLED = "phone_blacklist_regex_enabled";
+
+ /**
* Whether silent mode should allow vibration feedback. This is used
* internally in AudioService and the Sound settings activity to
* coordinate decoupling of vibrate and silent modes. This setting
@@ -2644,6 +2780,30 @@ public final class Settings {
private static final Validator RINGTONE_VALIDATOR = sUriValidator;
/**
+ * Persistent store for the SIM-2 ringtone URI.
+ * <p>
+ * If you need to play SIM-2 ringtone at any given time, it is recommended
+ * you give {@link #DEFAULT_RINGTONE_URI_2} to the media player. It will resolve
+ * to the set default ringtone at the time of playing.
+ *
+ * @see #DEFAULT_RINGTONE_URI_2
+ * @hide
+ */
+ public static final String RINGTONE_2 = "ringtone_2";
+
+ /**
+ * Persistent store for the SIM-3 ringtone URI.
+ * <p>
+ * If you need to play SIM-3 ringtone at any given time, it is recommended
+ * you give {@link #DEFAULT_RINGTONE_URI_3} to the media player. It will resolve
+ * to the set default ringtone at the time of playing.
+ *
+ * @see #DEFAULT_RINGTONE_URI_3
+ * @hide
+ */
+ public static final String RINGTONE_3 = "ringtone_3";
+
+ /**
* A {@link Uri} that will point to the current default ringtone at any
* given time.
* <p>
@@ -2654,6 +2814,39 @@ public final class Settings {
public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE);
/**
+ * A {@link Uri} that will point to the current SIM-2 ringtone at any
+ * given time.
+ * <p>
+ * If the current default ringtone is in the DRM provider and the caller
+ * does not have permission, the exception will be a
+ * FileNotFoundException.
+ *
+ * @hide
+ */
+ public static final Uri DEFAULT_RINGTONE_URI_2 = getUriFor(RINGTONE_2);
+
+ /**
+ * A {@link Uri} that will point to the current SIM-3 ringtone at any
+ * given time.
+ * <p>
+ * If the current default ringtone is in the DRM provider and the caller
+ * does not have permission, the exception will be a
+ * FileNotFoundException.
+ *
+ * @hide
+ */
+ public static final Uri DEFAULT_RINGTONE_URI_3 = getUriFor(RINGTONE_3);
+
+ /**
+ * Maximum number of ringtones supported.
+ * <p>
+ * Maximum number of ringtones supported by settings. Increment this
+ * if a new URI needs to be added for ringtone.
+ * @hide
+ */
+ public static final int MAX_NUM_RINGTONES = 3;
+
+ /**
* Persistent store for the system-wide default notification sound.
*
* @see #RINGTONE
@@ -2723,6 +2916,15 @@ public final class Settings {
private static final Validator TEXT_AUTO_CAPS_VALIDATOR = sBooleanValidator;
/**
+ * Setting to show if system is in power off alarm mode. 1 = true, 0 = false
+ * @hide
+ */
+ public static final String POWER_OFF_ALARM_MODE = "power_off_alarm_mode";
+
+ /** Validator for POWER_OFF_ALARM_MODE */
+ private static final Validator POWER_OFF_ALARM_MODE_VALIDATOR = sBooleanValidator;
+
+ /**
* Setting to enable Auto Punctuate in text editors. 1 = On, 0 = Off. This
* feature converts two spaces to a "." and space.
*/
@@ -2788,6 +2990,14 @@ public final class Settings {
new DiscreteValueValidator(new String[] {"12", "24"});
/**
+ * Developer options - Navigation Bar show switch
+ * @deprecated Moved to CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR
+ * @hide
+ */
+ public static final String DEV_FORCE_SHOW_NAVBAR = "dev_force_show_navbar";
+
+
+ /**
* Date format string
* mm/dd/yyyy
* dd/mm/yyyy
@@ -2849,6 +3059,19 @@ public final class Settings {
public static final String ANIMATOR_DURATION_SCALE = Global.ANIMATOR_DURATION_SCALE;
/**
+ * Control the type of rotation which can be performed using the accelerometer
+ * if ACCELEROMETER_ROTATION is enabled.
+ * Value is a bitwise combination of
+ * 1 = 0 degrees (portrait)
+ * 2 = 90 degrees (left)
+ * 4 = 180 degrees (inverted portrait)
+ * 8 = 270 degrees (right)
+ * Setting to 0 is effectively orientation lock
+ * @hide
+ */
+ public static final String ACCELEROMETER_ROTATION_ANGLES = "accelerometer_rotation_angles";
+
+ /**
* Control whether the accelerometer will be used to change screen
* orientation. If 0, it will not be used unless explicitly requested
* by the application; if 1, it will be used by default unless explicitly
@@ -3183,6 +3406,63 @@ public final class Settings {
new InclusiveFloatRangeValidator(-7, 7);
/**
+ * Show icon when stylus is used?
+ * 0 = no
+ * 1 = yes
+ * @hide
+ */
+ public static final String STYLUS_ICON_ENABLED = "stylus_icon_enabled";
+
+ /**
+ * Enable Stylus Gestures
+ *
+ * @hide
+ */
+ public static final String ENABLE_STYLUS_GESTURES = "enable_stylus_gestures";
+
+ /**
+ * Left Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_LEFT_SWIPE = "gestures_left_swipe";
+
+ /**
+ * Right Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_RIGHT_SWIPE = "gestures_right_swipe";
+
+ /**
+ * Up Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_UP_SWIPE = "gestures_up_swipe";
+
+ /**
+ * down Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_DOWN_SWIPE = "gestures_down_swipe";
+
+ /**
+ * Long press Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_LONG_PRESS = "gestures_long_press";
+
+ /**
+ * double tap Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_DOUBLE_TAP = "gestures_double_tap";
+
+ /**
* Whether lock-to-app will be triggered by long-press on recents.
* @hide
*/
@@ -3219,6 +3499,44 @@ public final class Settings {
* the setting value. See an example above.
*/
+ /**
+ * Whether wifi settings will connect to access point automatically
+ * 0 = automatically
+ * 1 = manually
+ * @hide
+ */
+ public static final String WIFI_AUTO_CONNECT_TYPE = "wifi_auto_connect_type";
+
+ /**
+ * Volume keys control cursor in text fields (default is 0)
+ * 0 - Disabled
+ * 1 - Volume up/down moves cursor left/right
+ * 2 - Volume up/down moves cursor right/left
+ * @hide
+ */
+ public static final String VOLUME_KEY_CURSOR_CONTROL = "volume_key_cursor_control";
+
+ /**
+ * Whether to enable voice wakeup. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String VOICE_WAKEUP = "voice_wakeup";
+
+ /**
+ * An intent (a flattened Uri String) to launch when user voice launch
+ * action is detected. An empty or null string will launch the default
+ * voice search activity.
+ * @hide
+ */
+ public static final String VOICE_LAUNCH_INTENT = "voice_launch_intent";
+
+ /**
+ * Volume key controls ringtone or media sound stream
+ * @hide
+ */
+ public static final String VOLUME_KEYS_CONTROL_RING_STREAM =
+ "volume_keys_control_ring_stream";
+
/**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
@@ -3270,7 +3588,12 @@ public final class Settings {
VIBRATE_WHEN_RINGING,
RINGTONE,
LOCK_TO_APP_ENABLED,
- NOTIFICATION_SOUND
+ NOTIFICATION_SOUND,
+ PHONE_BLACKLIST_ENABLED,
+ PHONE_BLACKLIST_NOTIFY_ENABLED,
+ PHONE_BLACKLIST_PRIVATE_NUMBER_MODE,
+ PHONE_BLACKLIST_UNKNOWN_NUMBER_MODE,
+ PHONE_BLACKLIST_REGEX_ENABLED,
};
/**
@@ -3323,6 +3646,7 @@ public final class Settings {
PUBLIC_SETTINGS.add(SOUND_EFFECTS_ENABLED);
PUBLIC_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
PUBLIC_SETTINGS.add(SHOW_WEB_SUGGESTIONS);
+ PUBLIC_SETTINGS.add(POWER_OFF_ALARM_MODE);
}
/**
@@ -3448,6 +3772,7 @@ public final class Settings {
VALIDATORS.put(WIFI_STATIC_NETMASK, WIFI_STATIC_NETMASK_VALIDATOR);
VALIDATORS.put(WIFI_STATIC_DNS1, WIFI_STATIC_DNS1_VALIDATOR);
VALIDATORS.put(WIFI_STATIC_DNS2, WIFI_STATIC_DNS2_VALIDATOR);
+ VALIDATORS.put(POWER_OFF_ALARM_MODE, POWER_OFF_ALARM_MODE_VALIDATOR);
}
/**
@@ -3756,6 +4081,9 @@ public final class Settings {
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_VISIBLE);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_SIZE);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_DOTS_VISIBLE);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_SHOW_ERROR_PATH);
MOVED_TO_GLOBAL = new HashSet<String>();
MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
@@ -3872,6 +4200,44 @@ public final class Settings {
MOVED_TO_GLOBAL.add(Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY);
}
+ /**
+ * Put a delimited list as a string
+ * @param resolver to access the database with
+ * @param name to store
+ * @param delimiter to split
+ * @param list to join and store
+ * @hide
+ */
+ public static void putListAsDelimitedString(ContentResolver resolver, String name,
+ String delimiter, List<String> list) {
+ String store = TextUtils.join(delimiter, list);
+ putString(resolver, name, store);
+ }
+
+ /**
+ * Get a delimited string returned as a list
+ * @param resolver to access the database with
+ * @param name to store
+ * @param delimiter to split the list with
+ * @return list of strings for a specific Settings.Secure item
+ * @hide
+ */
+ public static List<String> getDelimitedStringAsList(ContentResolver resolver, String name,
+ String delimiter) {
+ String baseString = getString(resolver, name);
+ List<String> list = new ArrayList<String>();
+ if (!TextUtils.isEmpty(baseString)) {
+ final String[] array = TextUtils.split(baseString, Pattern.quote(delimiter));
+ for (String item : array) {
+ if (TextUtils.isEmpty(item)) {
+ continue;
+ }
+ list.add(item);
+ }
+ }
+ return list;
+ }
+
/** @hide */
public static void getMovedToGlobalSettings(Set<String> outKeySet) {
outKeySet.addAll(MOVED_TO_GLOBAL);
@@ -4488,6 +4854,24 @@ public final class Settings {
LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
/**
+ * Determines the width and height of the LockPatternView widget
+ * @hide
+ */
+ public static final String LOCK_PATTERN_SIZE = "lock_pattern_size";
+
+ /**
+ * Whether lock pattern will show dots (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LOCK_DOTS_VISIBLE = "lock_pattern_dotsvisible";
+
+ /**
+ * Whether lockscreen error pattern is visible (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LOCK_SHOW_ERROR_PATH = "lock_pattern_show_error_path";
+
+ /**
* This preference allows the device to be locked given time after screen goes off,
* subject to current DeviceAdmin policy limits.
* @hide
@@ -4588,6 +4972,12 @@ public final class Settings {
public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
/**
+ * Known good originating source sms addresses
+ * @hide
+ */
+ public static final String PROTECTED_SMS_ADDRESSES = "protected_sms_addresses";
+
+ /**
* Settings classname to launch when Settings is clicked from All
* Applications. Needed because of user testing between the old
* and new Settings apps.
@@ -5155,6 +5545,12 @@ public final class Settings {
"connectivity_release_pending_intent_delay_ms";
/**
+ * Whether the Wimax should be on. Only the WiMAX service should touch this.
+ * @hide
+ */
+ public static final String WIMAX_ON = "wimax_on";
+
+ /**
* Whether background data usage is allowed.
*
* @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH},
@@ -5692,6 +6088,12 @@ public final class Settings {
public static final String ASSISTANT = "assistant";
/**
+ * Default theme to use. If empty, use system.
+ * @hide
+ */
+ public static final String DEFAULT_THEME_PACKAGE = "default_theme_package";
+
+ /**
* Whether the camera launch gesture should be disabled.
*
* @hide
@@ -5708,6 +6110,12 @@ public final class Settings {
"camera_double_tap_power_gesture_disabled";
/**
+ * Boolean value whether to link ringtone and notification volume
+ * @hide
+ */
+ public static final String VOLUME_LINK_NOTIFICATION = "volume_link_notification";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -5763,7 +6171,7 @@ public final class Settings {
MOUNT_UMS_NOTIFY_ENABLED,
SLEEP_TIMEOUT,
DOUBLE_TAP_TO_WAKE,
- CAMERA_GESTURE_DISABLED,
+ CAMERA_GESTURE_DISABLED
};
/**
@@ -6177,6 +6585,14 @@ public final class Settings {
public static final String ADB_ENABLED = "adb_enabled";
/**
+ * String to contain power menu actions
+ * @deprecated Use {@link CMSettings.Secure#POWER_MENU_ACTIONS} instead
+ * @hide
+ */
+ @Deprecated
+ public static final String POWER_MENU_ACTIONS = "power_menu_actions";
+
+ /**
* Whether Views are allowed to save their attribute data.
* @hide
*/
@@ -7234,6 +7650,9 @@ public final class Settings {
BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX = "bluetooth_a2dp_sink_priority_";
/** {@hide} */
public static final String
+ BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX = "bluetooth_a2dp_src_priority_";
+ /** {@hide} */
+ public static final String
BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX = "bluetooth_input_device_priority_";
/** {@hide} */
public static final String
@@ -7336,6 +7755,14 @@ public final class Settings {
}
/**
+ * Get the key that retrieves a bluetooth a2dp src's priority.
+ * @hide
+ */
+ public static final String getBluetoothA2dpSrcPriorityKey(String address) {
+ return BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
+ }
+
+ /**
* Get the key that retrieves a bluetooth Input Device's priority.
* @hide
*/
@@ -7566,13 +7993,22 @@ public final class Settings {
/**
* Defines global runtime overrides to window policy.
*
- * See {@link com.android.server.policy.PolicyControl} for value format.
+ * See {@link android.view.WindowManagerPolicyControl} for value format.
*
* @hide
*/
public static final String POLICY_CONTROL = "policy_control";
/**
+ * Defines global runtime overrides to window policy style.
+ *
+ * See {@link android.view.WindowManagerPolicyControl} for value definitions.
+ *
+ * @hide
+ */
+ public static final String POLICY_CONTROL_STYLE = "policy_control_style";
+
+ /**
* Defines global zen mode. ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
* or ZEN_MODE_NO_INTERRUPTIONS.
*
@@ -7662,7 +8098,7 @@ public final class Settings {
public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
/**
- * Whether the Volte/VT is enabled
+ * Whether the Volte is enabled
* <p>
* Type: int (0 for false, 1 for true)
* @hide
@@ -7670,6 +8106,15 @@ public final class Settings {
public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
/**
+ * Whether VT (Video Telephony over IMS) is enabled
+ * <p>
+ * Type: int (0 for false, 1 for true)
+ *
+ * @hide
+ */
+ public static final String VT_IMS_ENABLED = "vt_ims_enabled";
+
+ /**
* Whether WFC is enabled
* <p>
* Type: int (0 for false, 1 for true)
@@ -7706,6 +8151,13 @@ public final class Settings {
public static final String LTE_SERVICE_FORCED = "lte_service_forced";
/**
+ * Whether to ignore the representation of outgoing calls set by the network.
+ *
+ * @hide
+ */
+ public static final String CONNECTED_LINE_IDENTIFICATION = "connected_line_identification";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
@@ -7752,6 +8204,7 @@ public final class Settings {
static {
MOVED_TO_SECURE = new HashSet<String>(1);
MOVED_TO_SECURE.add(Settings.Global.INSTALL_NON_MARKET_APPS);
+ MOVED_TO_SECURE.add(Settings.Global.POWER_MENU_ACTIONS);
}
/** @hide */
@@ -7760,6 +8213,44 @@ public final class Settings {
}
/**
+ * Put a delimited list as a string
+ * @param resolver to access the database with
+ * @param name to store
+ * @param delimiter to split
+ * @param list to join and store
+ * @hide
+ */
+ public static void putListAsDelimitedString(ContentResolver resolver, String name,
+ String delimiter, List<String> list) {
+ String store = TextUtils.join(delimiter, list);
+ putString(resolver, name, store);
+ }
+
+ /**
+ * Get a delimited string returned as a list
+ * @param resolver to access the database with
+ * @param name to store
+ * @param delimiter to split the list with
+ * @return list of strings for a specific Settings.Secure item
+ * @hide
+ */
+ public static List<String> getDelimitedStringAsList(ContentResolver resolver, String name,
+ String delimiter) {
+ String baseString = getString(resolver, name);
+ List<String> list = new ArrayList<String>();
+ if (!TextUtils.isEmpty(baseString)) {
+ final String[] array = TextUtils.split(baseString, Pattern.quote(delimiter));
+ for (String item : array) {
+ if (TextUtils.isEmpty(item)) {
+ continue;
+ }
+ list.add(item);
+ }
+ }
+ return list;
+ }
+
+ /**
* Look up a name in the database.
* @param resolver to access the database with
* @param name to look up in the table
@@ -7815,6 +8306,12 @@ public final class Settings {
* @return the corresponding content URI, or null if not present
*/
public static Uri getUriFor(String name) {
+ if (MOVED_TO_SECURE.contains(name)) {
+ Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global"
+ + " to android.provider.Settings.Secure, returning Secure URI.");
+ return Secure.getUriFor(Secure.CONTENT_URI, name);
+ }
+
return getUriFor(CONTENT_URI, name);
}
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index ff7cef9..c750b5e 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -42,4 +42,9 @@ public abstract class DreamManagerInternal {
* Called by the power manager to determine whether a dream is running.
*/
public abstract boolean isDreaming();
+
+ /**
+ * Called by the power manager to determine whether the dream has gone to doze mode.
+ */
+ public abstract boolean isDozing();
}
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index be3f3b3..78dda0c 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -30,7 +30,10 @@ interface IDreamManager {
ComponentName getDefaultDreamComponent();
void testDream(in ComponentName componentName);
boolean isDreaming();
+ boolean isDozing();
void finishSelf(in IBinder token, boolean immediate);
void startDozing(in IBinder token, int screenState, int screenBrightness);
void stopDozing(in IBinder token);
+ void setLidState(int state);
+ int getLidState();
}
diff --git a/core/java/android/service/gesture/IGestureService.aidl b/core/java/android/service/gesture/IGestureService.aidl
new file mode 100644
index 0000000..1944d50
--- /dev/null
+++ b/core/java/android/service/gesture/IGestureService.aidl
@@ -0,0 +1,11 @@
+package android.service.gesture;
+
+import android.app.PendingIntent;
+
+/** @hide */
+interface IGestureService {
+
+ void setOnLongPressPendingIntent(in PendingIntent pendingIntent);
+ void setOnDoubleClickPendingIntent(in PendingIntent pendingIntent);
+
+}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 88e2ede..3eb24e4 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -260,6 +260,7 @@ public class SpeechRecognizer {
* not set explicitly, default values will be used by the recognizer.
*/
public void startListening(final Intent recognizerIntent) {
+ android.util.SeempLog.record(72);
if (recognizerIntent == null) {
throw new IllegalArgumentException("intent must not be null");
}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index d8f7158..75fd2da 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1754,19 +1754,21 @@ public class TextUtils {
* Be careful: this code will need to be updated when vertical scripts will be supported
*/
public static int getLayoutDirectionFromLocale(Locale locale) {
+ boolean mirror = SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false);
if (locale != null && !locale.equals(Locale.ROOT)) {
final String scriptSubtag = ICU.addLikelySubtags(locale).getScript();
if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
- return View.LAYOUT_DIRECTION_RTL;
+ // If forcing into RTL layout mode and language is RTL
+ // return LTR as default, else RTL
+ return mirror ? View.LAYOUT_DIRECTION_LTR : View.LAYOUT_DIRECTION_RTL;
}
}
- // If forcing into RTL layout mode, return RTL as default, else LTR
- return SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false)
- ? View.LAYOUT_DIRECTION_RTL
- : View.LAYOUT_DIRECTION_LTR;
+ // If forcing into RTL layout mode and language is LTR
+ // return RTL as default, else LTR
+ return mirror ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
}
/**
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 3ed37b3..998fa9d 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -177,12 +177,23 @@ public class DateFormat {
* @hide
*/
public static boolean is24HourFormat(Context context, int userHandle) {
- String value = Settings.System.getStringForUser(context.getContentResolver(),
+ String setting = Settings.System.getStringForUser(context.getContentResolver(),
Settings.System.TIME_12_24, userHandle);
+ Locale locale = context.getResources().getConfiguration().locale;
+ return is24HourFormat(setting, locale);
+ }
- if (value == null) {
- Locale locale = context.getResources().getConfiguration().locale;
-
+ /**
+ * Returns true if user preference with the given user handle is set to 24-hour format.
+ * @param setting value of the TIME_12_24 system setting, which may be null
+ * @param locale current default locale for this device
+ * @param userHandle the user handle of the user to query.
+ * @return true if 24 hour time format is selected, false otherwise.
+ *
+ * @hide
+ */
+ public static boolean is24HourFormat(String setting, Locale locale) {
+ if (setting == null) {
synchronized (sLocaleLock) {
if (sIs24HourLocale != null && sIs24HourLocale.equals(locale)) {
return sIs24Hour;
@@ -197,23 +208,23 @@ public class DateFormat {
String pattern = sdf.toPattern();
if (pattern.indexOf('H') >= 0) {
- value = "24";
+ setting = "24";
} else {
- value = "12";
+ setting = "12";
}
} else {
- value = "12";
+ setting = "12";
}
synchronized (sLocaleLock) {
sIs24HourLocale = locale;
- sIs24Hour = value.equals("24");
+ sIs24Hour = setting.equals("24");
}
return sIs24Hour;
}
- return value.equals("24");
+ return setting.equals("24");
}
/**
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index e9db5fd..569ca60 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -23,6 +23,9 @@ import android.text.Spanned;
import android.view.KeyEvent;
import android.view.View;
import android.view.KeyCharacterMap;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
/**
* This base class encapsulates the behavior for tracking the state of
@@ -273,6 +276,14 @@ public abstract class MetaKeyKeyListener {
adjust(content, CAP);
adjust(content, ALT);
adjust(content, SYM);
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ if (getMetaState(content, META_SHIFT_ON) <= 0)
+ power.setKeyboardLight(false, 1);
+ if (getMetaState(content, META_ALT_ON) <= 0)
+ power.setKeyboardLight(false, 2);
+ } catch (RemoteException doe) {}
}
/**
@@ -325,12 +336,32 @@ public abstract class MetaKeyKeyListener {
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
press(content, CAP);
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ int state = content.getSpanFlags(CAP);
+ if (state == PRESSED || state == LOCKED) {
+ power.setKeyboardLight(true, 1);
+ } else {
+ power.setKeyboardLight(false, 1);
+ }
+ } catch (RemoteException doe) {}
return true;
}
if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
|| keyCode == KeyEvent.KEYCODE_NUM) {
press(content, ALT);
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ int state = content.getSpanFlags(ALT);
+ if (state == PRESSED || state == LOCKED) {
+ power.setKeyboardLight(true, 2);
+ } else {
+ power.setKeyboardLight(false, 2);
+ }
+ } catch (RemoteException doe) {}
return true;
}
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 9a69600..ee959e2 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,6 +16,7 @@
package android.util;
+import android.graphics.Bitmap;
import android.os.SystemProperties;
@@ -138,7 +139,20 @@ public class DisplayMetrics {
* density for a display in {@link #densityDpi}.
*/
@Deprecated
- public static int DENSITY_DEVICE = getDeviceDensity();
+ public static int DENSITY_DEVICE;
+
+ /** @hide */
+ public static int DENSITY_PREFERRED;
+
+ /** @hide */
+ public static int DENSITY_DEVICE_DEFAULT;
+
+ static {
+ DENSITY_DEVICE = SystemProperties.getInt("qemu.sf.lcd_density", SystemProperties
+ .getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
+ DENSITY_DEVICE_DEFAULT = DENSITY_DEVICE;
+ DENSITY_PREFERRED = SystemProperties.getInt("persist.sys.lcd_density", DENSITY_DEVICE);
+ }
/**
* The absolute width of the display in pixels.
@@ -229,6 +243,24 @@ public class DisplayMetrics {
*/
public float noncompatYdpi;
+ /** @hide */
+ public void setDensity(int inDensity) {
+ density = inDensity / (float) DENSITY_DEFAULT;
+ densityDpi = inDensity;
+ scaledDensity = density;
+ xdpi = inDensity;
+ ydpi = inDensity;
+
+ noncompatDensity = density;
+ noncompatDensityDpi = densityDpi;
+ noncompatScaledDensity = scaledDensity;
+ noncompatXdpi = xdpi;
+ noncompatYdpi = ydpi;
+
+ DENSITY_DEVICE = inDensity;
+ Bitmap.setDefaultDensity(inDensity);
+ }
+
public DisplayMetrics() {
}
@@ -319,13 +351,4 @@ public class DisplayMetrics {
", height=" + heightPixels + ", scaledDensity=" + scaledDensity +
", xdpi=" + xdpi + ", ydpi=" + ydpi + "}";
}
-
- private static int getDeviceDensity() {
- // qemu.sf.lcd_density can be used to override ro.sf.lcd_density
- // when running in the emulator, allowing for dynamic configurations.
- // 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", DENSITY_DEFAULT));
- }
}
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 2cc91b9..6fc8ae5 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -125,15 +125,35 @@ public class Patterns {
+ "|[1-9][0-9]|[0-9]))");
/**
+ * Match the characters without containing chinese characters
+ * @hide
+ */
+ private static final String GOOD_IRI_HOST_CHAR =
+ "a-zA-Z0-9\u00A0-\u2FFF\u3040-\u4DFF\u9FA6-\uD7FF"
+ + "\uF900-\uFDCF\uFDF0-\uFEFF";
+
+ /**
* RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets.
*/
- private static final String IRI
- = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
+ private static final String IRI =
+ "[" + GOOD_IRI_HOST_CHAR + "]([" + GOOD_IRI_HOST_CHAR + "\\-]{0,61}["
+ + GOOD_IRI_HOST_CHAR + "]){0,1}";
private static final String GOOD_GTLD_CHAR =
- "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+ "a-zA-Z\u00A0-\u2FFF\u3040-\u4DFF\u9FA6-\uD7FF"
+ + "\uF900-\uFDCF\uFDF0-\uFEFF";
private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
+ // Halfwidth and fullwidth forms
+ private static final String HALF_FULL_WIDTH_CHAR = "\uFF00-\uFFEF";
+ // Symbols and punctuation
+ private static final String SYMBOLS_PUNCTUATION_CHAR = "\u3000-\u303F";
+ // Chinese characters
+ private static final String CHINESE_CHAR = "\u4E00-\u9FA5";
+ // Forbidden characters, should remove from URL,
+ private static final String FORBIDDEN_CHAR =
+ "[" + SYMBOLS_PUNCTUATION_CHAR + CHINESE_CHAR
+ + HALF_FULL_WIDTH_CHAR + "]";
public static final Pattern DOMAIN_NAME
= Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
@@ -149,11 +169,15 @@ public class Patterns {
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "(?:" + DOMAIN_NAME + ")"
+ "(?:\\:\\d{1,5})?)" // plus option port number
- + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
- + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
- + "(?:\\b|$)"); // and finally, a word boundary or end of
- // input. This is to stop foo.sure from
- // matching as foo.su
+ + "(\\/(?:(?:[" + GOOD_IRI_HOST_CHAR
+ + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
+ + "\\-\\.\\+\\!\\*\\'\\(\\)\\_])|(?:\\,[" + GOOD_IRI_HOST_CHAR
+ + "])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ + "(?:(?=" + FORBIDDEN_CHAR
+ + ")|\\b|$)");
+ // and finally, a word boundary or end of input. This is to stop
+ // foo.sure from matching as foo.su
+ // also should remove forbidden characters from end of URL.
public static final Pattern EMAIL_ADDRESS
= Pattern.compile(
diff --git a/core/java/android/util/SeempLog.java b/core/java/android/util/SeempLog.java
new file mode 100644
index 0000000..6e6cce6
--- /dev/null
+++ b/core/java/android/util/SeempLog.java
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package android.util;
+
+import com.android.internal.os.RuntimeInit;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.UnknownHostException;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.List;
+import java.util.Iterator;
+import android.util.Log;
+import android.provider.Settings;
+
+/**
+ * SeempLog
+ *
+ * @hide
+ */
+public final class SeempLog {
+ private SeempLog() {
+ }
+
+ /**
+ * Send a log message to the seemp log.
+ * @param api The api triggering this message.
+ */
+ public static int record(int api) {
+ return seemp_println_native(api, "");
+ }
+
+ /**
+ * Send a log message to the seemp log.
+ * @param api The api triggering this message.
+ * @param msg The message you would like logged.
+ */
+ public static int record_str(int api, String msg) {
+ if ( msg != null ) {
+ return seemp_println_native(api, msg);
+ }
+ else {
+ return seemp_println_native(api, "");
+ }
+ }
+
+ public static int record_sensor(int api,
+ android.hardware.Sensor sensor) {
+ if ( sensor != null ) {
+ return seemp_println_native(api, "sensor="+sensor.getType());
+ }
+ else {
+ return seemp_println_native(api, "sensor=-1");
+ }
+ }
+
+ public static int record_sensor_rate(int api,
+ android.hardware.Sensor sensor, int rate) {
+ if ( sensor != null ) {
+ return seemp_println_native(api,
+ "sensor="+sensor.getType() + ",rate="+rate);
+ }
+ else {
+ return seemp_println_native(api, "sensor=-1,rate=" + rate);
+ }
+ }
+
+ public static int record_uri(int api, android.net.Uri uri) {
+ if ( uri != null ) {
+ return seemp_println_native(api, "uri, " + uri.toString());
+ }
+ else {
+ return seemp_println_native(api, "uri, null" );
+ }
+ }
+
+ public static int record_vg_layout(int api,
+ android.view.ViewGroup.LayoutParams params) {
+ try {
+ android.view.WindowManager.LayoutParams p =
+ (android.view.WindowManager.LayoutParams) params;
+ if ( p != null ) {
+ return seemp_println_native(api,
+ "window_type=" + p.type + ",window_flag=" + p.flags);
+ }
+ else {
+ return seemp_println_native(api, "");
+ }
+ } catch (ClassCastException cce) {
+ return seemp_println_native(api, "");
+ }
+ }
+
+ /** @hide */ public static native int seemp_println_native(int api, String msg);
+
+ public static final int SEEMP_API_android_provider_Settings__get_ANDROID_ID_ = 7;
+ public static final int SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_ = 96;
+ public static final int SEEMP_API_android_provider_Settings__get_USER_ROTATION_ = 97;
+ public static final int SEEMP_API_android_provider_Settings__get_ADB_ENABLED_ = 98;
+ public static final int SEEMP_API_android_provider_Settings__get_DEBUG_APP_ = 99;
+ public static final int SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_ = 100;
+ public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_ = 101;
+ public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_ = 102;
+ public static final int SEEMP_API_android_provider_Settings__get_ALARM_ALERT_ = 103;
+ public static final int SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_ = 104;
+ public static final int SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_ = 105;
+ public static final int SEEMP_API_android_provider_Settings__get_LOGGING_ID_ = 106;
+ public static final int SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_ = 107;
+ public static final int SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_ = 108;
+ public static final int SEEMP_API_android_provider_Settings__get_FONT_SCALE_ = 109;
+ public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_ = 110;
+ public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_ = 111;
+ public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 112;
+ public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 113;
+ public static final int SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_ = 114;
+ public static final int SEEMP_API_android_provider_Settings__get_DIM_SCREEN_ = 115;
+ public static final int SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_ = 116;
+ public static final int SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_ = 117;
+ public static final int SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_ = 118;
+ public static final int SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_ = 119;
+ public static final int SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_ = 120;
+ public static final int SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_ = 121;
+ public static final int SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_ = 122;
+ public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ = 123;
+ public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_ = 124;
+ public static final int SEEMP_API_android_provider_Settings__get_DATE_FORMAT_ = 125;
+ public static final int SEEMP_API_android_provider_Settings__get_TIME_12_24_ = 126;
+ public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_ = 127;
+ public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 128;
+ public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_ = 129;
+ public static final int SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_ = 130;
+ public static final int SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_ = 131;
+ public static final int SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_ = 132;
+ public static final int SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_ = 133;
+ public static final int SEEMP_API_android_provider_Settings__get_RINGTONE_ = 134;
+ public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_ = 135;
+ public static final int SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_ = 136;
+ public static final int SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_ = 137;
+ public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_ = 138;
+ public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 139;
+ public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_ = 140;
+ public static final int SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_ = 141;
+ public static final int SEEMP_API_android_provider_Settings__get_DATA_ROAMING_ = 142;
+ public static final int SEEMP_API_android_provider_Settings__get_HTTP_PROXY_ = 143;
+ public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_ = 144;
+ public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_ = 145;
+ public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_ = 146;
+ public static final int SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_ = 147;
+ public static final int SEEMP_API_android_provider_Settings__get_RADIO_CELL_ = 148;
+ public static final int SEEMP_API_android_provider_Settings__get_RADIO_NFC_ = 149;
+ public static final int SEEMP_API_android_provider_Settings__get_RADIO_WIFI_ = 150;
+ public static final int SEEMP_API_android_provider_Settings__get_SYS_PROP_SETTING_VERSION_ = 151;
+ public static final int SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_ = 152;
+ public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_ = 153;
+ public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_ = 154;
+ public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_ = 155;
+ public static final int SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_ = 156;
+ public static final int SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_ = 157;
+ public static final int SEEMP_API_android_provider_Settings__get_VIBRATE_ON_ = 158;
+ public static final int SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_ = 159;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_ = 160;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_ = 161;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_ = 162;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_ = 163;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_RING_ = 164;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_ = 165;
+ public static final int SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_ = 166;
+ public static final int SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_ = 167;
+ public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_ = 168;
+ public static final int SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_ = 169;
+ public static final int SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_ = 170;
+ public static final int SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_ = 171;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_ = 172;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 173;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 174;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 175;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 176;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_ON_ = 177;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_ = 178;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_DEFAULT_ = 179;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_ = 180;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 181;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_ = 182;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_ = 183;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_ = 184;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_ = 185;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_ = 186;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_ = 187;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 188;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_ = 189;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 190;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 191;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 192;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 193;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 194;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_ = 195;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_ = 196;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_ = 197;
+ public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 198;
+ public static final int SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_ = 199;
+ public static final int SEEMP_API_android_provider_Settings__put_USER_ROTATION_ = 200;
+ public static final int SEEMP_API_android_provider_Settings__put_ADB_ENABLED_ = 201;
+ public static final int SEEMP_API_android_provider_Settings__put_DEBUG_APP_ = 202;
+ public static final int SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_ = 203;
+ public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_ = 204;
+ public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_ = 205;
+ public static final int SEEMP_API_android_provider_Settings__put_ALARM_ALERT_ = 206;
+ public static final int SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_ = 207;
+ public static final int SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_ = 208;
+ public static final int SEEMP_API_android_provider_Settings__put_ANDROID_ID_ = 209;
+ public static final int SEEMP_API_android_provider_Settings__put_LOGGING_ID_ = 210;
+ public static final int SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_ = 211;
+ public static final int SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_ = 212;
+ public static final int SEEMP_API_android_provider_Settings__put_FONT_SCALE_ = 213;
+ public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_ = 214;
+ public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_ = 215;
+ public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 216;
+ public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 217;
+ public static final int SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_ = 218;
+ public static final int SEEMP_API_android_provider_Settings__put_DIM_SCREEN_ = 219;
+ public static final int SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_ = 220;
+ public static final int SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_ = 221;
+ public static final int SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_ = 222;
+ public static final int SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_ = 223;
+ public static final int SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_ = 224;
+ public static final int SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_ = 225;
+ public static final int SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_ = 226;
+ public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ = 227;
+ public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_ = 228;
+ public static final int SEEMP_API_android_provider_Settings__put_DATE_FORMAT_ = 229;
+ public static final int SEEMP_API_android_provider_Settings__put_TIME_12_24_ = 230;
+ public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_ = 231;
+ public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 232;
+ public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_ = 233;
+ public static final int SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_ = 234;
+ public static final int SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_ = 235;
+ public static final int SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_ = 236;
+ public static final int SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_ = 237;
+ public static final int SEEMP_API_android_provider_Settings__put_RINGTONE_ = 238;
+ public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_ = 239;
+ public static final int SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_ = 240;
+ public static final int SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_ = 241;
+ public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_ = 242;
+ public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 243;
+ public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_ = 244;
+ public static final int SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_ = 245;
+ public static final int SEEMP_API_android_provider_Settings__put_DATA_ROAMING_ = 246;
+ public static final int SEEMP_API_android_provider_Settings__put_HTTP_PROXY_ = 247;
+ public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_ = 248;
+ public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_ = 249;
+ public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_ = 250;
+ public static final int SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_ = 251;
+ public static final int SEEMP_API_android_provider_Settings__put_RADIO_CELL_ = 252;
+ public static final int SEEMP_API_android_provider_Settings__put_RADIO_NFC_ = 253;
+ public static final int SEEMP_API_android_provider_Settings__put_RADIO_WIFI_ = 254;
+ public static final int SEEMP_API_android_provider_Settings__put_SYS_PROP_SETTING_VERSION_ = 255;
+ public static final int SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_ = 256;
+ public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_ = 257;
+ public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_ = 258;
+ public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_ = 259;
+ public static final int SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_ = 260;
+ public static final int SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_ = 261;
+ public static final int SEEMP_API_android_provider_Settings__put_VIBRATE_ON_ = 262;
+ public static final int SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_ = 263;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_ = 264;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_ = 265;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_ = 266;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_ = 267;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_RING_ = 268;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_ = 269;
+ public static final int SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_ = 270;
+ public static final int SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_ = 271;
+ public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_ = 272;
+ public static final int SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_ = 273;
+ public static final int SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_ = 274;
+ public static final int SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_ = 275;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_ = 276;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 277;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 278;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 279;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 280;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_ON_ = 281;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_ = 282;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_DEFAULT_ = 283;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_ = 284;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 285;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_ = 286;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_ = 287;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_ = 288;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_ = 289;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_ = 290;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_ = 291;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 292;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_ = 293;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 294;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 295;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 296;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 297;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 298;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_ = 299;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_ = 300;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_ = 301;
+ public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 302;
+
+ private final static java.util.Map<String,Integer> value_to_get_map;
+ static {
+ value_to_get_map = new java.util.HashMap<String,Integer>( 198 );
+ value_to_get_map.put(Settings.System.NOTIFICATION_SOUND,
+ SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_);
+ value_to_get_map.put(Settings.System.DTMF_TONE_WHEN_DIALING,
+ SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_);
+ value_to_get_map.put(Settings.System.LOCK_PATTERN_ENABLED,
+ SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_);
+ value_to_get_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT,
+ SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_);
+ value_to_get_map.put(Settings.System.AUTO_TIME,
+ SEEMP_API_android_provider_Settings__get_AUTO_TIME_);
+ value_to_get_map.put(Settings.System.SETUP_WIZARD_HAS_RUN,
+ SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_);
+ value_to_get_map.put(Settings.System.SYS_PROP_SETTING_VERSION,
+ SEEMP_API_android_provider_Settings__get_SYS_PROP_SETTING_VERSION_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_);
+ value_to_get_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED,
+ SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_);
+ value_to_get_map.put(Settings.System.ALARM_ALERT,
+ SEEMP_API_android_provider_Settings__get_ALARM_ALERT_);
+ value_to_get_map.put(Settings.System.VIBRATE_ON,
+ SEEMP_API_android_provider_Settings__get_VIBRATE_ON_);
+ value_to_get_map.put(Settings.System.USB_MASS_STORAGE_ENABLED,
+ SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_);
+ value_to_get_map.put(Settings.System.FONT_SCALE,
+ SEEMP_API_android_provider_Settings__get_FONT_SCALE_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_);
+ value_to_get_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES,
+ SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_);
+ value_to_get_map.put(Settings.System.ACCELEROMETER_ROTATION,
+ SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_);
+ value_to_get_map.put(Settings.System.VOLUME_NOTIFICATION,
+ SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_);
+ value_to_get_map.put(Settings.System.AIRPLANE_MODE_ON,
+ SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_);
+ value_to_get_map.put(Settings.System.WIFI_STATIC_IP,
+ SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_);
+ value_to_get_map.put(Settings.System.RADIO_BLUETOOTH,
+ SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_);
+ value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT,
+ SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_);
+ value_to_get_map.put(Settings.System.VOLUME_RING,
+ SEEMP_API_android_provider_Settings__get_VOLUME_RING_);
+ value_to_get_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_);
+ value_to_get_map.put(Settings.System.VOLUME_SYSTEM,
+ SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_);
+ value_to_get_map.put(Settings.System.SCREEN_OFF_TIMEOUT,
+ SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_);
+ value_to_get_map.put(Settings.System.RADIO_WIFI,
+ SEEMP_API_android_provider_Settings__get_RADIO_WIFI_);
+ value_to_get_map.put(Settings.System.AUTO_TIME_ZONE,
+ SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_);
+ value_to_get_map.put(Settings.System.TEXT_AUTO_CAPS,
+ SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_);
+ value_to_get_map.put(Settings.System.WALLPAPER_ACTIVITY,
+ SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_);
+ value_to_get_map.put(Settings.System.ANIMATOR_DURATION_SCALE,
+ SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_);
+ value_to_get_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT,
+ SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_);
+ value_to_get_map.put(Settings.System.LOCK_PATTERN_VISIBLE,
+ SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_);
+ value_to_get_map.put(Settings.System.VOLUME_VOICE,
+ SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_);
+ value_to_get_map.put(Settings.System.DEBUG_APP,
+ SEEMP_API_android_provider_Settings__get_DEBUG_APP_);
+ value_to_get_map.put(Settings.System.WIFI_ON,
+ SEEMP_API_android_provider_Settings__get_WIFI_ON_);
+ value_to_get_map.put(Settings.System.TEXT_SHOW_PASSWORD,
+ SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_);
+ value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+ SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_);
+ value_to_get_map.put(Settings.System.WIFI_SLEEP_POLICY,
+ SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_);
+ value_to_get_map.put(Settings.System.VOLUME_MUSIC,
+ SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_);
+ value_to_get_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE,
+ SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_);
+ value_to_get_map.put(Settings.System.DEVICE_PROVISIONED,
+ SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_);
+ value_to_get_map.put(Settings.System.HTTP_PROXY,
+ SEEMP_API_android_provider_Settings__get_HTTP_PROXY_);
+ value_to_get_map.put(Settings.System.ANDROID_ID,
+ SEEMP_API_android_provider_Settings__get_ANDROID_ID_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_);
+ value_to_get_map.put(Settings.System.END_BUTTON_BEHAVIOR,
+ SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_);
+ value_to_get_map.put(Settings.System.NEXT_ALARM_FORMATTED,
+ SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_);
+ value_to_get_map.put(Settings.System.RADIO_CELL,
+ SEEMP_API_android_provider_Settings__get_RADIO_CELL_);
+ value_to_get_map.put(Settings.System.PARENTAL_CONTROL_ENABLED,
+ SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_);
+ value_to_get_map.put(Settings.System.BLUETOOTH_ON,
+ SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_);
+ value_to_get_map.put(Settings.System.WINDOW_ANIMATION_SCALE,
+ SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_);
+ value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY,
+ SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_);
+ value_to_get_map.put(Settings.System.WIFI_STATIC_DNS1,
+ SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_);
+ value_to_get_map.put(Settings.System.WIFI_STATIC_DNS2,
+ SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_);
+ value_to_get_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_);
+ value_to_get_map.put(Settings.System.SHOW_WEB_SUGGESTIONS,
+ SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_);
+ value_to_get_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL,
+ SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_);
+ value_to_get_map.put(Settings.System.DATE_FORMAT,
+ SEEMP_API_android_provider_Settings__get_DATE_FORMAT_);
+ value_to_get_map.put(Settings.System.RADIO_NFC,
+ SEEMP_API_android_provider_Settings__get_RADIO_NFC_);
+ value_to_get_map.put(Settings.System.AIRPLANE_MODE_RADIOS,
+ SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_);
+ value_to_get_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+ SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_);
+ value_to_get_map.put(Settings.System.TIME_12_24,
+ SEEMP_API_android_provider_Settings__get_TIME_12_24_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_);
+ value_to_get_map.put(Settings.System.VOLUME_BLUETOOTH_SCO,
+ SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_);
+ value_to_get_map.put(Settings.System.USER_ROTATION,
+ SEEMP_API_android_provider_Settings__get_USER_ROTATION_);
+ value_to_get_map.put(Settings.System.WIFI_STATIC_GATEWAY,
+ SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_);
+ value_to_get_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN,
+ SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_);
+ value_to_get_map.put(Settings.System.SOUND_EFFECTS_ENABLED,
+ SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_);
+ value_to_get_map.put(Settings.System.DATA_ROAMING,
+ SEEMP_API_android_provider_Settings__get_DATA_ROAMING_);
+ value_to_get_map.put(Settings.System.SETTINGS_CLASSNAME,
+ SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_);
+ value_to_get_map.put(Settings.System.TRANSITION_ANIMATION_SCALE,
+ SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_);
+ value_to_get_map.put(Settings.System.WAIT_FOR_DEBUGGER,
+ SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_);
+ value_to_get_map.put(Settings.System.INSTALL_NON_MARKET_APPS,
+ SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_);
+ value_to_get_map.put(Settings.System.ADB_ENABLED,
+ SEEMP_API_android_provider_Settings__get_ADB_ENABLED_);
+ value_to_get_map.put(Settings.System.WIFI_USE_STATIC_IP,
+ SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_);
+ value_to_get_map.put(Settings.System.DIM_SCREEN,
+ SEEMP_API_android_provider_Settings__get_DIM_SCREEN_);
+ value_to_get_map.put(Settings.System.VOLUME_ALARM,
+ SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ON,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_);
+ value_to_get_map.put(Settings.System.WIFI_STATIC_NETMASK,
+ SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_);
+ value_to_get_map.put(Settings.System.NETWORK_PREFERENCE,
+ SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_);
+ value_to_get_map.put(Settings.System.SHOW_PROCESSES,
+ SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_);
+ value_to_get_map.put(Settings.System.TEXT_AUTO_REPLACE,
+ SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_);
+ value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+ SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_);
+ value_to_get_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE,
+ SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_);
+ value_to_get_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS,
+ SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_);
+ value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS,
+ SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_);
+ value_to_get_map.put(Settings.System.USE_GOOGLE_MAIL,
+ SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_);
+ value_to_get_map.put(Settings.System.RINGTONE,
+ SEEMP_API_android_provider_Settings__get_RINGTONE_);
+ value_to_get_map.put(Settings.System.LOGGING_ID,
+ SEEMP_API_android_provider_Settings__get_LOGGING_ID_);
+ value_to_get_map.put(Settings.System.MODE_RINGER,
+ SEEMP_API_android_provider_Settings__get_MODE_RINGER_);
+ value_to_get_map.put(Settings.System.MUTE_STREAMS_AFFECTED,
+ SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_);
+ value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE,
+ SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_);
+ value_to_get_map.put(Settings.System.TEXT_AUTO_PUNCTUATE,
+ SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_);
+ value_to_get_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS,
+ SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_);
+ value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE,
+ SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_);
+ }
+
+ public static int getSeempGetApiIdFromValue( String v )
+ {
+ Integer result = value_to_get_map.get( v );
+ if (result == null)
+ {
+ result = -1;
+ }
+ return result;
+ }
+
+ private final static java.util.Map<String,Integer> value_to_put_map;
+ static {
+ value_to_put_map = new java.util.HashMap<String,Integer>( 198 );
+ value_to_put_map.put(Settings.System.NOTIFICATION_SOUND,
+ SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_);
+ value_to_put_map.put(Settings.System.DTMF_TONE_WHEN_DIALING,
+ SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_);
+ value_to_put_map.put(Settings.System.LOCK_PATTERN_ENABLED,
+ SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_);
+ value_to_put_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT,
+ SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_);
+ value_to_put_map.put(Settings.System.AUTO_TIME,
+ SEEMP_API_android_provider_Settings__put_AUTO_TIME_);
+ value_to_put_map.put(Settings.System.SETUP_WIZARD_HAS_RUN,
+ SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_);
+ value_to_put_map.put(Settings.System.SYS_PROP_SETTING_VERSION,
+ SEEMP_API_android_provider_Settings__put_SYS_PROP_SETTING_VERSION_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_);
+ value_to_put_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED,
+ SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_);
+ value_to_put_map.put(Settings.System.ALARM_ALERT,
+ SEEMP_API_android_provider_Settings__put_ALARM_ALERT_);
+ value_to_put_map.put(Settings.System.VIBRATE_ON,
+ SEEMP_API_android_provider_Settings__put_VIBRATE_ON_);
+ value_to_put_map.put(Settings.System.USB_MASS_STORAGE_ENABLED,
+ SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_);
+ value_to_put_map.put(Settings.System.FONT_SCALE,
+ SEEMP_API_android_provider_Settings__put_FONT_SCALE_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_);
+ value_to_put_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES,
+ SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_);
+ value_to_put_map.put(Settings.System.ACCELEROMETER_ROTATION,
+ SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_);
+ value_to_put_map.put(Settings.System.VOLUME_NOTIFICATION,
+ SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_);
+ value_to_put_map.put(Settings.System.AIRPLANE_MODE_ON,
+ SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_);
+ value_to_put_map.put(Settings.System.WIFI_STATIC_IP,
+ SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_);
+ value_to_put_map.put(Settings.System.RADIO_BLUETOOTH,
+ SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_);
+ value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT,
+ SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_);
+ value_to_put_map.put(Settings.System.VOLUME_RING,
+ SEEMP_API_android_provider_Settings__put_VOLUME_RING_);
+ value_to_put_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_);
+ value_to_put_map.put(Settings.System.VOLUME_SYSTEM,
+ SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_);
+ value_to_put_map.put(Settings.System.SCREEN_OFF_TIMEOUT,
+ SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_);
+ value_to_put_map.put(Settings.System.RADIO_WIFI,
+ SEEMP_API_android_provider_Settings__put_RADIO_WIFI_);
+ value_to_put_map.put(Settings.System.AUTO_TIME_ZONE,
+ SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_);
+ value_to_put_map.put(Settings.System.TEXT_AUTO_CAPS,
+ SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_);
+ value_to_put_map.put(Settings.System.WALLPAPER_ACTIVITY,
+ SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_);
+ value_to_put_map.put(Settings.System.ANIMATOR_DURATION_SCALE,
+ SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_);
+ value_to_put_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT,
+ SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_);
+ value_to_put_map.put(Settings.System.LOCK_PATTERN_VISIBLE,
+ SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_);
+ value_to_put_map.put(Settings.System.VOLUME_VOICE,
+ SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_);
+ value_to_put_map.put(Settings.System.DEBUG_APP,
+ SEEMP_API_android_provider_Settings__put_DEBUG_APP_);
+ value_to_put_map.put(Settings.System.WIFI_ON,
+ SEEMP_API_android_provider_Settings__put_WIFI_ON_);
+ value_to_put_map.put(Settings.System.TEXT_SHOW_PASSWORD,
+ SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_);
+ value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+ SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_);
+ value_to_put_map.put(Settings.System.WIFI_SLEEP_POLICY,
+ SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_);
+ value_to_put_map.put(Settings.System.VOLUME_MUSIC,
+ SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_);
+ value_to_put_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE,
+ SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_);
+ value_to_put_map.put(Settings.System.DEVICE_PROVISIONED,
+ SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_);
+ value_to_put_map.put(Settings.System.HTTP_PROXY,
+ SEEMP_API_android_provider_Settings__put_HTTP_PROXY_);
+ value_to_put_map.put(Settings.System.ANDROID_ID,
+ SEEMP_API_android_provider_Settings__put_ANDROID_ID_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_);
+ value_to_put_map.put(Settings.System.END_BUTTON_BEHAVIOR,
+ SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_);
+ value_to_put_map.put(Settings.System.NEXT_ALARM_FORMATTED,
+ SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_);
+ value_to_put_map.put(Settings.System.RADIO_CELL,
+ SEEMP_API_android_provider_Settings__put_RADIO_CELL_);
+ value_to_put_map.put(Settings.System.PARENTAL_CONTROL_ENABLED,
+ SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_);
+ value_to_put_map.put(Settings.System.BLUETOOTH_ON,
+ SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_);
+ value_to_put_map.put(Settings.System.WINDOW_ANIMATION_SCALE,
+ SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_);
+ value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY,
+ SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_);
+ value_to_put_map.put(Settings.System.WIFI_STATIC_DNS1,
+ SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_);
+ value_to_put_map.put(Settings.System.WIFI_STATIC_DNS2,
+ SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_);
+ value_to_put_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_);
+ value_to_put_map.put(Settings.System.SHOW_WEB_SUGGESTIONS,
+ SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_);
+ value_to_put_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL,
+ SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_);
+ value_to_put_map.put(Settings.System.DATE_FORMAT,
+ SEEMP_API_android_provider_Settings__put_DATE_FORMAT_);
+ value_to_put_map.put(Settings.System.RADIO_NFC,
+ SEEMP_API_android_provider_Settings__put_RADIO_NFC_);
+ value_to_put_map.put(Settings.System.AIRPLANE_MODE_RADIOS,
+ SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_);
+ value_to_put_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+ SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_);
+ value_to_put_map.put(Settings.System.TIME_12_24,
+ SEEMP_API_android_provider_Settings__put_TIME_12_24_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_);
+ value_to_put_map.put(Settings.System.VOLUME_BLUETOOTH_SCO,
+ SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_);
+ value_to_put_map.put(Settings.System.USER_ROTATION,
+ SEEMP_API_android_provider_Settings__put_USER_ROTATION_);
+ value_to_put_map.put(Settings.System.WIFI_STATIC_GATEWAY,
+ SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_);
+ value_to_put_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN,
+ SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_);
+ value_to_put_map.put(Settings.System.SOUND_EFFECTS_ENABLED,
+ SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_);
+ value_to_put_map.put(Settings.System.DATA_ROAMING,
+ SEEMP_API_android_provider_Settings__put_DATA_ROAMING_);
+ value_to_put_map.put(Settings.System.SETTINGS_CLASSNAME,
+ SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_);
+ value_to_put_map.put(Settings.System.TRANSITION_ANIMATION_SCALE,
+ SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_);
+ value_to_put_map.put(Settings.System.WAIT_FOR_DEBUGGER,
+ SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_);
+ value_to_put_map.put(Settings.System.INSTALL_NON_MARKET_APPS,
+ SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_);
+ value_to_put_map.put(Settings.System.ADB_ENABLED,
+ SEEMP_API_android_provider_Settings__put_ADB_ENABLED_);
+ value_to_put_map.put(Settings.System.WIFI_USE_STATIC_IP,
+ SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_);
+ value_to_put_map.put(Settings.System.DIM_SCREEN,
+ SEEMP_API_android_provider_Settings__put_DIM_SCREEN_);
+ value_to_put_map.put(Settings.System.VOLUME_ALARM,
+ SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ON,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_);
+ value_to_put_map.put(Settings.System.WIFI_STATIC_NETMASK,
+ SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_);
+ value_to_put_map.put(Settings.System.NETWORK_PREFERENCE,
+ SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_);
+ value_to_put_map.put(Settings.System.SHOW_PROCESSES,
+ SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_);
+ value_to_put_map.put(Settings.System.TEXT_AUTO_REPLACE,
+ SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_);
+ value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+ SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_);
+ value_to_put_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE,
+ SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_);
+ value_to_put_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS,
+ SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_);
+ value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS,
+ SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_);
+ value_to_put_map.put(Settings.System.USE_GOOGLE_MAIL,
+ SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_);
+ value_to_put_map.put(Settings.System.RINGTONE,
+ SEEMP_API_android_provider_Settings__put_RINGTONE_);
+ value_to_put_map.put(Settings.System.LOGGING_ID,
+ SEEMP_API_android_provider_Settings__put_LOGGING_ID_);
+ value_to_put_map.put(Settings.System.MODE_RINGER,
+ SEEMP_API_android_provider_Settings__put_MODE_RINGER_);
+ value_to_put_map.put(Settings.System.MUTE_STREAMS_AFFECTED,
+ SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_);
+ value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE,
+ SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_);
+ value_to_put_map.put(Settings.System.TEXT_AUTO_PUNCTUATE,
+ SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_);
+ value_to_put_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS,
+ SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_);
+ value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE,
+ SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_);
+ }
+
+ public static int getSeempPutApiIdFromValue( String v )
+ {
+ Integer result = value_to_put_map.get( v );
+ if (result == null)
+ {
+ result = -1;
+ }
+ return result;
+ }
+}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 1269ad9..7b2d299 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -778,6 +778,9 @@ public final class Display {
synchronized (this) {
updateDisplayInfoLocked();
mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments);
+ if (getDisplayId() == DEFAULT_DISPLAY) {
+ outMetrics.densityDpi = DisplayMetrics.DENSITY_DEVICE_DEFAULT;
+ }
}
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index ee76274..d43b962 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -564,6 +564,9 @@ public final class DisplayInfo implements Parcelable {
if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
compatInfo.applyToDisplayMetrics(outMetrics);
+ } else if (type == Display.TYPE_BUILT_IN
+ && (flags & Display.FLAG_PRESENTATION) == 0) {
+ outMetrics.setDensity(DisplayMetrics.DENSITY_PREFERRED);
}
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5994d4f..55735c7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -130,7 +130,7 @@ interface IWindowManager
boolean inKeyguardRestrictedInputMode();
void dismissKeyguard();
void keyguardGoingAway(boolean disableWindowAnimations,
- boolean keyguardGoingToNotificationShade);
+ boolean keyguardGoingToNotificationShade, boolean keyguardShowingMedia);
void closeSystemDialogs(String reason);
@@ -232,6 +232,16 @@ interface IWindowManager
Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth, int maxHeight);
/**
+ * Get the current x offset for the wallpaper
+ */
+ int getLastWallpaperX();
+
+ /**
+ * Get the current y offset for the wallpaper
+ */
+ int getLastWallpaperY();
+
+ /**
* Called by the status bar to notify Views of changes to System UI visiblity.
*/
oneway void statusBarVisibilityChanged(int visibility);
@@ -240,6 +250,12 @@ interface IWindowManager
* Device has a software navigation bar (separate from the status bar).
*/
boolean hasNavigationBar();
+ boolean hasPermanentMenuKey();
+
+ /**
+ * Device needs a software navigation bar (because it has no hardware keys).
+ */
+ boolean needsNavigationBar();
/**
* Lock the device immediately with the specified options (can be null).
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 73b4a6e..3956237 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -185,6 +185,16 @@ interface IWindowSession {
*/
void setWallpaperDisplayOffset(IBinder windowToken, int x, int y);
+ /**
+ * Get the current x offset for the wallpaper
+ */
+ int getLastWallpaperX();
+
+ /**
+ * Get the current y offset for the wallpaper
+ */
+ int getLastWallpaperY();
+
Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, in Bundle extras, boolean sync);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 5592f7a..5f88c11 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -281,6 +281,18 @@ public final class InputDevice implements Parcelable {
public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON;
/**
+ * The input source is a touch device whose motions should be interpreted as gestures.
+ *
+ * For example, an upward swipe should be treated the same as a swipe of the touchscreen.
+ * The same should apply for left, right, down swipes. Complex gestures may also be input.
+ *
+ * @see #SOURCE_CLASS_NONE
+ *
+ * @hide
+ */
+ public static final int SOURCE_GESTURE_SENSOR = 0x10000000 | SOURCE_CLASS_NONE;
+
+ /**
* A special input source constant that is used when filtering input devices
* to match devices that provide any type of input source.
*/
@@ -957,6 +969,7 @@ public final class InputDevice implements Parcelable {
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
+ appendSourceDescriptionIfApplicable(description, SOURCE_GESTURE_SENSOR, "gesture");
description.append(" )\n");
final int numAxes = mMotionRanges.size();
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 19d5c73..d128288 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1844,8 +1844,14 @@ public class KeyEvent extends InputEvent implements Parcelable {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
+ case KeyEvent.KEYCODE_HOME:
case KeyEvent.KEYCODE_WAKEUP:
case KeyEvent.KEYCODE_PAIRING:
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_FOCUS:
case KeyEvent.KEYCODE_STEM_1:
case KeyEvent.KEYCODE_STEM_2:
case KeyEvent.KEYCODE_STEM_3:
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bcf9b2c..e839468 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -58,6 +58,11 @@ public class SurfaceControl {
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
private static native void nativeSetLayerStack(long nativeObject, int layerStack);
+ private static native void nativeSetBlur(long nativeObject, float blur);
+ private static native void nativeSetBlurMaskSurface(long nativeObject, long maskLayerNativeObject);
+ private static native void nativeSetBlurMaskSampling(long nativeObject, int blurMaskSampling);
+ private static native void nativeSetBlurMaskAlphaThreshold(long nativeObject, float alpha);
+
private static native boolean nativeClearContentFrameStats(long nativeObject);
private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
private static native boolean nativeClearAnimationFrameStats();
@@ -170,6 +175,11 @@ public class SurfaceControl {
public static final int FX_SURFACE_NORMAL = 0x00000000;
/**
+ * Surface creation flag: Creates a blur surface.
+ */
+ public static final int FX_SURFACE_BLUR = 0x00010000;
+
+ /**
* Surface creation flag: Creates a Dim surface.
* Everything behind this surface is dimmed by the amount specified
* in {@link #setAlpha}. It is an error to lock a Dim surface, since it
@@ -215,6 +225,12 @@ public class SurfaceControl {
*/
public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
+ /**
+ * Built-in physical display id: Attached HDMI display.
+ * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
+ */
+ public static final int BUILT_IN_DISPLAY_ID_TERTIARY = 2;
+
/* Display power modes * /
/**
@@ -378,6 +394,29 @@ public class SurfaceControl {
nativeSetSize(mNativeObject, w, h);
}
+ public void setBlur(float blur) {
+ checkNotReleased();
+ nativeSetBlur(mNativeObject, blur);
+ }
+
+ public void setBlurMaskSurface(SurfaceControl maskSurface) {
+ checkNotReleased();
+ if (maskSurface != null) {
+ maskSurface.checkNotReleased();
+ }
+ nativeSetBlurMaskSurface(mNativeObject, maskSurface == null ? 0:maskSurface.mNativeObject);
+ }
+
+ public void setBlurMaskSampling(int blurMaskSampling) {
+ checkNotReleased();
+ nativeSetBlurMaskSampling(mNativeObject, blurMaskSampling);
+ }
+
+ public void setBlurMaskAlphaThreshold(float alpha) {
+ checkNotReleased();
+ nativeSetBlurMaskAlphaThreshold(mNativeObject, alpha);
+ }
+
public void hide() {
checkNotReleased();
nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f6119e2..db147ab 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -145,9 +145,10 @@ public class ThreadedRenderer extends HardwareRenderer {
@Override
boolean initialize(Surface surface) throws OutOfResourcesException {
+ boolean status = !mInitialized;
mInitialized = true;
updateEnabledState(surface);
- boolean status = nInitialize(mNativeProxy, surface);
+ nInitialize(mNativeProxy, surface);
return status;
}
@@ -503,7 +504,7 @@ public class ThreadedRenderer extends HardwareRenderer {
private static native boolean nLoadSystemProperties(long nativeProxy);
private static native void nSetName(long nativeProxy, String name);
- private static native boolean nInitialize(long nativeProxy, Surface window);
+ private static native void nInitialize(long nativeProxy, Surface window);
private static native void nUpdateSurface(long nativeProxy, Surface window);
private static native boolean nPauseSurface(long nativeProxy, Surface window);
private static native void nSetup(long nativeProxy, int width, int height,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 720d9a8..4b56352 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9284,6 +9284,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
+ android.util.SeempLog.record(3);
// Defensive cleanup for new gesture
stopNestedScroll();
}
@@ -9828,6 +9829,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param event The KeyEvent object that defines the button action.
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
+ android.util.SeempLog.record(4);
boolean result = false;
if (KeyEvent.isConfirmKey(keyCode)) {
@@ -9872,6 +9874,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param event The KeyEvent object that defines the button action.
*/
public boolean onKeyUp(int keyCode, KeyEvent event) {
+ android.util.SeempLog.record(5);
if (KeyEvent.isConfirmKey(keyCode)) {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return true;
@@ -10269,6 +10272,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return True if the event was handled, false otherwise.
*/
public boolean onTouchEvent(MotionEvent event) {
+ android.util.SeempLog.record(3);
final float x = event.getX();
final float y = event.getY();
final int viewFlags = mViewFlags;
@@ -15940,8 +15944,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
RenderNode renderNode = null;
Bitmap cache = null;
int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
- if (layerType == LAYER_TYPE_SOFTWARE
- || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
+ if (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE) {
// If not drawing with RenderNode, treat HW layers as SW
layerType = LAYER_TYPE_SOFTWARE;
buildDrawingCache(true);
@@ -21719,7 +21722,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Last global system UI visibility reported by the window manager.
*/
- int mGlobalSystemUiVisibility;
+ int mGlobalSystemUiVisibility = -1;
/**
* True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 4d584a3..93f5779 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -317,7 +317,7 @@ public class ViewConfiguration {
case HAS_PERMANENT_MENU_KEY_AUTODETECT: {
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
- sHasPermanentMenuKey = !wm.hasNavigationBar();
+ sHasPermanentMenuKey = wm.hasPermanentMenuKey();
sHasPermanentMenuKeySet = true;
} catch (RemoteException ex) {
sHasPermanentMenuKey = false;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index c222a82..3616622 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -199,6 +199,7 @@ public abstract class Window {
private boolean mHaveWindowFormat = false;
private boolean mHaveDimAmount = false;
+ private boolean mHaveBlurAmount = false;
private int mDefaultWindowFormat = PixelFormat.OPAQUE;
private boolean mHasSoftInputMode = false;
@@ -818,6 +819,13 @@ public abstract class Window {
setPrivateFlags(flags, flags);
}
+ /** @hide */
+ public void setBlurMaskAlphaThreshold(float alpha) {
+ final WindowManager.LayoutParams attrs = getAttributes();
+ attrs.blurMaskAlphaThreshold = alpha;
+ dispatchWindowAttributesChanged(attrs);
+ }
+
/**
* Convenience function to clear the flag bits as specified in flags, as
* per {@link #setFlags}.
@@ -829,6 +837,11 @@ public abstract class Window {
setFlags(0, flags);
}
+ /** @hide */
+ public void clearPrivateFlags(int flags) {
+ setPrivateFlags(0, flags);
+ }
+
/**
* Set the flags of the window, as per the
* {@link WindowManager.LayoutParams WindowManager.LayoutParams}
@@ -856,6 +869,10 @@ public abstract class Window {
}
private void setPrivateFlags(int flags, int mask) {
+ if ((flags & mask & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0){
+ mContext.enforceCallingOrSelfPermission("android.permission.PREVENT_POWER_KEY",
+ "No permission to prevent power key");
+ }
final WindowManager.LayoutParams attrs = getAttributes();
attrs.privateFlags = (attrs.privateFlags & ~mask) | (flags & mask);
dispatchWindowAttributesChanged(attrs);
@@ -895,6 +912,19 @@ public abstract class Window {
}
/**
+ * Set the amount of blur behind the window when using
+ * {@link WindowManager.LayoutParams#FLAG_BLUR_BEHIND}.
+ * This feature may not be supported by all devices.
+ * {@hide}
+ */
+ public void setBlurAmount(float amount) {
+ final WindowManager.LayoutParams attrs = getAttributes();
+ attrs.blurAmount = amount;
+ mHaveBlurAmount = true;
+ dispatchWindowAttributesChanged(attrs);
+ }
+
+ /**
* Specify custom window attributes. <strong>PLEASE NOTE:</strong> the
* layout params you give here should generally be from values previously
* retrieved with {@link #getAttributes()}; you probably do not want to
@@ -1404,6 +1434,11 @@ public abstract class Window {
return mHaveDimAmount;
}
+ /** @hide */
+ protected boolean haveBlurAmount() {
+ return mHaveBlurAmount;
+ }
+
public abstract void setChildDrawable(int featureId, Drawable drawable);
public abstract void setChildInt(int featureId, int value);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 45bc1df..1125b44 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -186,6 +186,7 @@ public interface WindowManager extends ViewManager {
* @see #TYPE_SYSTEM_ERROR
* @see #TYPE_INPUT_METHOD
* @see #TYPE_INPUT_METHOD_DIALOG
+ * @see #TYPE_KEYGUARD_PANEL
*/
@ViewDebug.ExportedProperty(mapping = {
@ViewDebug.IntToString(from = TYPE_BASE_APPLICATION, to = "TYPE_BASE_APPLICATION"),
@@ -226,6 +227,7 @@ public interface WindowManager extends ViewManager {
@ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
+ @ViewDebug.IntToString(from = TYPE_KEYGUARD_PANEL, to = "TYPE_KEYGUARD_PANEL"),
})
public int type;
@@ -565,6 +567,13 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
/**
+ * Window type: Windows that are layered within the keyguard
+ * This type is LAST_SYSTEM_WINDOW-1 to avoid future conflicts with AOSP
+ * @hide
+ */
+ public static final int TYPE_KEYGUARD_PANEL = FIRST_SYSTEM_WINDOW+998;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
@@ -1128,6 +1137,42 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000;
/**
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_STATUS_HIDE_FORCED = 0x00800000;
+
+ /**
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_NAV_HIDE_FORCED = 0x01000000;
+
+ /**
+ * The window had not set FULLSCREEN flag so don't handle it as fullscreen in layoutWindowLw
+ *
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_WAS_NOT_FULLSCREEN = 0x02000000;
+
+ /**
+ * Window flag: Overrides default power key behavior
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_PREVENT_POWER_KEY = 0x20000000;
+
+ /**
+ * Window flag: adding additional blur layer and set this as masking layer
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_BLUR_WITH_MASKING = 0x40000000;
+
+ /**
+ * Window flag: adding additional blur layer and set this as masking layer.
+ * This is faster and ugglier than non-scaled version.
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_BLUR_WITH_MASKING_SCALED = 0x80000000;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
@@ -1389,6 +1434,15 @@ public interface WindowManager extends ViewManager {
public float dimAmount = 1.0f;
/**
+ * When {@link #FLAG_BLUR_BEHIND} is set, this is the amount of blur
+ * to apply. Range is from 1.0 for maximum to 0.0 for no
+ * blur.
+ * @hide
+ */
+ public float blurAmount = 1.0f;
+
+
+ /**
* Default value for {@link #screenBrightness} and {@link #buttonBrightness}
* indicating that the brightness value is not overridden for this window
* and normal brightness policy should be used.
@@ -1581,6 +1635,14 @@ public interface WindowManager extends ViewManager {
*/
public long userActivityTimeout = -1;
+ /**
+ * Threshold value that blur masking layer uses to determine whether
+ * to use or discard the blurred color.
+ * Value should be between 0.0 and 1.0
+ * @hide
+ */
+ public float blurMaskAlphaThreshold = 0.0f;
+
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
@@ -1667,6 +1729,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(windowAnimations);
out.writeFloat(alpha);
out.writeFloat(dimAmount);
+ out.writeFloat(blurAmount);
out.writeFloat(screenBrightness);
out.writeFloat(buttonBrightness);
out.writeInt(rotationAnimation);
@@ -1687,6 +1750,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(surfaceInsets.bottom);
out.writeInt(hasManualSurfaceInsets ? 1 : 0);
out.writeInt(needsMenuKey);
+ out.writeFloat(blurMaskAlphaThreshold);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1717,6 +1781,7 @@ public interface WindowManager extends ViewManager {
windowAnimations = in.readInt();
alpha = in.readFloat();
dimAmount = in.readFloat();
+ blurAmount = in.readFloat();
screenBrightness = in.readFloat();
buttonBrightness = in.readFloat();
rotationAnimation = in.readInt();
@@ -1737,6 +1802,7 @@ public interface WindowManager extends ViewManager {
surfaceInsets.bottom = in.readInt();
hasManualSurfaceInsets = in.readInt() != 0;
needsMenuKey = in.readInt();
+ blurMaskAlphaThreshold = in.readFloat();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1776,6 +1842,10 @@ public interface WindowManager extends ViewManager {
/** {@hide} */
public static final int PREFERRED_DISPLAY_MODE_ID = 1 << 23;
/** {@hide} */
+ public static final int BLUR_AMOUNT_CHANGED = 1 << 29;
+ /** {@hide} */
+ public static final int BLUR_MASK_ALPHA_THRESHOLD_CHANGED = 1 << 30;
+ /** {@hide} */
public static final int EVERYTHING_CHANGED = 0xffffffff;
// internal buffer to backup/restore parameters under compatibility mode.
@@ -1870,6 +1940,10 @@ public interface WindowManager extends ViewManager {
dimAmount = o.dimAmount;
changes |= DIM_AMOUNT_CHANGED;
}
+ if (blurAmount != o.blurAmount) {
+ blurAmount = o.blurAmount;
+ changes |= BLUR_AMOUNT_CHANGED;
+ }
if (screenBrightness != o.screenBrightness) {
screenBrightness = o.screenBrightness;
changes |= SCREEN_BRIGHTNESS_CHANGED;
@@ -1935,6 +2009,11 @@ public interface WindowManager extends ViewManager {
changes |= NEEDS_MENU_KEY_CHANGED;
}
+ if (blurMaskAlphaThreshold != o.blurMaskAlphaThreshold) {
+ blurMaskAlphaThreshold = o.blurMaskAlphaThreshold;
+ changes |= BLUR_MASK_ALPHA_THRESHOLD_CHANGED;
+ }
+
return changes;
}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 98e9f54..95e291c 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -81,12 +81,14 @@ public final class WindowManagerImpl implements WindowManager {
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
+ android.util.SeempLog.record_vg_layout(383,params);
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
+ android.util.SeempLog.record_vg_layout(384,params);
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index aaf6052..a962f2a 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -453,6 +453,8 @@ public interface WindowManagerPolicy {
/** Unregister a system listener for touch events */
void unregisterPointerEventListener(PointerEventListener listener);
+
+ void addSystemUIVisibilityFlag(int flags);
}
public interface PointerEventListener {
@@ -778,7 +780,8 @@ public interface WindowManagerPolicy {
* Create and return an animation to let the wallpaper disappear after being shown on a force
* hiding window.
*/
- public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade);
+ public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade,
+ boolean keyguardShowingMedia);
/**
* Called from the input reader thread before a key is enqueued.
@@ -1237,6 +1240,12 @@ public interface WindowManagerPolicy {
* Specifies whether there is an on-screen navigation bar separate from the status bar.
*/
public boolean hasNavigationBar();
+ public boolean hasPermanentMenuKey();
+
+ /**
+ * Specifies whether the device needs a navigation bar (because it has no hardware buttons)
+ */
+ public boolean needsNavigationBar();
/**
* Lock the device now.
diff --git a/core/java/android/view/WindowManagerPolicyControl.java b/core/java/android/view/WindowManagerPolicyControl.java
new file mode 100644
index 0000000..cdba239
--- /dev/null
+++ b/core/java/android/view/WindowManagerPolicyControl.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerPolicy.WindowState;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Iterator;
+
+/**
+ * Runtime adjustments applied to the global window policy.
+ *
+ * This includes forcing immersive mode behavior for one or both system bars (based on a package
+ * list) and permanently disabling immersive mode confirmations for specific packages.
+ *
+ * Control by setting {@link Settings.Global.POLICY_CONTROL} to one or more name-value pairs.
+ * e.g.
+ * to force immersive mode everywhere:
+ * "immersive.full=*"
+ * to force transient status for all apps except a specific package:
+ * "immersive.status=apps,-com.package"
+ * to disable the immersive mode confirmations for specific packages:
+ * "immersive.preconfirms=com.package.one,com.package.two"
+ *
+ * Separate multiple name-value pairs with ':'
+ * e.g. "immersive.status=apps:immersive.preconfirms=*"
+ *
+ * @hide
+ */
+public class WindowManagerPolicyControl {
+ private static String TAG = "PolicyControl";
+ private static boolean DEBUG = false;
+
+ private static final String NAME_IMMERSIVE_FULL = "immersive.full";
+ private static final String NAME_IMMERSIVE_STATUS = "immersive.status";
+ private static final String NAME_IMMERSIVE_NAVIGATION = "immersive.navigation";
+ private static final String NAME_IMMERSIVE_PRECONFIRMATIONS = "immersive.preconfirms";
+
+ private static int sDefaultImmersiveStyle;
+ private static String sSettingValue;
+ private static Filter sImmersivePreconfirmationsFilter;
+ private static Filter sImmersiveStatusFilter;
+ private static Filter sImmersiveNavigationFilter;
+
+ /**
+ * Accessible constants for Settings
+ */
+ public final static class ImmersiveDefaultStyles {
+ public final static int IMMERSIVE_FULL = 0;
+ public final static int IMMERSIVE_STATUS = 1;
+ public final static int IMMERSIVE_NAVIGATION = 2;
+ }
+
+ public static int getSystemUiVisibility(WindowState win, LayoutParams attrs) {
+ attrs = attrs != null ? attrs : win.getAttrs();
+ int vis = win != null ? win.getSystemUiVisibility() : attrs.systemUiVisibility;
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_STATUS)) {
+ vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.STATUS_BAR_TRANSLUCENT);
+ }
+ if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_NAVIGATION)) {
+ vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.NAVIGATION_BAR_TRANSLUCENT);
+ }
+ return vis;
+ }
+
+ public static int getWindowFlags(WindowState win, LayoutParams attrs) {
+ attrs = attrs != null ? attrs : win.getAttrs();
+ int flags = attrs.flags;
+
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_STATUS)) {
+ flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ flags &= ~(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+ | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+ }
+ if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_NAVIGATION)) {
+ flags &= ~WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+ }
+ return flags;
+ }
+
+ public static int getPrivateWindowFlags(WindowState win, LayoutParams attrs) {
+ attrs = attrs != null ? attrs : win.getAttrs();
+ int privateFlags = attrs.privateFlags;
+
+ if (sImmersiveStatusFilter != null && sImmersiveNavigationFilter != null &&
+ sImmersiveStatusFilter.isEnabledForAll()
+ && sImmersiveNavigationFilter.isEnabledForAll()) {
+
+ if ((attrs.flags & LayoutParams.FLAG_FULLSCREEN) == 0) {
+ privateFlags |= LayoutParams.PRIVATE_FLAG_WAS_NOT_FULLSCREEN;
+ }
+
+ switch (sDefaultImmersiveStyle) {
+ case ImmersiveDefaultStyles.IMMERSIVE_FULL:
+ privateFlags |= LayoutParams.PRIVATE_FLAG_NAV_HIDE_FORCED;
+ privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_HIDE_FORCED;
+ return privateFlags;
+ case ImmersiveDefaultStyles.IMMERSIVE_STATUS:
+ privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_HIDE_FORCED;
+ return privateFlags;
+ case ImmersiveDefaultStyles.IMMERSIVE_NAVIGATION:
+ privateFlags |= LayoutParams.PRIVATE_FLAG_NAV_HIDE_FORCED;
+ return privateFlags;
+ }
+ }
+
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) {
+ if ((attrs.flags & LayoutParams.FLAG_FULLSCREEN) == 0) {
+ privateFlags |= LayoutParams.PRIVATE_FLAG_WAS_NOT_FULLSCREEN;
+ }
+ privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_HIDE_FORCED;
+ }
+
+ if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) {
+ privateFlags |= LayoutParams.PRIVATE_FLAG_NAV_HIDE_FORCED;
+ }
+
+ return privateFlags;
+ }
+
+ public static boolean immersiveStatusFilterMatches(String packageName) {
+ return sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(packageName);
+ }
+
+ public static boolean immersiveNavigationFilterMatches(String packageName) {
+ return sImmersiveNavigationFilter != null
+ && sImmersiveNavigationFilter.matches(packageName);
+ }
+
+ public static int adjustClearableFlags(WindowState win, int clearableFlags) {
+ final LayoutParams attrs = win != null ? win.getAttrs() : null;
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) {
+ clearableFlags &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
+ }
+ return clearableFlags;
+ }
+
+ public static boolean disableImmersiveConfirmation(String pkg) {
+ return (sImmersivePreconfirmationsFilter != null
+ && sImmersivePreconfirmationsFilter.matches(pkg))
+ || ActivityManager.isRunningInTestHarness();
+ }
+
+ public static void reloadFromSetting(Context context) {
+ reloadStyleFromSetting(context, Settings.Global.POLICY_CONTROL_STYLE);
+ reloadFromSetting(context, Settings.Global.POLICY_CONTROL);
+ }
+
+ public static void reloadFromSetting(Context context, String key) {
+ if (DEBUG) Slog.d(TAG, "reloadFromSetting()");
+ String value = null;
+ try {
+ value = Settings.Global.getStringForUser(context.getContentResolver(),
+ key,
+ UserHandle.USER_CURRENT);
+ if (sSettingValue != null && sSettingValue.equals(value)) return;
+ setFilters(value);
+ sSettingValue = value;
+ } catch (Throwable t) {
+ Slog.w(TAG, "Error loading policy control, value=" + value, t);
+ }
+ }
+
+ public static void reloadStyleFromSetting(Context context, String key) {
+ sDefaultImmersiveStyle = Settings.Global.getInt(context.getContentResolver(),
+ key, WindowManagerPolicyControl.ImmersiveDefaultStyles.IMMERSIVE_FULL);
+ if (DEBUG) Slog.d(TAG, "reloadStyleFromSetting " + sDefaultImmersiveStyle);
+ }
+
+ public static void saveToSettings(Context context) {
+ saveToSettings(context, Settings.Global.POLICY_CONTROL);
+ }
+
+ public static void saveToSettings(Context context, String key) {
+ StringBuilder value = new StringBuilder();
+ boolean needSemicolon = false;
+ if (sImmersiveStatusFilter != null) {
+ writeFilter(NAME_IMMERSIVE_STATUS, sImmersiveStatusFilter, value);
+ needSemicolon = true;
+ }
+ if (sImmersiveNavigationFilter != null) {
+ if (needSemicolon) {
+ value.append(":");
+ }
+ writeFilter(NAME_IMMERSIVE_NAVIGATION, sImmersiveNavigationFilter, value);
+ }
+
+ Settings.Global.putString(context.getContentResolver(), key, value.toString());
+ }
+
+ public static void saveStyleToSettings(Context context, int value) {
+ Settings.Global.putInt(context.getContentResolver(),
+ Settings.Global.POLICY_CONTROL_STYLE, value);
+ sDefaultImmersiveStyle = value;
+ }
+
+ public static void addToStatusWhiteList(String packageName) {
+ if (sImmersiveStatusFilter == null) {
+ sImmersiveStatusFilter = new Filter(new ArraySet<String>(), new ArraySet<String>());
+ }
+
+ if (!sImmersiveStatusFilter.mWhitelist.contains(packageName)) {
+ sImmersiveStatusFilter.mWhitelist.add(packageName);
+ }
+ }
+
+ public static void addToNavigationWhiteList(String packageName) {
+ if (sImmersiveNavigationFilter == null) {
+ sImmersiveNavigationFilter = new Filter(new ArraySet<String>(), new ArraySet<String>());
+ }
+
+ if (!sImmersiveNavigationFilter.mWhitelist.contains(packageName)) {
+ sImmersiveNavigationFilter.mWhitelist.add(packageName);
+ }
+ }
+
+ public static void removeFromWhiteLists(String packageName) {
+ if (sImmersiveStatusFilter != null) {
+ sImmersiveStatusFilter.mWhitelist.remove(packageName);
+ }
+ if (sImmersiveNavigationFilter != null) {
+ sImmersiveNavigationFilter.mWhitelist.remove(packageName);
+ }
+ }
+
+ public static ArraySet<String> getWhiteLists() {
+ ArraySet<String> result = new ArraySet<>();
+
+ if (sImmersiveStatusFilter != null) {
+ result.addAll(sImmersiveStatusFilter.mWhitelist);
+ }
+ if (sImmersiveNavigationFilter != null
+ && sImmersiveNavigationFilter != sImmersiveStatusFilter) {
+ result.addAll(sImmersiveNavigationFilter.mWhitelist);
+ }
+
+ return result;
+ }
+
+ private static void writeFilter(String name, Filter filter, StringBuilder stringBuilder) {
+ if (filter.mWhitelist.isEmpty() && filter.mBlacklist.isEmpty()) {
+ return;
+ }
+ stringBuilder.append(name);
+ stringBuilder.append("=");
+
+ boolean needComma = false;
+ if (!filter.mWhitelist.isEmpty()) {
+ writePackages(filter.mWhitelist, stringBuilder, false);
+ needComma = true;
+ }
+ if (!filter.mBlacklist.isEmpty()) {
+ if (needComma) {
+ stringBuilder.append(",");
+ }
+ writePackages(filter.mBlacklist, stringBuilder, true);
+ }
+ }
+
+ private static void writePackages(ArraySet<String> set, StringBuilder stringBuilder,
+ boolean isBlackList) {
+ Iterator<String> iterator = set.iterator();
+ while (iterator.hasNext()) {
+ if (isBlackList) {
+ stringBuilder.append("-");
+ }
+ String name = iterator.next();
+ stringBuilder.append(name);
+ if (iterator.hasNext()) {
+ stringBuilder.append(",");
+ }
+ }
+ }
+
+ public static boolean isImmersiveFiltersActive() {
+ return sImmersiveStatusFilter != null || sImmersiveNavigationFilter != null;
+ }
+
+ public static void dump(String prefix, PrintWriter pw) {
+ dump("sImmersiveStatusFilter", sImmersiveStatusFilter, prefix, pw);
+ dump("sImmersiveNavigationFilter", sImmersiveNavigationFilter, prefix, pw);
+ dump("sImmersivePreconfirmationsFilter", sImmersivePreconfirmationsFilter, prefix, pw);
+ }
+
+ private static void dump(String name, Filter filter, String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("PolicyControl."); pw.print(name); pw.print('=');
+ if (filter == null) {
+ pw.println("null");
+ } else {
+ filter.dump(pw); pw.println();
+ }
+ }
+
+ private static void setFilters(String value) {
+ if (DEBUG) Slog.d(TAG, "setFilters: " + value);
+ sImmersiveStatusFilter = null;
+ sImmersiveNavigationFilter = null;
+ sImmersivePreconfirmationsFilter = null;
+ if (value != null) {
+ String[] nvps = value.split(":");
+ for (String nvp : nvps) {
+ int i = nvp.indexOf('=');
+ if (i == -1) continue;
+ String n = nvp.substring(0, i);
+ String v = nvp.substring(i + 1);
+ if (n.equals(NAME_IMMERSIVE_FULL)) {
+ Filter f = Filter.parse(v);
+ sImmersiveStatusFilter = sImmersiveNavigationFilter = f;
+ if (sImmersivePreconfirmationsFilter == null) {
+ sImmersivePreconfirmationsFilter = f;
+ }
+ } else if (n.equals(NAME_IMMERSIVE_STATUS)) {
+ Filter f = Filter.parse(v);
+ sImmersiveStatusFilter = f;
+ } else if (n.equals(NAME_IMMERSIVE_NAVIGATION)) {
+ Filter f = Filter.parse(v);
+ sImmersiveNavigationFilter = f;
+ if (sImmersivePreconfirmationsFilter == null) {
+ sImmersivePreconfirmationsFilter = f;
+ }
+ } else if (n.equals(NAME_IMMERSIVE_PRECONFIRMATIONS)) {
+ Filter f = Filter.parse(v);
+ sImmersivePreconfirmationsFilter = f;
+ }
+ }
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "immersiveStatusFilter: " + sImmersiveStatusFilter);
+ Slog.d(TAG, "immersiveNavigationFilter: " + sImmersiveNavigationFilter);
+ Slog.d(TAG, "immersivePreconfirmationsFilter: " + sImmersivePreconfirmationsFilter);
+ }
+ }
+
+ private static class Filter {
+ private static final String ALL = "*";
+ private static final String APPS = "apps";
+
+ private final ArraySet<String> mWhitelist;
+ private final ArraySet<String> mBlacklist;
+
+ private Filter(ArraySet<String> whitelist, ArraySet<String> blacklist) {
+ mWhitelist = whitelist;
+ mBlacklist = blacklist;
+ }
+
+ boolean matches(LayoutParams attrs) {
+ if (attrs == null) return false;
+ boolean isApp = attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+ if (isApp && mBlacklist.contains(APPS)) return false;
+ if (onBlacklist(attrs.packageName)) return false;
+ if (isApp && mWhitelist.contains(APPS)) return true;
+ return onWhitelist(attrs.packageName);
+ }
+
+ boolean matches(String packageName) {
+ return !onBlacklist(packageName) && onWhitelist(packageName);
+ }
+
+ public boolean isEnabledForAll() {
+ return mWhitelist.contains(ALL);
+ }
+
+ private boolean onBlacklist(String packageName) {
+ return mBlacklist.contains(packageName) || mBlacklist.contains(ALL);
+ }
+
+ private boolean onWhitelist(String packageName) {
+ return mWhitelist.contains(ALL) || mWhitelist.contains(packageName);
+ }
+
+ void dump(PrintWriter pw) {
+ pw.print("Filter[");
+ dump("whitelist", mWhitelist, pw); pw.print(',');
+ dump("blacklist", mBlacklist, pw); pw.print(']');
+ }
+
+ private void dump(String name, ArraySet<String> set, PrintWriter pw) {
+ pw.print(name); pw.print("=(");
+ final int n = set.size();
+ for (int i = 0; i < n; i++) {
+ if (i > 0) pw.print(',');
+ pw.print(set.valueAt(i));
+ }
+ pw.print(')');
+ }
+
+ @Override
+ public String toString() {
+ StringWriter sw = new StringWriter();
+ dump(new PrintWriter(sw, true));
+ return sw.toString();
+ }
+
+ // value = comma-delimited list of tokens, where token = (package name|apps|*)
+ // e.g. "com.package1", or "apps, com.android.keyguard" or "*"
+ static Filter parse(String value) {
+ if (value == null) return null;
+ ArraySet<String> whitelist = new ArraySet<String>();
+ ArraySet<String> blacklist = new ArraySet<String>();
+ for (String token : value.split(",")) {
+ token = token.trim();
+ if (token.startsWith("-") && token.length() > 1) {
+ token = token.substring(1);
+ blacklist.add(token);
+ } else {
+ whitelist.add(token);
+ }
+ }
+ return new Filter(whitelist, blacklist);
+ }
+ }
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4737e9b..01fcc1a 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -290,7 +290,9 @@ public class WebChromeClient {
* origin.
*/
public void onGeolocationPermissionsShowPrompt(String origin,
- GeolocationPermissions.Callback callback) {}
+ GeolocationPermissions.Callback callback) {
+ android.util.SeempLog.record(54);
+ }
/**
* Notify the host application that a request for Geolocation permissions,
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 584deff..93b1e56 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -97,7 +97,14 @@ public final class WebViewFactory {
}
public static String getWebViewPackageName() {
- return AppGlobals.getInitialApplication().getString(
+ Application initialApp = AppGlobals.getInitialApplication();
+ String pkg = initialApp.getString(
+ com.android.internal.R.string.config_alternateWebViewPackageName);
+ /* Attempt to use alternate WebView package first */
+ if (isPackageInstalled(initialApp, pkg)) {
+ return pkg;
+ }
+ return initialApp.getString(
com.android.internal.R.string.config_webViewPackageName);
}
@@ -529,6 +536,14 @@ public final class WebViewFactory {
return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
}
+ private static boolean isPackageInstalled(Context context, String packageName) {
+ try {
+ return context.getPackageManager().getPackageInfo(packageName, 0) != null;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
private static native boolean nativeCreateRelroFile(String lib32, String lib64,
String relro32, String relro64);
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index a4c8d1c..31bc536 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -663,7 +663,14 @@ public abstract class AbsSeekBar extends ProgressBar {
progress += scale * max;
setHotspot(x, (int) event.getY());
- setProgress((int) progress, true);
+ setProgress(updateTouchProgress(getProgress(), (int) progress), true);
+ }
+
+ /**
+ * @hide
+ */
+ protected int updateTouchProgress(int lastProgress, int newProgress) {
+ return newProgress;
}
/**
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index c40289e..559181b 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -383,6 +383,7 @@ class FastScroller {
break;
}
}
+ ta.recycle();
updateAppearance();
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index ca1b211..6a272e5 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2744,6 +2744,12 @@ public class RemoteViews implements Parcelable, Filter {
/** @hide */
public View apply(Context context, ViewGroup parent, OnClickHandler handler) {
+ return apply(context, parent, handler, null);
+ }
+
+ /** @hide */
+ public View apply(Context context, ViewGroup parent, OnClickHandler handler,
+ String themePackageName) {
RemoteViews rvToApply = getRemoteViewsToApply(context);
View result;
@@ -2751,7 +2757,7 @@ public class RemoteViews implements Parcelable, Filter {
// user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats
// are loaded without requiring cross user persmissions.
- final Context contextForResources = getContextForResources(context);
+ final Context contextForResources = getContextForResources(context, themePackageName);
Context inflationContext = new ContextWrapper(context) {
@Override
public Resources getResources() {
@@ -2841,14 +2847,15 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- private Context getContextForResources(Context context) {
+ private Context getContextForResources(Context context, String themePackageName) {
if (mApplication != null) {
if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
- && context.getPackageName().equals(mApplication.packageName)) {
+ && context.getPackageName().equals(mApplication.packageName)
+ && themePackageName == null) {
return context;
}
try {
- return context.createApplicationContext(mApplication,
+ return context.createApplicationContext(mApplication, themePackageName,
Context.CONTEXT_RESTRICTED);
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found");
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index bcde315..d5a3f16 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -548,6 +548,7 @@ public class TextClock extends TextView {
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ filter.addAction(Intent.ACTION_DOZE_PULSE_STARTING);
getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 207f675..4b31af0 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -21,9 +21,11 @@ import android.annotation.StringRes;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -400,6 +402,18 @@ public class Toast {
if (context == null) {
context = mView.getContext();
}
+
+ ImageView appIcon = (ImageView) mView.findViewById(android.R.id.icon);
+ if (appIcon != null) {
+ PackageManager pm = context.getPackageManager();
+ Drawable icon = null;
+ try {
+ icon = pm.getApplicationIcon(packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ // nothing to do
+ }
+ appIcon.setImageDrawable(icon);
+ }
mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
// We can resolve the Gravity here by using the Locale for getting
// the layout direction
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 9fa2c23..aa1c265 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -46,4 +46,12 @@ interface IAppOpsService {
void setUserRestrictions(in Bundle restrictions, int userHandle);
void removeUser(int userHandle);
+ boolean isControlAllowed(int code, String packageName);
+
+ // Privacy guard methods
+ boolean getPrivacyGuardSettingForPackage(int uid, String packageName);
+ void setPrivacyGuardSettingForPackage(int uid, String packageName, boolean state);
+
+ // AppOps accounting
+ void resetCounters();
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3cddbf6..ba92f48 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -121,4 +122,18 @@ interface IBatteryStats {
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
+
+
+ /** @hide */
+ byte[] getDockStatistics();
+ /** @hide */
+ ParcelFileDescriptor getDockStatisticsStream();
+ /** @hide **/
+ void resetStatistics();
+ /** @hide **/
+ void setDockBatteryState(int status, int health, int plugType, int level, int temp, int volt);
+ /** @hide **/
+ long getAwakeTimeDockBattery();
+ /** @hide **/
+ long getAwakeTimeDockPlugged();
}
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 4efefa9..83160cd 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,6 +44,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.ArrayList;
+import java.util.Arrays;
public class LocalePicker extends ListFragment {
private static final String TAG = "LocalePicker";
@@ -83,12 +87,23 @@ public class LocalePicker extends ListFragment {
}
}
+ public static ArrayList<String> getLocaleArray(String[] locales, Resources resources) {
+ String locale_codes = resources.getString(R.string.locale_codes);
+ String[] localeCodesArray = null;
+ if (locale_codes != null && !"".equals(locale_codes.trim())) {
+ localeCodesArray = locale_codes.split(",");
+ }
+ ArrayList<String> localeList = new ArrayList<String>(
+ Arrays.asList((localeCodesArray == null || localeCodesArray.length == 0) ? locales
+ : localeCodesArray));
+ return localeList;
+ }
+
public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
final Resources resources = context.getResources();
- final String[] locales = Resources.getSystem().getAssets().getLocales();
- List<String> localeList = new ArrayList<String>(locales.length);
- Collections.addAll(localeList, locales);
+ String[] locales = Resources.getSystem().getAssets().getLocales();
+ ArrayList<String> localeList = getLocaleArray(locales, resources);
// Don't show the pseudolocales unless we're in developer mode. http://b/17190407.
if (!isInDeveloperMode) {
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 2595fe0..efe88ff 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2014-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,10 +58,13 @@ public class PlatLogoActivity extends Activity {
int mKeyCount;
PathInterpolator mInterpolator = new PathInterpolator(0f, 0f, 0.5f, 1f);
+ private boolean mIsCM;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mIsCM = getIntent().hasExtra("is_cm");
mLayout = new FrameLayout(this);
setContentView(mLayout);
}
@@ -153,6 +157,7 @@ public class PlatLogoActivity extends Activity {
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ .putExtra("is_cm", mIsCM)
.addCategory("com.android.internal.category.PLATLOGO"));
} catch (ActivityNotFoundException ex) {
Log.e("PlatLogoActivity", "No more eggs.");
@@ -202,7 +207,9 @@ public class PlatLogoActivity extends Activity {
}
public void showMarshmallow(View im) {
- final Drawable fg = getDrawable(com.android.internal.R.drawable.platlogo);
+ final Drawable fg = getDrawable(mIsCM
+ ? com.android.internal.R.drawable.platlogo_cm
+ : com.android.internal.R.drawable.platlogo);
fg.setBounds(0, 0, im.getWidth(), im.getHeight());
fg.setAlpha(0);
im.getOverlay().add(fg);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 4ba678c..00e250b 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -93,6 +93,7 @@ public class ResolverActivity extends Activity {
private boolean mSafeForwardingMode;
private boolean mAlwaysUseOption;
private AbsListView mAdapterView;
+ private ViewGroup mFilteredItemContainer;
private Button mAlwaysButton;
private Button mOnceButton;
private View mProfileView;
@@ -305,6 +306,21 @@ public class ResolverActivity extends Activity {
}
if (mAdapter.hasFilteredItem()) {
+ mFilteredItemContainer = (ViewGroup) findViewById(R.id.filtered_item_container);
+ mFilteredItemContainer.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ DisplayResolveInfo filteredItem = mAdapter.getFilteredItem();
+
+ if (filteredItem == null) {
+ return false;
+ }
+
+ showAppDetails(filteredItem.getResolveInfo());
+ return true;
+ }
+ });
+
setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false);
mOnceButton.setEnabled(true);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f178c8c..54a4e86 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.SensorManager;
import android.net.ConnectivityManager;
+import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStats.Uid;
import android.os.Bundle;
@@ -61,15 +62,18 @@ public final class BatteryStatsHelper {
private static final String TAG = BatteryStatsHelper.class.getSimpleName();
private static BatteryStats sStatsXfer;
+ private static BatteryStats sDockStatsXfer;
private static Intent sBatteryBroadcastXfer;
private static ArrayMap<File, BatteryStats> sFileXfer = new ArrayMap<>();
final private Context mContext;
+ final private BatteryManager mBatteryService;
final private boolean mCollectBatteryBroadcast;
final private boolean mWifiOnly;
private IBatteryStats mBatteryInfo;
private BatteryStats mStats;
+ private BatteryStats mDockStats;
private Intent mBatteryBroadcast;
private PowerProfile mPowerProfile;
@@ -160,19 +164,28 @@ public final class BatteryStatsHelper {
public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly) {
mContext = context;
+ mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE));
mCollectBatteryBroadcast = collectBatteryBroadcast;
mWifiOnly = wifiOnly;
}
public void storeStatsHistoryInFile(String fname) {
+ internalStoreStatsHistoryInFile(getStats(), fname);
+ }
+
+ public void storeDockStatsHistoryInFile(String fname) {
+ internalStoreStatsHistoryInFile(getDockStats(), fname);
+ }
+
+ public void internalStoreStatsHistoryInFile(BatteryStats stats, String fname) {
synchronized (sFileXfer) {
File path = makeFilePath(mContext, fname);
- sFileXfer.put(path, this.getStats());
+ sFileXfer.put(path, stats);
FileOutputStream fout = null;
try {
fout = new FileOutputStream(path);
Parcel hist = Parcel.obtain();
- getStats().writeToParcelWithoutUids(hist, 0);
+ stats.writeToParcelWithoutUids(hist, 0);
byte[] histData = hist.marshall();
fout.write(histData);
} catch (IOException e) {
@@ -229,18 +242,38 @@ public final class BatteryStatsHelper {
/** Clears the current stats and forces recreating for future use. */
public void clearStats() {
mStats = null;
+ mDockStats = null;
+ }
+
+ private void clearAllStats() {
+ clearStats();
+ sStatsXfer = null;
+ sDockStatsXfer = null;
+ sBatteryBroadcastXfer = null;
+ for (File f : sFileXfer.keySet()) {
+ f.delete();
+ }
+ sFileXfer.clear();
}
public BatteryStats getStats() {
if (mStats == null) {
- load();
+ loadStats();
}
return mStats;
}
+ public BatteryStats getDockStats() {
+ if (mDockStats == null) {
+ loadDockStats();
+ }
+ return mDockStats;
+ }
+
public Intent getBatteryBroadcast() {
if (mBatteryBroadcast == null && mCollectBatteryBroadcast) {
- load();
+ loadStats();
+ loadDockStats();
}
return mBatteryBroadcast;
}
@@ -257,6 +290,7 @@ public final class BatteryStatsHelper {
public void create(Bundle icicle) {
if (icicle != null) {
mStats = sStatsXfer;
+ mDockStats = sDockStatsXfer;
mBatteryBroadcast = sBatteryBroadcastXfer;
}
mBatteryInfo = IBatteryStats.Stub.asInterface(
@@ -266,6 +300,7 @@ public final class BatteryStatsHelper {
public void storeState() {
sStatsXfer = mStats;
+ sDockStatsXfer = mDockStats;
sBatteryBroadcastXfer = mBatteryBroadcast;
}
@@ -321,6 +356,7 @@ public final class BatteryStatsHelper {
long rawUptimeUs) {
// Initialize mStats if necessary.
getStats();
+ getDockStats();
mMaxPower = 0;
mMaxRealPower = 0;
@@ -739,7 +775,7 @@ public final class BatteryStatsHelper {
}
}
- private void load() {
+ private void loadStats() {
if (mBatteryInfo == null) {
return;
}
@@ -750,6 +786,26 @@ public final class BatteryStatsHelper {
}
}
+ private void loadDockStats() {
+ if (mBatteryInfo == null) {
+ return;
+ }
+ if (mBatteryService.isDockBatterySupported()) {
+ mDockStats = getDockStats(mBatteryInfo);
+ } else {
+ mDockStats = null;
+ }
+ }
+
+ public void resetStatistics() {
+ try {
+ clearAllStats();
+ mBatteryInfo.resetStatistics();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException:", e);
+ }
+ }
+
private static BatteryStatsImpl getStats(IBatteryStats service) {
try {
ParcelFileDescriptor pfd = service.getStatisticsStream();
@@ -772,4 +828,27 @@ public final class BatteryStatsHelper {
}
return new BatteryStatsImpl();
}
+
+ private static BatteryStatsImpl getDockStats(IBatteryStats service) {
+ try {
+ ParcelFileDescriptor pfd = service.getDockStatisticsStream();
+ if (pfd != null) {
+ FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ try {
+ byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
+ Parcel parcel = Parcel.obtain();
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ BatteryStatsImpl stats = com.android.internal.os.DockBatteryStatsImpl.CREATOR
+ .createFromParcel(parcel);
+ return stats;
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to read statistics stream", e);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "RemoteException:", e);
+ }
+ return new BatteryStatsImpl();
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1d9fa9d..d0a169e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006-2007 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +92,7 @@ import java.util.concurrent.locks.ReentrantLock;
* battery life. All times are represented in microseconds except where indicated
* otherwise.
*/
-public final class BatteryStatsImpl extends BatteryStats {
+public class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
public static final boolean DEBUG_ENERGY = false;
@@ -6843,13 +6844,13 @@ public final class BatteryStatsImpl extends BatteryStats {
public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
if (systemDir != null) {
- mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
- new File(systemDir, "batterystats.bin.tmp"));
+ mFile = new JournaledFile(new File(systemDir, getStatsName() + ".bin"),
+ new File(systemDir, getStatsName() + ".bin.tmp"));
} else {
mFile = null;
}
- mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
- mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
+ mCheckinFile = new AtomicFile(new File(systemDir, getStatsName() + "-checkin.bin"));
+ mDailyFile = new AtomicFile(new File(systemDir, getStatsName () + "-daily.xml"));
mExternalSync = externalSync;
mHandler = new MyHandler(handler.getLooper());
mStartCount++;
@@ -6925,6 +6926,16 @@ public final class BatteryStatsImpl extends BatteryStats {
readFromParcel(p);
}
+ /** @hide */
+ protected String getStatsName() {
+ return "batterystats";
+ }
+
+ /** @hide */
+ protected String getLogName() {
+ return "BatteryStats";
+ }
+
public void setPowerProfile(PowerProfile profile) {
synchronized (this) {
mPowerProfile = profile;
@@ -8447,7 +8458,13 @@ public final class BatteryStatsImpl extends BatteryStats {
public void setBatteryStateLocked(int status, int health, int plugType, int level,
int temp, int volt) {
- final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
+ // We need to add a extra check over the status because of dock batteries
+ // PlugType doesn't means that the dock battery is charging (some devices
+ // doesn't charge under dock usb)
+ boolean onBattery = plugType == BATTERY_PLUGGED_NONE &&
+ (status != BatteryManager.BATTERY_STATUS_CHARGING ||
+ status != BatteryManager.BATTERY_STATUS_FULL);
+
final long uptime = SystemClock.uptimeMillis();
final long elapsedRealtime = SystemClock.elapsedRealtime();
if (!mHaveBatteryLevel) {
diff --git a/core/java/com/android/internal/os/DeviceKeyHandler.java b/core/java/com/android/internal/os/DeviceKeyHandler.java
new file mode 100644
index 0000000..e7d103d
--- /dev/null
+++ b/core/java/com/android/internal/os/DeviceKeyHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod Project Licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.view.KeyEvent;
+
+public interface DeviceKeyHandler {
+
+ /**
+ * Invoked when an unknown key was detected by the system, letting the device handle
+ * this special keys prior to pass the key to the active app.
+ *
+ * @param event The key event to be handled
+ * @return If the event is consume
+ */
+ public boolean handleKeyEvent(KeyEvent event);
+}
diff --git a/core/java/com/android/internal/os/DockBatteryStatsImpl.java b/core/java/com/android/internal/os/DockBatteryStatsImpl.java
new file mode 100644
index 0000000..6099ad2
--- /dev/null
+++ b/core/java/com/android/internal/os/DockBatteryStatsImpl.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.File;
+
+public final class DockBatteryStatsImpl extends BatteryStatsImpl {
+ public DockBatteryStatsImpl() {
+ super();
+ }
+
+ public DockBatteryStatsImpl(Parcel p) {
+ super(p);
+ }
+
+ public DockBatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
+ super(systemDir, handler, externalSync);
+ }
+
+ protected String getStatsName() {
+ return "dockbatterystats";
+ }
+
+ protected String getLogName() {
+ return "DockBatteryStats";
+ }
+
+ public static final Parcelable.Creator<DockBatteryStatsImpl> CREATOR =
+ new Parcelable.Creator<DockBatteryStatsImpl>() {
+ public DockBatteryStatsImpl createFromParcel(Parcel in) {
+ return new DockBatteryStatsImpl(in);
+ }
+
+ public DockBatteryStatsImpl[] newArray(int size) {
+ return new DockBatteryStatsImpl[size];
+ }
+ };
+}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index f81658e..3377189 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -19,6 +19,7 @@ package com.android.internal.os;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.ApplicationErrorReport;
+import android.content.res.ThemeConfig;
import android.os.Build;
import android.os.Debug;
import android.os.IBinder;
@@ -83,6 +84,10 @@ public class RuntimeInit {
message.append("Process: ").append(processName).append(", ");
}
message.append("PID: ").append(Process.myPid());
+ final ThemeConfig themeConfig =
+ ActivityManagerNative.getDefault().getConfiguration().themeConfig;
+ message.append("\nTheme: ").append(themeConfig == null ?
+ ThemeConfig.SYSTEM_DEFAULT : themeConfig);
Clog_e(TAG, message.toString(), e);
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 3e86fac..6c3cb3e 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -22,6 +22,7 @@ import static android.system.OsConstants.STDERR_FILENO;
import static android.system.OsConstants.STDIN_FILENO;
import static android.system.OsConstants.STDOUT_FILENO;
+import android.graphics.Typeface;
import android.net.Credentials;
import android.net.LocalSocket;
import android.os.Process;
@@ -194,6 +195,10 @@ class ZygoteConnection {
Os.fcntlInt(childPipeFd, F_SETFD, 0);
}
+ if (parsedArgs.refreshTheme) {
+ Typeface.recreateDefaults();
+ }
+
/**
* In order to avoid leaking descriptors to the Zygote child,
* the native code must close the two Zygote socket descriptors
@@ -373,6 +378,9 @@ class ZygoteConnection {
*/
String appDataDir;
+ /** from --refresh_theme */
+ boolean refreshTheme;
+
/**
* Constructs instance and parses args
* @param args zygote command-line args
@@ -529,6 +537,8 @@ class ZygoteConnection {
instructionSet = arg.substring(arg.indexOf('=') + 1);
} else if (arg.startsWith("--app-data-dir=")) {
appDataDir = arg.substring(arg.indexOf('=') + 1);
+ } else if (arg.equals("--refresh_theme")) {
+ refreshTheme = true;
} else {
break;
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 8e8d352..fe0bc65 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -76,12 +76,19 @@ import com.android.internal.widget.SwipeDismissLayout;
import android.app.ActivityManager;
import android.app.KeyguardManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
+import android.content.ActivityNotFoundException;
+import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
@@ -93,10 +100,14 @@ import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Settings;
import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionInflater;
@@ -108,6 +119,8 @@ import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
@@ -118,10 +131,14 @@ import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.TextView;
+import android.widget.Toast;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.R;
+
/**
* Android-specific Window.
* <p>
@@ -249,7 +266,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private int mTitleColor = 0;
private boolean mAlwaysReadCloseOnTouchAttr = false;
+ private boolean mEnableGestures;
+ private Context mContext;
private ContextMenuBuilder mContextMenu;
private MenuDialogHelper mContextMenuHelper;
private boolean mClosingActionMenu;
@@ -260,6 +279,36 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private AudioManager mAudioManager;
private KeyguardManager mKeyguardManager;
+ private final class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.System
+ .getUriFor(Settings.System.ENABLE_STYLUS_GESTURES), false,
+ this);
+ checkGestures();
+ }
+
+ void unobserve() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ checkGestures();
+ }
+
+ void checkGestures() {
+ mEnableGestures = Settings.System.getInt(
+ mContext.getContentResolver(),
+ Settings.System.ENABLE_STYLUS_GESTURES, 0) == 1;
+ }
+ }
+
private int mUiOptions = 0;
private boolean mInvalidatePanelMenuPosted;
@@ -303,6 +352,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
public PhoneWindow(Context context) {
super(context);
+ mContext = context;
mLayoutInflater = LayoutInflater.from(context);
}
@@ -2224,6 +2274,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private View mStatusGuard;
// View added at runtime to draw under the navigation bar area
private View mNavigationGuard;
+ private SettingsObserver mSettingsObserver;
private final ColorViewState mStatusColorViewState = new ColorViewState(
SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
@@ -2267,6 +2318,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mBarEnterExitDuration = context.getResources().getInteger(
R.integer.dock_enter_exit_duration);
+
+ mSettingsObserver = new SettingsObserver(new Handler());
}
public void setBackgroundFallback(int resId) {
@@ -2358,8 +2411,211 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
+ private final StylusGestureFilter mStylusFilter = new StylusGestureFilter();
+
+ private class StylusGestureFilter extends SimpleOnGestureListener {
+
+ private final static int SWIPE_UP = 1;
+ private final static int SWIPE_DOWN = 2;
+ private final static int SWIPE_LEFT = 3;
+ private final static int SWIPE_RIGHT = 4;
+ private final static int PRESS_LONG = 5;
+ private final static int TAP_DOUBLE = 6;
+ private final static double SWIPE_MIN_DISTANCE = 25.0;
+ private final static double SWIPE_MIN_VELOCITY = 50.0;
+ private final static int KEY_NO_ACTION = 1000;
+ private final static int KEY_HOME = 1001;
+ private final static int KEY_BACK = 1002;
+ private final static int KEY_MENU = 1003;
+ private final static int KEY_SEARCH = 1004;
+ private final static int KEY_RECENT = 1005;
+ private final static int KEY_APP = 1006;
+ private GestureDetector mDetector;
+ private final static String TAG = "StylusGestureFilter";
+
+ public StylusGestureFilter() {
+ mDetector = new GestureDetector(this);
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ return mDetector.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+
+ final float xDistance = Math.abs(e1.getX() - e2.getX());
+ final float yDistance = Math.abs(e1.getY() - e2.getY());
+
+ velocityX = Math.abs(velocityX);
+ velocityY = Math.abs(velocityY);
+ boolean result = false;
+
+ if (velocityX > (SWIPE_MIN_VELOCITY * getResources().getDisplayMetrics().density)
+ && xDistance > (SWIPE_MIN_DISTANCE * getResources().getDisplayMetrics().density)
+ && xDistance > yDistance) {
+ if (e1.getX() > e2.getX()) { // right to left
+ // Swipe Left
+ dispatchStylusAction(SWIPE_LEFT);
+ } else {
+ // Swipe Right
+ dispatchStylusAction(SWIPE_RIGHT);
+ }
+ result = true;
+ } else if (velocityY > (SWIPE_MIN_VELOCITY * getResources().getDisplayMetrics().density)
+ && yDistance > (SWIPE_MIN_DISTANCE * getResources().getDisplayMetrics().density)
+ && yDistance > xDistance) {
+ if (e1.getY() > e2.getY()) { // bottom to up
+ // Swipe Up
+ dispatchStylusAction(SWIPE_UP);
+ } else {
+ // Swipe Down
+ dispatchStylusAction(SWIPE_DOWN);
+ }
+ result = true;
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent arg0) {
+ dispatchStylusAction(TAP_DOUBLE);
+ return true;
+ }
+
+ public void onLongPress(MotionEvent e) {
+ dispatchStylusAction(PRESS_LONG);
+ }
+
+ }
+
+ private void menuAction() {
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_MENU));
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
+ KeyEvent.KEYCODE_MENU));
+
+ }
+
+ private void backAction() {
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_BACK));
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
+ KeyEvent.KEYCODE_BACK));
+ }
+
+ private void dispatchStylusAction(int gestureAction) {
+ final ContentResolver resolver = mContext.getContentResolver();
+ boolean isSystemUI = mContext.getPackageName().equals("com.android.systemui");
+ String setting = null;
+ int dispatchAction = -1;
+ switch (gestureAction) {
+ case StylusGestureFilter.SWIPE_LEFT:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_LEFT_SWIPE);
+ break;
+ case StylusGestureFilter.SWIPE_RIGHT:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_RIGHT_SWIPE);
+ break;
+ case StylusGestureFilter.SWIPE_UP:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_UP_SWIPE);
+ break;
+ case StylusGestureFilter.SWIPE_DOWN:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_DOWN_SWIPE);
+ break;
+ case StylusGestureFilter.TAP_DOUBLE:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_DOUBLE_TAP);
+ break;
+ case StylusGestureFilter.PRESS_LONG:
+ setting = Settings.System.getString(resolver,
+ Settings.System.GESTURES_LONG_PRESS);
+ break;
+ default:
+ return;
+ }
+
+ try {
+ int value = Integer.valueOf(setting);
+ if (value == StylusGestureFilter.KEY_NO_ACTION) {
+ return;
+ }
+ dispatchAction = value;
+ } catch (NumberFormatException e) {
+ dispatchAction = StylusGestureFilter.KEY_APP;
+ }
+
+ // Dispatching action
+ switch (dispatchAction) {
+ case StylusGestureFilter.KEY_HOME:
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(homeIntent);
+ break;
+ case StylusGestureFilter.KEY_BACK:
+ backAction();
+ break;
+ case StylusGestureFilter.KEY_MENU:
+ // Menu action on notificationbar / systemui will be converted
+ // to back action
+ if (isSystemUI) {
+ backAction();
+ break;
+ }
+ menuAction();
+ break;
+ case StylusGestureFilter.KEY_SEARCH:
+ // Search action on notificationbar / systemui will be converted
+ // to back action
+ if (isSystemUI) {
+ backAction();
+ break;
+ }
+ launchDefaultSearch(new KeyEvent(KeyEvent.ACTION_UP,
+ KeyEvent.KEYCODE_SEARCH));
+ break;
+ case StylusGestureFilter.KEY_RECENT:
+ IStatusBarService mStatusBarService = IStatusBarService.Stub
+ .asInterface(ServiceManager.getService("statusbar"));
+ try {
+ mStatusBarService.toggleRecentApps();
+ } catch (RemoteException e) {
+ }
+ break;
+ case StylusGestureFilter.KEY_APP:
+ // Launching app on notificationbar / systemui will be preceded
+ // with a back Action
+ if (isSystemUI) {
+ backAction();
+ }
+ try {
+ final PackageManager pm = mContext.getPackageManager();
+ Intent launchIntent = pm.getLaunchIntentForPackage(setting);
+ if (launchIntent != null) {
+ mContext.startActivity(launchIntent);
+ }
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(mContext, mContext.getString(R.string.stylus_app_not_installed, setting),
+ Toast.LENGTH_LONG).show();
+ }
+ break;
+ }
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
+ // Stylus events with side button pressed are filtered and other
+ // events are processed normally.
+ if (mEnableGestures
+ && MotionEvent.BUTTON_SECONDARY == ev.getButtonState()) {
+ mStylusFilter.onTouchEvent(ev);
+ return false;
+ }
final Callback cb = getCallback();
return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
: super.dispatchTouchEvent(ev);
@@ -3255,6 +3511,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ mSettingsObserver.observe();
+
updateWindowResizeState();
final Callback cb = getCallback();
@@ -3278,6 +3536,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ mSettingsObserver.unobserve();
+
final Callback cb = getCallback();
if (cb != null && mFeatureId < 0) {
cb.onDetachedFromWindow();
diff --git a/core/java/com/android/internal/util/cm/ActionUtils.java b/core/java/com/android/internal/util/cm/ActionUtils.java
new file mode 100644
index 0000000..7e86cd3
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/ActionUtils.java
@@ -0,0 +1,149 @@
+package com.android.internal.util.cm;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import android.view.HapticFeedbackConstants;
+import android.widget.Toast;
+import com.android.internal.R;
+
+import java.util.List;
+
+public class ActionUtils {
+ private static final boolean DEBUG = false;
+ private static final String TAG = ActionUtils.class.getSimpleName();
+ private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
+
+ /**
+ * Kills the top most / most recent user application, but leaves out the launcher.
+ * This is function governed by {@link CMSettings.Secure.KILL_APP_LONGPRESS_BACK}.
+ *
+ * @param context the current context, used to retrieve the package manager.
+ * @param userId the ID of the currently active user
+ * @return {@code true} when a user application was found and closed.
+ */
+ public static boolean killForegroundApp(Context context, int userId) {
+ try {
+ return killForegroundAppInternal(context, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not kill foreground app");
+ }
+ return false;
+ }
+
+ private static boolean killForegroundAppInternal(Context context, int userId)
+ throws RemoteException {
+ try {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ String defaultHomePackage = "com.android.launcher";
+ intent.addCategory(Intent.CATEGORY_HOME);
+ final ResolveInfo res = context.getPackageManager().resolveActivity(intent, 0);
+
+ if (res.activityInfo != null && !res.activityInfo.packageName.equals("android")) {
+ defaultHomePackage = res.activityInfo.packageName;
+ }
+
+ IActivityManager am = ActivityManagerNative.getDefault();
+ List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses();
+ for (ActivityManager.RunningAppProcessInfo appInfo : apps) {
+ int uid = appInfo.uid;
+ // Make sure it's a foreground user application (not system,
+ // root, phone, etc.)
+ if (uid >= Process.FIRST_APPLICATION_UID && uid <= Process.LAST_APPLICATION_UID
+ && appInfo.importance ==
+ ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
+ if (appInfo.pkgList != null && (appInfo.pkgList.length > 0)) {
+ for (String pkg : appInfo.pkgList) {
+ if (!pkg.equals("com.android.systemui")
+ && !pkg.equals(defaultHomePackage)) {
+ am.forceStopPackage(pkg, UserHandle.USER_CURRENT);
+ return true;
+ }
+ }
+ } else {
+ Process.killProcess(appInfo.pid);
+ return true;
+ }
+ }
+ }
+ } catch (RemoteException remoteException) {
+ // Do nothing; just let it go.
+ }
+ return false;
+ }
+
+ /**
+ * Attempt to bring up the last activity in the stack before the current active one.
+ *
+ * @param context
+ * @return whether an activity was found to switch to
+ */
+ public static boolean switchToLastApp(Context context, int userId) {
+ try {
+ return switchToLastAppInternal(context, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not switch to last app");
+ }
+ return false;
+ }
+
+ private static boolean switchToLastAppInternal(Context context, int userId)
+ throws RemoteException {
+ ActivityManager.RecentTaskInfo lastTask = getLastTask(context, userId);
+
+ if (lastTask == null || lastTask.id < 0) {
+ return false;
+ }
+
+ final String packageName = lastTask.baseIntent.getComponent().getPackageName();
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ final ActivityOptions opts = ActivityOptions.makeCustomAnimation(context,
+ com.android.internal.R.anim.last_app_in,
+ com.android.internal.R.anim.last_app_out);
+
+ if (DEBUG) Log.d(TAG, "switching to " + packageName);
+ am.moveTaskToFront(lastTask.id, ActivityManager.MOVE_TASK_NO_USER_ACTION, opts.toBundle());
+
+ return true;
+ }
+
+ private static ActivityManager.RecentTaskInfo getLastTask(Context context, int userId)
+ throws RemoteException {
+ final String defaultHomePackage = resolveCurrentLauncherPackage(context, userId);
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ final List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasks(5,
+ ActivityManager.RECENT_IGNORE_UNAVAILABLE, userId);
+
+ for (int i = 1; i < tasks.size(); i++) {
+ ActivityManager.RecentTaskInfo task = tasks.get(i);
+ if (task.origActivity != null) {
+ task.baseIntent.setComponent(task.origActivity);
+ }
+ String packageName = task.baseIntent.getComponent().getPackageName();
+ if (!packageName.equals(defaultHomePackage)
+ && !packageName.equals(SYSTEMUI_PACKAGE)) {
+ return tasks.get(i);
+ }
+ }
+
+ return null;
+ }
+
+ private static String resolveCurrentLauncherPackage(Context context, int userId) {
+ final Intent launcherIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME);
+ final PackageManager pm = context.getPackageManager();
+ final ResolveInfo launcherInfo = pm.resolveActivityAsUser(launcherIntent, 0, userId);
+ return launcherInfo.activityInfo.packageName;
+ }
+}
diff --git a/core/java/com/android/internal/util/cm/PowerMenuConstants.java b/core/java/com/android/internal/util/cm/PowerMenuConstants.java
new file mode 100644
index 0000000..3debd09
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/PowerMenuConstants.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.cm;
+
+/* Master list of all actions for the power menu */
+public class PowerMenuConstants {
+ public static final String GLOBAL_ACTION_KEY_POWER = "power";
+ public static final String GLOBAL_ACTION_KEY_REBOOT = "reboot";
+ public static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
+ public static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane";
+ public static final String GLOBAL_ACTION_KEY_USERS = "users";
+ public static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
+ public static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
+ public static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport";
+ public static final String GLOBAL_ACTION_KEY_SILENT = "silent";
+ public static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
+ public static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
+
+ private static String[] ALL_ACTIONS = {
+ GLOBAL_ACTION_KEY_POWER,
+ GLOBAL_ACTION_KEY_REBOOT,
+ GLOBAL_ACTION_KEY_SCREENSHOT,
+ GLOBAL_ACTION_KEY_AIRPLANE,
+ GLOBAL_ACTION_KEY_USERS,
+ GLOBAL_ACTION_KEY_SETTINGS,
+ GLOBAL_ACTION_KEY_LOCKDOWN,
+ GLOBAL_ACTION_KEY_BUGREPORT,
+ GLOBAL_ACTION_KEY_SILENT,
+ GLOBAL_ACTION_KEY_VOICEASSIST,
+ GLOBAL_ACTION_KEY_ASSIST
+ };
+
+ public static String[] getAllActions() {
+ return ALL_ACTIONS;
+ }
+}
diff --git a/core/java/com/android/internal/util/cm/SpamFilter.java b/core/java/com/android/internal/util/cm/SpamFilter.java
new file mode 100644
index 0000000..9de4489
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/SpamFilter.java
@@ -0,0 +1,65 @@
+package com.android.internal.util.cm;
+
+import android.app.Notification;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+public class SpamFilter {
+
+ public static final String AUTHORITY = "com.cyanogenmod.spam";
+ public static final String MESSAGE_PATH = "message";
+ public static final Uri NOTIFICATION_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendEncodedPath(MESSAGE_PATH)
+ .build();
+
+ public static final class SpamContract {
+
+ public static final class PackageTable {
+ public static final String TABLE_NAME = "packages";
+ public static final String ID = "_id";
+ public static final String PACKAGE_NAME = "package_name";
+ }
+
+ public static final class NotificationTable {
+ public static final String TABLE_NAME = "notifications";
+ public static final String ID = "_id";
+ public static final String PACKAGE_ID = "package_id";
+ public static final String MESSAGE_TEXT = "message_text";
+ public static final String COUNT = "count";
+ public static final String LAST_BLOCKED = "last_blocked";
+ public static final String NORMALIZED_TEXT = "normalized_text";
+ }
+
+ }
+
+ public static String getNormalizedContent(String msg) {
+ return msg.toLowerCase().replaceAll("[^\\p{L}\\p{Nd}]+", "");
+ }
+
+ public static String getNormalizedNotificationContent(Notification notification) {
+ String content = getNotificationContent(notification);
+ return getNormalizedContent(content);
+ }
+
+ public static String getNotificationContent(Notification notification) {
+ Bundle extras = notification.extras;
+ String titleExtra = extras.containsKey(Notification.EXTRA_TITLE_BIG)
+ ? Notification.EXTRA_TITLE_BIG : Notification.EXTRA_TITLE;
+ CharSequence notificationTitle = extras.getCharSequence(titleExtra);
+ CharSequence notificationMessage = extras.getCharSequence(Notification.EXTRA_TEXT);
+
+ if (TextUtils.isEmpty(notificationMessage)) {
+ CharSequence[] inboxLines = extras.getCharSequenceArray(Notification.EXTRA_TEXT_LINES);
+ if (inboxLines == null || inboxLines.length == 0) {
+ notificationMessage = "";
+ } else {
+ notificationMessage = TextUtils.join("\n", inboxLines);
+ }
+ }
+ return notificationTitle + "\n" + notificationMessage;
+ }
+}
diff --git a/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java b/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java
new file mode 100644
index 0000000..a24dff8
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.cm.palette;
+
+import android.graphics.Color;
+import com.android.internal.util.cm.palette.Palette.Swatch;
+import android.util.TimingLogger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+
+/**
+ * An color quantizer based on the Median-cut algorithm, but optimized for picking out distinct
+ * colors rather than representation colors.
+ *
+ * The color space is represented as a 3-dimensional cube with each dimension being an RGB
+ * component. The cube is then repeatedly divided until we have reduced the color space to the
+ * requested number of colors. An average color is then generated from each cube.
+ *
+ * What makes this different to median-cut is that median-cut divided cubes so that all of the cubes
+ * have roughly the same population, where this quantizer divides boxes based on their color volume.
+ * This means that the color space is divided into distinct colors, rather than representative
+ * colors.
+ *
+ * @hide
+ */
+final class ColorCutQuantizer {
+
+ private static final String LOG_TAG = "ColorCutQuantizer";
+ private static final boolean LOG_TIMINGS = false;
+
+ private static final int COMPONENT_RED = -3;
+ private static final int COMPONENT_GREEN = -2;
+ private static final int COMPONENT_BLUE = -1;
+
+ private static final int QUANTIZE_WORD_WIDTH = 5;
+ private static final int QUANTIZE_WORD_MASK = (1 << QUANTIZE_WORD_WIDTH) - 1;
+
+ final int[] mColors;
+ final int[] mHistogram;
+ final List<Swatch> mQuantizedColors;
+ final TimingLogger mTimingLogger;
+ final Palette.Filter[] mFilters;
+
+ private final float[] mTempHsl = new float[3];
+
+ /**
+ * Constructor.
+ *
+ * @param pixels histogram representing an image's pixel data
+ * @param maxColors The maximum number of colors that should be in the result palette.
+ * @param filters Set of filters to use in the quantization stage
+ */
+ ColorCutQuantizer(final int[] pixels, final int maxColors, final Palette.Filter[] filters) {
+ mTimingLogger = LOG_TIMINGS ? new TimingLogger(LOG_TAG, "Creation") : null;
+ mFilters = filters;
+
+ final int[] hist = mHistogram = new int[1 << (QUANTIZE_WORD_WIDTH * 3)];
+ for (int i = 0; i < pixels.length; i++) {
+ final int quantizedColor = quantizeFromRgb888(pixels[i]);
+ // Now update the pixel value to the quantized value
+ pixels[i] = quantizedColor;
+ // And update the histogram
+ hist[quantizedColor]++;
+ }
+
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("Histogram created");
+ }
+
+ // Now let's count the number of distinct colors
+ int distinctColorCount = 0;
+ for (int color = 0; color < hist.length; color++) {
+ if (hist[color] > 0 && shouldIgnoreColor(color)) {
+ // If we should ignore the color, set the population to 0
+ hist[color] = 0;
+ }
+ if (hist[color] > 0) {
+ // If the color has population, increase the distinct color count
+ distinctColorCount++;
+ }
+ }
+
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("Filtered colors and distinct colors counted");
+ }
+
+ // Now lets go through create an array consisting of only distinct colors
+ final int[] colors = mColors = new int[distinctColorCount];
+ int distinctColorIndex = 0;
+ for (int color = 0; color < hist.length; color++) {
+ if (hist[color] > 0) {
+ colors[distinctColorIndex++] = color;
+ }
+ }
+
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("Distinct colors copied into array");
+ }
+
+ if (distinctColorCount <= maxColors) {
+ // The image has fewer colors than the maximum requested, so just return the colors
+ mQuantizedColors = new ArrayList<>();
+ for (int color : colors) {
+ mQuantizedColors.add(new Swatch(approximateToRgb888(color), hist[color]));
+ }
+
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("Too few colors present. Copied to Swatches");
+ mTimingLogger.dumpToLog();
+ }
+ } else {
+ // We need use quantization to reduce the number of colors
+ mQuantizedColors = quantizePixels(maxColors);
+
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("Quantized colors computed");
+ mTimingLogger.dumpToLog();
+ }
+ }
+ }
+
+ /**
+ * @return the list of quantized colors
+ */
+ List<Swatch> getQuantizedColors() {
+ return mQuantizedColors;
+ }
+
+ private List<Swatch> quantizePixels(int maxColors) {
+ // Create the priority queue which is sorted by volume descending. This means we always
+ // split the largest box in the queue
+ final PriorityQueue<Vbox> pq = new PriorityQueue<>(maxColors, VBOX_COMPARATOR_VOLUME);
+
+ // To start, offer a box which contains all of the colors
+ pq.offer(new Vbox(0, mColors.length - 1));
+
+ // Now go through the boxes, splitting them until we have reached maxColors or there are no
+ // more boxes to split
+ splitBoxes(pq, maxColors);
+
+ // Finally, return the average colors of the color boxes
+ return generateAverageColors(pq);
+ }
+
+ /**
+ * Iterate through the {@link java.util.Queue}, popping
+ * {@link ColorCutQuantizer.Vbox} objects from the queue
+ * and splitting them. Once split, the new box and the remaining box are offered back to the
+ * queue.
+ *
+ * @param queue {@link java.util.PriorityQueue} to poll for boxes
+ * @param maxSize Maximum amount of boxes to split
+ */
+ private void splitBoxes(final PriorityQueue<Vbox> queue, final int maxSize) {
+ while (queue.size() < maxSize) {
+ final Vbox vbox = queue.poll();
+
+ if (vbox != null && vbox.canSplit()) {
+ // First split the box, and offer the result
+ queue.offer(vbox.splitBox());
+
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("Box split");
+ }
+ // Then offer the box back
+ queue.offer(vbox);
+ } else {
+ if (LOG_TIMINGS) {
+ mTimingLogger.addSplit("All boxes split");
+ }
+ // If we get here then there are no more boxes to split, so return
+ return;
+ }
+ }
+ }
+
+ private List<Swatch> generateAverageColors(Collection<Vbox> vboxes) {
+ ArrayList<Swatch> colors = new ArrayList<>(vboxes.size());
+ for (Vbox vbox : vboxes) {
+ Swatch swatch = vbox.getAverageColor();
+ if (!shouldIgnoreColor(swatch)) {
+ // As we're averaging a color box, we can still get colors which we do not want, so
+ // we check again here
+ colors.add(swatch);
+ }
+ }
+ return colors;
+ }
+
+ /**
+ * Represents a tightly fitting box around a color space.
+ */
+ private class Vbox {
+ // lower and upper index are inclusive
+ private int mLowerIndex;
+ private int mUpperIndex;
+ // Population of colors within this box
+ private int mPopulation;
+
+ private int mMinRed, mMaxRed;
+ private int mMinGreen, mMaxGreen;
+ private int mMinBlue, mMaxBlue;
+
+ Vbox(int lowerIndex, int upperIndex) {
+ mLowerIndex = lowerIndex;
+ mUpperIndex = upperIndex;
+ fitBox();
+ }
+
+ final int getVolume() {
+ return (mMaxRed - mMinRed + 1) * (mMaxGreen - mMinGreen + 1) *
+ (mMaxBlue - mMinBlue + 1);
+ }
+
+ final boolean canSplit() {
+ return getColorCount() > 1;
+ }
+
+ final int getColorCount() {
+ return 1 + mUpperIndex - mLowerIndex;
+ }
+
+ /**
+ * Recomputes the boundaries of this box to tightly fit the colors within the box.
+ */
+ final void fitBox() {
+ final int[] colors = mColors;
+ final int[] hist = mHistogram;
+
+ // Reset the min and max to opposite values
+ int minRed, minGreen, minBlue;
+ minRed = minGreen = minBlue = Integer.MAX_VALUE;
+ int maxRed, maxGreen, maxBlue;
+ maxRed = maxGreen = maxBlue = Integer.MIN_VALUE;
+ int count = 0;
+
+ for (int i = mLowerIndex; i <= mUpperIndex; i++) {
+ final int color = colors[i];
+ count += hist[color];
+
+ final int r = quantizedRed(color);
+ final int g = quantizedGreen(color);
+ final int b = quantizedBlue(color);
+ if (r > maxRed) {
+ maxRed = r;
+ }
+ if (r < minRed) {
+ minRed = r;
+ }
+ if (g > maxGreen) {
+ maxGreen = g;
+ }
+ if (g < minGreen) {
+ minGreen = g;
+ }
+ if (b > maxBlue) {
+ maxBlue = b;
+ }
+ if (b < minBlue) {
+ minBlue = b;
+ }
+ }
+
+ mMinRed = minRed;
+ mMaxRed = maxRed;
+ mMinGreen = minGreen;
+ mMaxGreen = maxGreen;
+ mMinBlue = minBlue;
+ mMaxBlue = maxBlue;
+ mPopulation = count;
+ }
+
+ /**
+ * Split this color box at the mid-point along it's longest dimension
+ *
+ * @return the new ColorBox
+ */
+ final Vbox splitBox() {
+ if (!canSplit()) {
+ throw new IllegalStateException("Can not split a box with only 1 color");
+ }
+
+ // find median along the longest dimension
+ final int splitPoint = findSplitPoint();
+
+ Vbox newBox = new Vbox(splitPoint + 1, mUpperIndex);
+
+ // Now change this box's upperIndex and recompute the color boundaries
+ mUpperIndex = splitPoint;
+ fitBox();
+
+ return newBox;
+ }
+
+ /**
+ * @return the dimension which this box is largest in
+ */
+ final int getLongestColorDimension() {
+ final int redLength = mMaxRed - mMinRed;
+ final int greenLength = mMaxGreen - mMinGreen;
+ final int blueLength = mMaxBlue - mMinBlue;
+
+ if (redLength >= greenLength && redLength >= blueLength) {
+ return COMPONENT_RED;
+ } else if (greenLength >= redLength && greenLength >= blueLength) {
+ return COMPONENT_GREEN;
+ } else {
+ return COMPONENT_BLUE;
+ }
+ }
+
+ /**
+ * Finds the point within this box's lowerIndex and upperIndex index of where to split.
+ *
+ * This is calculated by finding the longest color dimension, and then sorting the
+ * sub-array based on that dimension value in each color. The colors are then iterated over
+ * until a color is found with at least the midpoint of the whole box's dimension midpoint.
+ *
+ * @return the index of the colors array to split from
+ */
+ final int findSplitPoint() {
+ final int longestDimension = getLongestColorDimension();
+ final int[] colors = mColors;
+ final int[] hist = mHistogram;
+
+ // We need to sort the colors in this box based on the longest color dimension.
+ // As we can't use a Comparator to define the sort logic, we modify each color so that
+ // it's most significant is the desired dimension
+ modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
+
+ // Now sort... Arrays.sort uses a exclusive toIndex so we need to add 1
+ Arrays.sort(colors, mLowerIndex, mUpperIndex + 1);
+
+ // Now revert all of the colors so that they are packed as RGB again
+ modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
+
+ final int midPoint = mPopulation / 2;
+ for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++) {
+ count += hist[colors[i]];
+ if (count >= midPoint) {
+ return i;
+ }
+ }
+
+ return mLowerIndex;
+ }
+
+ /**
+ * @return the average color of this box.
+ */
+ final Swatch getAverageColor() {
+ final int[] colors = mColors;
+ final int[] hist = mHistogram;
+ int redSum = 0;
+ int greenSum = 0;
+ int blueSum = 0;
+ int totalPopulation = 0;
+
+ for (int i = mLowerIndex; i <= mUpperIndex; i++) {
+ final int color = colors[i];
+ final int colorPopulation = hist[color];
+
+ totalPopulation += colorPopulation;
+ redSum += colorPopulation * quantizedRed(color);
+ greenSum += colorPopulation * quantizedGreen(color);
+ blueSum += colorPopulation * quantizedBlue(color);
+ }
+
+ final int redMean = Math.round(redSum / (float) totalPopulation);
+ final int greenMean = Math.round(greenSum / (float) totalPopulation);
+ final int blueMean = Math.round(blueSum / (float) totalPopulation);
+
+ return new Swatch(approximateToRgb888(redMean, greenMean, blueMean), totalPopulation);
+ }
+ }
+
+ /**
+ * Modify the significant octet in a packed color int. Allows sorting based on the value of a
+ * single color component. This relies on all components being the same word size.
+ *
+ * @see Vbox#findSplitPoint()
+ */
+ private static void modifySignificantOctet(final int[] a, final int dimension,
+ final int lower, final int upper) {
+ switch (dimension) {
+ case COMPONENT_RED:
+ // Already in RGB, no need to do anything
+ break;
+ case COMPONENT_GREEN:
+ // We need to do a RGB to GRB swap, or vice-versa
+ for (int i = lower; i <= upper; i++) {
+ final int color = a[i];
+ a[i] = quantizedGreen(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)
+ | quantizedRed(color) << QUANTIZE_WORD_WIDTH
+ | quantizedBlue(color);
+ }
+ break;
+ case COMPONENT_BLUE:
+ // We need to do a RGB to BGR swap, or vice-versa
+ for (int i = lower; i <= upper; i++) {
+ final int color = a[i];
+ a[i] = quantizedBlue(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)
+ | quantizedGreen(color) << QUANTIZE_WORD_WIDTH
+ | quantizedRed(color);
+ }
+ break;
+ }
+ }
+
+ private boolean shouldIgnoreColor(int color565) {
+ final int rgb = approximateToRgb888(color565);
+ ColorUtils.colorToHSL(rgb, mTempHsl);
+ return shouldIgnoreColor(rgb, mTempHsl);
+ }
+
+ private boolean shouldIgnoreColor(Swatch color) {
+ return shouldIgnoreColor(color.getRgb(), color.getHsl());
+ }
+
+ private boolean shouldIgnoreColor(int rgb, float[] hsl) {
+ if (mFilters != null && mFilters.length > 0) {
+ for (int i = 0, count = mFilters.length; i < count; i++) {
+ if (!mFilters[i].isAllowed(rgb, hsl)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Comparator which sorts {@link Vbox} instances based on their volume, in descending order
+ */
+ private static final Comparator<Vbox> VBOX_COMPARATOR_VOLUME = new Comparator<Vbox>() {
+ @Override
+ public int compare(Vbox lhs, Vbox rhs) {
+ return rhs.getVolume() - lhs.getVolume();
+ }
+ };
+
+ /**
+ * Quantized a RGB888 value to have a word width of {@value #QUANTIZE_WORD_WIDTH}.
+ */
+ private static int quantizeFromRgb888(int color) {
+ int r = modifyWordWidth(Color.red(color), 8, QUANTIZE_WORD_WIDTH);
+ int g = modifyWordWidth(Color.green(color), 8, QUANTIZE_WORD_WIDTH);
+ int b = modifyWordWidth(Color.blue(color), 8, QUANTIZE_WORD_WIDTH);
+ return r << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH) | g << QUANTIZE_WORD_WIDTH | b;
+ }
+
+ /**
+ * Quantized RGB888 values to have a word width of {@value #QUANTIZE_WORD_WIDTH}.
+ */
+ private static int approximateToRgb888(int r, int g, int b) {
+ return Color.rgb(modifyWordWidth(r, QUANTIZE_WORD_WIDTH, 8),
+ modifyWordWidth(g, QUANTIZE_WORD_WIDTH, 8),
+ modifyWordWidth(b, QUANTIZE_WORD_WIDTH, 8));
+ }
+
+ private static int approximateToRgb888(int color) {
+ return approximateToRgb888(quantizedRed(color), quantizedGreen(color), quantizedBlue(color));
+ }
+
+ /**
+ * @return red component of the quantized color
+ */
+ private static int quantizedRed(int color) {
+ return (color >> (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)) & QUANTIZE_WORD_MASK;
+ }
+
+ /**
+ * @return green component of a quantized color
+ */
+ private static int quantizedGreen(int color) {
+ return (color >> QUANTIZE_WORD_WIDTH) & QUANTIZE_WORD_MASK;
+ }
+
+ /**
+ * @return blue component of a quantized color
+ */
+ private static int quantizedBlue(int color) {
+ return color & QUANTIZE_WORD_MASK;
+ }
+
+ private static int modifyWordWidth(int value, int currentWidth, int targetWidth) {
+ final int newValue;
+ if (targetWidth > currentWidth) {
+ // If we're approximating up in word width, we'll shift up
+ newValue = value << (targetWidth - currentWidth);
+ } else {
+ // Else, we will just shift and keep the MSB
+ newValue = value >> (currentWidth - targetWidth);
+ }
+ return newValue & ((1 << targetWidth) - 1);
+ }
+
+}
diff --git a/core/java/com/android/internal/util/cm/palette/ColorUtils.java b/core/java/com/android/internal/util/cm/palette/ColorUtils.java
new file mode 100644
index 0000000..8dcf750
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/palette/ColorUtils.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.cm.palette;
+
+import android.graphics.Color;
+
+/**
+ * A set of color-related utility methods, building upon those available in {@code Color}.
+ *
+ * @hide
+ */
+public class ColorUtils {
+
+ private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10;
+ private static final int MIN_ALPHA_SEARCH_PRECISION = 10;
+
+ private ColorUtils() {}
+
+ /**
+ * Composite two potentially translucent colors over each other and returns the result.
+ */
+ public static int compositeColors(int foreground, int background) {
+ int bgAlpha = Color.alpha(background);
+ int fgAlpha = Color.alpha(foreground);
+ int a = compositeAlpha(fgAlpha, bgAlpha);
+
+ int r = compositeComponent(Color.red(foreground), fgAlpha,
+ Color.red(background), bgAlpha, a);
+ int g = compositeComponent(Color.green(foreground), fgAlpha,
+ Color.green(background), bgAlpha, a);
+ int b = compositeComponent(Color.blue(foreground), fgAlpha,
+ Color.blue(background), bgAlpha, a);
+
+ return Color.argb(a, r, g, b);
+ }
+
+ private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+ return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+ }
+
+ private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+ if (a == 0) return 0;
+ return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+ }
+
+ /**
+ * Returns the luminance of a color.
+ *
+ * Formula defined here: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ */
+ public static double calculateLuminance(int color) {
+ double red = Color.red(color) / 255d;
+ red = red < 0.03928 ? red / 12.92 : Math.pow((red + 0.055) / 1.055, 2.4);
+
+ double green = Color.green(color) / 255d;
+ green = green < 0.03928 ? green / 12.92 : Math.pow((green + 0.055) / 1.055, 2.4);
+
+ double blue = Color.blue(color) / 255d;
+ blue = blue < 0.03928 ? blue / 12.92 : Math.pow((blue + 0.055) / 1.055, 2.4);
+
+ return (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
+ }
+
+ /**
+ * Returns the contrast ratio between {@code foreground} and {@code background}.
+ * {@code background} must be opaque.
+ * <p>
+ * Formula defined
+ * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef">here</a>.
+ */
+ public static double calculateContrast(int foreground, int background) {
+ if (Color.alpha(background) != 255) {
+ throw new IllegalArgumentException("background can not be translucent");
+ }
+ if (Color.alpha(foreground) < 255) {
+ // If the foreground is translucent, composite the foreground over the background
+ foreground = compositeColors(foreground, background);
+ }
+
+ final double luminance1 = calculateLuminance(foreground) + 0.05;
+ final double luminance2 = calculateLuminance(background) + 0.05;
+
+ // Now return the lighter luminance divided by the darker luminance
+ return Math.max(luminance1, luminance2) / Math.min(luminance1, luminance2);
+ }
+
+ /**
+ * Calculates the minimum alpha value which can be applied to {@code foreground} so that would
+ * have a contrast value of at least {@code minContrastRatio} when compared to
+ * {@code background}.
+ *
+ * @param foreground the foreground color.
+ * @param background the background color. Should be opaque.
+ * @param minContrastRatio the minimum contrast ratio.
+ * @return the alpha value in the range 0-255, or -1 if no value could be calculated.
+ */
+ public static int calculateMinimumAlpha(int foreground, int background,
+ float minContrastRatio) {
+ if (Color.alpha(background) != 255) {
+ throw new IllegalArgumentException("background can not be translucent");
+ }
+
+ // First lets check that a fully opaque foreground has sufficient contrast
+ int testForeground = setAlphaComponent(foreground, 255);
+ double testRatio = calculateContrast(testForeground, background);
+ if (testRatio < minContrastRatio) {
+ // Fully opaque foreground does not have sufficient contrast, return error
+ return -1;
+ }
+
+ // Binary search to find a value with the minimum value which provides sufficient contrast
+ int numIterations = 0;
+ int minAlpha = 0;
+ int maxAlpha = 255;
+
+ while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS &&
+ (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) {
+ final int testAlpha = (minAlpha + maxAlpha) / 2;
+
+ testForeground = setAlphaComponent(foreground, testAlpha);
+ testRatio = calculateContrast(testForeground, background);
+
+ if (testRatio < minContrastRatio) {
+ minAlpha = testAlpha;
+ } else {
+ maxAlpha = testAlpha;
+ }
+
+ numIterations++;
+ }
+
+ // Conservatively return the max of the range of possible alphas, which is known to pass.
+ return maxAlpha;
+ }
+
+ /**
+ * Convert RGB components to HSL (hue-saturation-lightness).
+ * <ul>
+ * <li>hsl[0] is Hue [0 .. 360)</li>
+ * <li>hsl[1] is Saturation [0...1]</li>
+ * <li>hsl[2] is Lightness [0...1]</li>
+ * </ul>
+ *
+ * @param r red component value [0..255]
+ * @param g green component value [0..255]
+ * @param b blue component value [0..255]
+ * @param hsl 3 element array which holds the resulting HSL components.
+ */
+ public static void RGBToHSL(int r, int g, int b, float[] hsl) {
+ final float rf = r / 255f;
+ final float gf = g / 255f;
+ final float bf = b / 255f;
+
+ final float max = Math.max(rf, Math.max(gf, bf));
+ final float min = Math.min(rf, Math.min(gf, bf));
+ final float deltaMaxMin = max - min;
+
+ float h, s;
+ float l = (max + min) / 2f;
+
+ if (max == min) {
+ // Monochromatic
+ h = s = 0f;
+ } else {
+ if (max == rf) {
+ h = ((gf - bf) / deltaMaxMin) % 6f;
+ } else if (max == gf) {
+ h = ((bf - rf) / deltaMaxMin) + 2f;
+ } else {
+ h = ((rf - gf) / deltaMaxMin) + 4f;
+ }
+
+ s = deltaMaxMin / (1f - Math.abs(2f * l - 1f));
+ }
+
+ h = (h * 60f) % 360f;
+ if (h < 0) {
+ h += 360f;
+ }
+
+ hsl[0] = constrain(h, 0f, 360f);
+ hsl[1] = constrain(s, 0f, 1f);
+ hsl[2] = constrain(l, 0f, 1f);
+ }
+
+ /**
+ * Convert the ARGB color to its HSL (hue-saturation-lightness) components.
+ * <ul>
+ * <li>hsl[0] is Hue [0 .. 360)</li>
+ * <li>hsl[1] is Saturation [0...1]</li>
+ * <li>hsl[2] is Lightness [0...1]</li>
+ * </ul>
+ *
+ * @param color the ARGB color to convert. The alpha component is ignored.
+ * @param hsl 3 element array which holds the resulting HSL components.
+ */
+ public static void colorToHSL(int color, float[] hsl) {
+ RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl);
+ }
+
+ /**
+ * Convert HSL (hue-saturation-lightness) components to a RGB color.
+ * <ul>
+ * <li>hsl[0] is Hue [0 .. 360)</li>
+ * <li>hsl[1] is Saturation [0...1]</li>
+ * <li>hsl[2] is Lightness [0...1]</li>
+ * </ul>
+ * If hsv values are out of range, they are pinned.
+ *
+ * @param hsl 3 element array which holds the input HSL components.
+ * @return the resulting RGB color
+ */
+ public static int HSLToColor(float[] hsl) {
+ final float h = hsl[0];
+ final float s = hsl[1];
+ final float l = hsl[2];
+
+ final float c = (1f - Math.abs(2 * l - 1f)) * s;
+ final float m = l - 0.5f * c;
+ final float x = c * (1f - Math.abs((h / 60f % 2f) - 1f));
+
+ final int hueSegment = (int) h / 60;
+
+ int r = 0, g = 0, b = 0;
+
+ switch (hueSegment) {
+ case 0:
+ r = Math.round(255 * (c + m));
+ g = Math.round(255 * (x + m));
+ b = Math.round(255 * m);
+ break;
+ case 1:
+ r = Math.round(255 * (x + m));
+ g = Math.round(255 * (c + m));
+ b = Math.round(255 * m);
+ break;
+ case 2:
+ r = Math.round(255 * m);
+ g = Math.round(255 * (c + m));
+ b = Math.round(255 * (x + m));
+ break;
+ case 3:
+ r = Math.round(255 * m);
+ g = Math.round(255 * (x + m));
+ b = Math.round(255 * (c + m));
+ break;
+ case 4:
+ r = Math.round(255 * (x + m));
+ g = Math.round(255 * m);
+ b = Math.round(255 * (c + m));
+ break;
+ case 5:
+ case 6:
+ r = Math.round(255 * (c + m));
+ g = Math.round(255 * m);
+ b = Math.round(255 * (x + m));
+ break;
+ }
+
+ r = constrain(r, 0, 255);
+ g = constrain(g, 0, 255);
+ b = constrain(b, 0, 255);
+
+ return Color.rgb(r, g, b);
+ }
+
+ /**
+ * Set the alpha component of {@code color} to be {@code alpha}.
+ */
+ public static int setAlphaComponent(int color, int alpha) {
+ if (alpha < 0 || alpha > 255) {
+ throw new IllegalArgumentException("alpha must be between 0 and 255.");
+ }
+ return (color & 0x00ffffff) | (alpha << 24);
+ }
+
+ private static float constrain(float amount, float low, float high) {
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
+ private static int constrain(int amount, int low, int high) {
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
+}
diff --git a/core/java/com/android/internal/util/cm/palette/DefaultGenerator.java b/core/java/com/android/internal/util/cm/palette/DefaultGenerator.java
new file mode 100644
index 0000000..407f01d
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/palette/DefaultGenerator.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.cm.palette;
+
+import com.android.internal.util.cm.palette.Palette.Swatch;
+
+import java.util.List;
+
+/**
+ * @hide
+ */
+class DefaultGenerator extends Palette.Generator {
+
+ private static final float TARGET_DARK_LUMA = 0.26f;
+ private static final float MAX_DARK_LUMA = 0.45f;
+
+ private static final float MIN_LIGHT_LUMA = 0.55f;
+ private static final float TARGET_LIGHT_LUMA = 0.74f;
+
+ private static final float MIN_NORMAL_LUMA = 0.3f;
+ private static final float TARGET_NORMAL_LUMA = 0.5f;
+ private static final float MAX_NORMAL_LUMA = 0.7f;
+
+ private static final float TARGET_MUTED_SATURATION = 0.3f;
+ private static final float MAX_MUTED_SATURATION = 0.4f;
+
+ private static final float TARGET_VIBRANT_SATURATION = 1f;
+ private static final float MIN_VIBRANT_SATURATION = 0.35f;
+
+ private static final float WEIGHT_SATURATION = 3f;
+ private static final float WEIGHT_LUMA = 6f;
+ private static final float WEIGHT_POPULATION = 1f;
+
+ private List<Swatch> mSwatches;
+
+ private int mHighestPopulation;
+
+ private Swatch mVibrantSwatch;
+ private Swatch mMutedSwatch;
+ private Swatch mDarkVibrantSwatch;
+ private Swatch mDarkMutedSwatch;
+ private Swatch mLightVibrantSwatch;
+ private Swatch mLightMutedSwatch;
+
+ @Override
+ public void generate(final List<Swatch> swatches) {
+ mSwatches = swatches;
+
+ mHighestPopulation = findMaxPopulation();
+
+ generateVariationColors();
+
+ // Now try and generate any missing colors
+ generateEmptySwatches();
+ }
+
+ @Override
+ public Swatch getVibrantSwatch() {
+ return mVibrantSwatch;
+ }
+
+ @Override
+ public Swatch getLightVibrantSwatch() {
+ return mLightVibrantSwatch;
+ }
+
+ @Override
+ public Swatch getDarkVibrantSwatch() {
+ return mDarkVibrantSwatch;
+ }
+
+ @Override
+ public Swatch getMutedSwatch() {
+ return mMutedSwatch;
+ }
+
+ @Override
+ public Swatch getLightMutedSwatch() {
+ return mLightMutedSwatch;
+ }
+
+ @Override
+ public Swatch getDarkMutedSwatch() {
+ return mDarkMutedSwatch;
+ }
+
+ private void generateVariationColors() {
+ mVibrantSwatch = findColorVariation(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA,
+ TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
+
+ mLightVibrantSwatch = findColorVariation(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f,
+ TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
+
+ mDarkVibrantSwatch = findColorVariation(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA,
+ TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
+
+ mMutedSwatch = findColorVariation(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA,
+ TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
+
+ mLightMutedSwatch = findColorVariation(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f,
+ TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
+
+ mDarkMutedSwatch = findColorVariation(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA,
+ TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
+ }
+
+ /**
+ * Try and generate any missing swatches from the swatches we did find.
+ */
+ private void generateEmptySwatches() {
+ if (mVibrantSwatch == null) {
+ // If we do not have a vibrant color...
+ if (mDarkVibrantSwatch != null) {
+ // ...but we do have a dark vibrant, generate the value by modifying the luma
+ final float[] newHsl = copyHslValues(mDarkVibrantSwatch);
+ newHsl[2] = TARGET_NORMAL_LUMA;
+ mVibrantSwatch = new Swatch(ColorUtils.HSLToColor(newHsl), 0);
+ }
+ }
+
+ if (mDarkVibrantSwatch == null) {
+ // If we do not have a dark vibrant color...
+ if (mVibrantSwatch != null) {
+ // ...but we do have a vibrant, generate the value by modifying the luma
+ final float[] newHsl = copyHslValues(mVibrantSwatch);
+ newHsl[2] = TARGET_DARK_LUMA;
+ mDarkVibrantSwatch = new Swatch(ColorUtils.HSLToColor(newHsl), 0);
+ }
+ }
+ }
+
+ /**
+ * Find the {@link Palette.Swatch} with the highest population value and return the population.
+ */
+ private int findMaxPopulation() {
+ int population = 0;
+ for (Swatch swatch : mSwatches) {
+ population = Math.max(population, swatch.getPopulation());
+ }
+ return population;
+ }
+
+ private Swatch findColorVariation(float targetLuma, float minLuma, float maxLuma,
+ float targetSaturation, float minSaturation, float maxSaturation) {
+ Swatch max = null;
+ float maxValue = 0f;
+
+ for (Swatch swatch : mSwatches) {
+ final float sat = swatch.getHsl()[1];
+ final float luma = swatch.getHsl()[2];
+
+ if (sat >= minSaturation && sat <= maxSaturation &&
+ luma >= minLuma && luma <= maxLuma &&
+ !isAlreadySelected(swatch)) {
+ float value = createComparisonValue(sat, targetSaturation, luma, targetLuma,
+ swatch.getPopulation(), mHighestPopulation);
+ if (max == null || value > maxValue) {
+ max = swatch;
+ maxValue = value;
+ }
+ }
+ }
+
+ return max;
+ }
+
+ /**
+ * @return true if we have already selected {@code swatch}
+ */
+ private boolean isAlreadySelected(Swatch swatch) {
+ return mVibrantSwatch == swatch || mDarkVibrantSwatch == swatch ||
+ mLightVibrantSwatch == swatch || mMutedSwatch == swatch ||
+ mDarkMutedSwatch == swatch || mLightMutedSwatch == swatch;
+ }
+
+ private static float createComparisonValue(float saturation, float targetSaturation,
+ float luma, float targetLuma,
+ int population, int maxPopulation) {
+ return createComparisonValue(saturation, targetSaturation, WEIGHT_SATURATION,
+ luma, targetLuma, WEIGHT_LUMA,
+ population, maxPopulation, WEIGHT_POPULATION);
+ }
+
+ private static float createComparisonValue(
+ float saturation, float targetSaturation, float saturationWeight,
+ float luma, float targetLuma, float lumaWeight,
+ int population, int maxPopulation, float populationWeight) {
+ return weightedMean(
+ invertDiff(saturation, targetSaturation), saturationWeight,
+ invertDiff(luma, targetLuma), lumaWeight,
+ population / (float) maxPopulation, populationWeight
+ );
+ }
+
+ /**
+ * Copy a {@link Swatch}'s HSL values into a new float[].
+ */
+ private static float[] copyHslValues(Swatch color) {
+ final float[] newHsl = new float[3];
+ System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
+ return newHsl;
+ }
+
+ /**
+ * Returns a value in the range 0-1. 1 is returned when {@code value} equals the
+ * {@code targetValue} and then decreases as the absolute difference between {@code value} and
+ * {@code targetValue} increases.
+ *
+ * @param value the item's value
+ * @param targetValue the value which we desire
+ */
+ private static float invertDiff(float value, float targetValue) {
+ return 1f - Math.abs(value - targetValue);
+ }
+
+ private static float weightedMean(float... values) {
+ float sum = 0f;
+ float sumWeight = 0f;
+
+ for (int i = 0; i < values.length; i += 2) {
+ float value = values[i];
+ float weight = values[i + 1];
+
+ sum += (value * weight);
+ sumWeight += weight;
+ }
+
+ return sum / sumWeight;
+ }
+}
diff --git a/core/java/com/android/internal/util/cm/palette/Palette.java b/core/java/com/android/internal/util/cm/palette/Palette.java
new file mode 100644
index 0000000..2cbd2b8
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/palette/Palette.java
@@ -0,0 +1,740 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.cm.palette;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.os.AsyncTask;
+import android.annotation.ColorInt;
+import android.annotation.Nullable;
+import android.util.TimingLogger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A helper class to extract prominent colors from an image.
+ * <p>
+ * A number of colors with different profiles are extracted from the image:
+ * <ul>
+ * <li>Vibrant</li>
+ * <li>Vibrant Dark</li>
+ * <li>Vibrant Light</li>
+ * <li>Muted</li>
+ * <li>Muted Dark</li>
+ * <li>Muted Light</li>
+ * </ul>
+ * These can be retrieved from the appropriate getter method.
+ *
+ * <p>
+ * Instances are created with a {@link Builder} which supports several options to tweak the
+ * generated Palette. See that class' documentation for more information.
+ * <p>
+ * Generation should always be completed on a background thread, ideally the one in
+ * which you load your image on. {@link Builder} supports both synchronous and asynchronous
+ * generation:
+ *
+ * <pre>
+ * // Synchronous
+ * Palette p = Palette.from(bitmap).generate();
+ *
+ * // Asynchronous
+ * Palette.from(bitmap).generate(new PaletteAsyncListener() {
+ * public void onGenerated(Palette p) {
+ * // Use generated instance
+ * }
+ * });
+ * </pre>
+ *
+ * @hide
+ */
+public final class Palette {
+
+ /**
+ * Listener to be used with {@link #generateAsync(Bitmap, PaletteAsyncListener)} or
+ * {@link #generateAsync(Bitmap, int, PaletteAsyncListener)}
+ */
+ public interface PaletteAsyncListener {
+
+ /**
+ * Called when the {@link Palette} has been generated.
+ */
+ void onGenerated(Palette palette);
+ }
+
+ private static final int DEFAULT_RESIZE_BITMAP_MAX_DIMENSION = 192;
+ private static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16;
+
+ private static final float MIN_CONTRAST_TITLE_TEXT = 3.0f;
+ private static final float MIN_CONTRAST_BODY_TEXT = 4.5f;
+
+ private static final String LOG_TAG = "Palette";
+ private static final boolean LOG_TIMINGS = false;
+
+ /**
+ * Start generating a {@link Palette} with the returned {@link Builder} instance.
+ */
+ public static Builder from(Bitmap bitmap) {
+ return new Builder(bitmap);
+ }
+
+ /**
+ * Generate a {@link Palette} from the pre-generated list of {@link Palette.Swatch} swatches.
+ * This is useful for testing, or if you want to resurrect a {@link Palette} instance from a
+ * list of swatches. Will return null if the {@code swatches} is null.
+ */
+ public static Palette from(List<Swatch> swatches) {
+ return new Builder(swatches).generate();
+ }
+
+ /**
+ * @deprecated Use {@link Builder} to generate the Palette.
+ */
+ @Deprecated
+ public static Palette generate(Bitmap bitmap) {
+ return from(bitmap).generate();
+ }
+
+ /**
+ * @deprecated Use {@link Builder} to generate the Palette.
+ */
+ @Deprecated
+ public static Palette generate(Bitmap bitmap, int numColors) {
+ return from(bitmap).maximumColorCount(numColors).generate();
+ }
+
+ /**
+ * @deprecated Use {@link Builder} to generate the Palette.
+ */
+ @Deprecated
+ public static AsyncTask<Bitmap, Void, Palette> generateAsync(
+ Bitmap bitmap, PaletteAsyncListener listener) {
+ return from(bitmap).generate(listener);
+ }
+
+ /**
+ * @deprecated Use {@link Builder} to generate the Palette.
+ */
+ @Deprecated
+ public static AsyncTask<Bitmap, Void, Palette> generateAsync(
+ final Bitmap bitmap, final int numColors, final PaletteAsyncListener listener) {
+ return from(bitmap).maximumColorCount(numColors).generate(listener);
+ }
+
+ private final List<Swatch> mSwatches;
+ private final Generator mGenerator;
+
+ private Palette(List<Swatch> swatches, Generator generator) {
+ mSwatches = swatches;
+ mGenerator = generator;
+ }
+
+ /**
+ * Returns all of the swatches which make up the palette.
+ */
+ public List<Swatch> getSwatches() {
+ return Collections.unmodifiableList(mSwatches);
+ }
+
+ /**
+ * Returns the most vibrant swatch in the palette. Might be null.
+ */
+ @Nullable
+ public Swatch getVibrantSwatch() {
+ return mGenerator.getVibrantSwatch();
+ }
+
+ /**
+ * Returns a light and vibrant swatch from the palette. Might be null.
+ */
+ @Nullable
+ public Swatch getLightVibrantSwatch() {
+ return mGenerator.getLightVibrantSwatch();
+ }
+
+ /**
+ * Returns a dark and vibrant swatch from the palette. Might be null.
+ */
+ @Nullable
+ public Swatch getDarkVibrantSwatch() {
+ return mGenerator.getDarkVibrantSwatch();
+ }
+
+ /**
+ * Returns a muted swatch from the palette. Might be null.
+ */
+ @Nullable
+ public Swatch getMutedSwatch() {
+ return mGenerator.getMutedSwatch();
+ }
+
+ /**
+ * Returns a muted and light swatch from the palette. Might be null.
+ */
+ @Nullable
+ public Swatch getLightMutedSwatch() {
+ return mGenerator.getLightMutedSwatch();
+ }
+
+ /**
+ * Returns a muted and dark swatch from the palette. Might be null.
+ */
+ @Nullable
+ public Swatch getDarkMutedSwatch() {
+ return mGenerator.getDarkMutedSwatch();
+ }
+
+ /**
+ * Returns the most vibrant color in the palette as an RGB packed int.
+ *
+ * @param defaultColor value to return if the swatch isn't available
+ */
+ @ColorInt
+ public int getVibrantColor(@ColorInt int defaultColor) {
+ Swatch swatch = getVibrantSwatch();
+ return swatch != null ? swatch.getRgb() : defaultColor;
+ }
+
+ /**
+ * Returns a light and vibrant color from the palette as an RGB packed int.
+ *
+ * @param defaultColor value to return if the swatch isn't available
+ */
+ @ColorInt
+ public int getLightVibrantColor(@ColorInt int defaultColor) {
+ Swatch swatch = getLightVibrantSwatch();
+ return swatch != null ? swatch.getRgb() : defaultColor;
+ }
+
+ /**
+ * Returns a dark and vibrant color from the palette as an RGB packed int.
+ *
+ * @param defaultColor value to return if the swatch isn't available
+ */
+ @ColorInt
+ public int getDarkVibrantColor(@ColorInt int defaultColor) {
+ Swatch swatch = getDarkVibrantSwatch();
+ return swatch != null ? swatch.getRgb() : defaultColor;
+ }
+
+ /**
+ * Returns a muted color from the palette as an RGB packed int.
+ *
+ * @param defaultColor value to return if the swatch isn't available
+ */
+ @ColorInt
+ public int getMutedColor(@ColorInt int defaultColor) {
+ Swatch swatch = getMutedSwatch();
+ return swatch != null ? swatch.getRgb() : defaultColor;
+ }
+
+ /**
+ * Returns a muted and light color from the palette as an RGB packed int.
+ *
+ * @param defaultColor value to return if the swatch isn't available
+ */
+ @ColorInt
+ public int getLightMutedColor(@ColorInt int defaultColor) {
+ Swatch swatch = getLightMutedSwatch();
+ return swatch != null ? swatch.getRgb() : defaultColor;
+ }
+
+ /**
+ * Returns a muted and dark color from the palette as an RGB packed int.
+ *
+ * @param defaultColor value to return if the swatch isn't available
+ */
+ @ColorInt
+ public int getDarkMutedColor(@ColorInt int defaultColor) {
+ Swatch swatch = getDarkMutedSwatch();
+ return swatch != null ? swatch.getRgb() : defaultColor;
+ }
+
+ /**
+ * Scale the bitmap down so that it's largest dimension is {@code targetMaxDimension}.
+ * If {@code bitmap} is smaller than this, then it is returned.
+ */
+ private static Bitmap scaleBitmapDown(Bitmap bitmap, final int targetMaxDimension) {
+ final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
+
+ if (maxDimension <= targetMaxDimension) {
+ // If the bitmap is small enough already, just return it
+ return bitmap;
+ }
+
+ final float scaleRatio = targetMaxDimension / (float) maxDimension;
+ return Bitmap.createScaledBitmap(bitmap,
+ Math.round(bitmap.getWidth() * scaleRatio),
+ Math.round(bitmap.getHeight() * scaleRatio),
+ false);
+ }
+
+ /**
+ * Represents a color swatch generated from an image's palette. The RGB color can be retrieved
+ * by calling {@link #getRgb()}.
+ */
+ public static final class Swatch {
+ private final int mRed, mGreen, mBlue;
+ private final int mRgb;
+ private final int mPopulation;
+
+ private boolean mGeneratedTextColors;
+ private int mTitleTextColor;
+ private int mBodyTextColor;
+
+ private float[] mHsl;
+
+ public Swatch(@ColorInt int color, int population) {
+ mRed = Color.red(color);
+ mGreen = Color.green(color);
+ mBlue = Color.blue(color);
+ mRgb = color;
+ mPopulation = population;
+ }
+
+ Swatch(int red, int green, int blue, int population) {
+ mRed = red;
+ mGreen = green;
+ mBlue = blue;
+ mRgb = Color.rgb(red, green, blue);
+ mPopulation = population;
+ }
+
+ /**
+ * @return this swatch's RGB color value
+ */
+ @ColorInt
+ public int getRgb() {
+ return mRgb;
+ }
+
+ /**
+ * Return this swatch's HSL values.
+ * hsv[0] is Hue [0 .. 360)
+ * hsv[1] is Saturation [0...1]
+ * hsv[2] is Lightness [0...1]
+ */
+ public float[] getHsl() {
+ if (mHsl == null) {
+ mHsl = new float[3];
+ ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl);
+ }
+ return mHsl;
+ }
+
+ /**
+ * @return the number of pixels represented by this swatch
+ */
+ public int getPopulation() {
+ return mPopulation;
+ }
+
+ /**
+ * Returns an appropriate color to use for any 'title' text which is displayed over this
+ * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast.
+ */
+ @ColorInt
+ public int getTitleTextColor() {
+ ensureTextColorsGenerated();
+ return mTitleTextColor;
+ }
+
+ /**
+ * Returns an appropriate color to use for any 'body' text which is displayed over this
+ * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast.
+ */
+ @ColorInt
+ public int getBodyTextColor() {
+ ensureTextColorsGenerated();
+ return mBodyTextColor;
+ }
+
+ private void ensureTextColorsGenerated() {
+ if (!mGeneratedTextColors) {
+ // First check white, as most colors will be dark
+ final int lightBodyAlpha = ColorUtils.calculateMinimumAlpha(
+ Color.WHITE, mRgb, MIN_CONTRAST_BODY_TEXT);
+ final int lightTitleAlpha = ColorUtils.calculateMinimumAlpha(
+ Color.WHITE, mRgb, MIN_CONTRAST_TITLE_TEXT);
+
+ if (lightBodyAlpha != -1 && lightTitleAlpha != -1) {
+ // If we found valid light values, use them and return
+ mBodyTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha);
+ mTitleTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha);
+ mGeneratedTextColors = true;
+ return;
+ }
+
+ final int darkBodyAlpha = ColorUtils.calculateMinimumAlpha(
+ Color.BLACK, mRgb, MIN_CONTRAST_BODY_TEXT);
+ final int darkTitleAlpha = ColorUtils.calculateMinimumAlpha(
+ Color.BLACK, mRgb, MIN_CONTRAST_TITLE_TEXT);
+
+ if (darkBodyAlpha != -1 && darkBodyAlpha != -1) {
+ // If we found valid dark values, use them and return
+ mBodyTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
+ mTitleTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
+ mGeneratedTextColors = true;
+ return;
+ }
+
+ // If we reach here then we can not find title and body values which use the same
+ // lightness, we need to use mismatched values
+ mBodyTextColor = lightBodyAlpha != -1
+ ? ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha)
+ : ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
+ mTitleTextColor = lightTitleAlpha != -1
+ ? ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha)
+ : ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
+ mGeneratedTextColors = true;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(getClass().getSimpleName())
+ .append(" [RGB: #").append(Integer.toHexString(getRgb())).append(']')
+ .append(" [HSL: ").append(Arrays.toString(getHsl())).append(']')
+ .append(" [Population: ").append(mPopulation).append(']')
+ .append(" [Title Text: #").append(Integer.toHexString(getTitleTextColor()))
+ .append(']')
+ .append(" [Body Text: #").append(Integer.toHexString(getBodyTextColor()))
+ .append(']').toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Swatch swatch = (Swatch) o;
+ return mPopulation == swatch.mPopulation && mRgb == swatch.mRgb;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * mRgb + mPopulation;
+ }
+ }
+
+ /**
+ * Builder class for generating {@link Palette} instances.
+ */
+ public static final class Builder {
+ private List<Swatch> mSwatches;
+ private Bitmap mBitmap;
+ private int mMaxColors = DEFAULT_CALCULATE_NUMBER_COLORS;
+ private int mResizeMaxDimension = DEFAULT_RESIZE_BITMAP_MAX_DIMENSION;
+ private final List<Filter> mFilters = new ArrayList<>();
+
+ private Generator mGenerator;
+
+ /**
+ * Construct a new {@link Builder} using a source {@link Bitmap}
+ */
+ public Builder(Bitmap bitmap) {
+ this();
+ if (bitmap == null || bitmap.isRecycled()) {
+ throw new IllegalArgumentException("Bitmap is not valid");
+ }
+ mBitmap = bitmap;
+ }
+
+ /**
+ * Construct a new {@link Builder} using a list of {@link Swatch} instances.
+ * Typically only used for testing.
+ */
+ public Builder(List<Swatch> swatches) {
+ this();
+ if (swatches == null || swatches.isEmpty()) {
+ throw new IllegalArgumentException("List of Swatches is not valid");
+ }
+ mSwatches = swatches;
+ }
+
+ private Builder() {
+ mFilters.add(DEFAULT_FILTER);
+ }
+
+ /**
+ * Set the {@link Generator} to use when generating the {@link Palette}. If this is called
+ * with {@code null} then the default generator will be used.
+ */
+ Builder generator(Generator generator) {
+ mGenerator = generator;
+ return this;
+ }
+
+ /**
+ * Set the maximum number of colors to use in the quantization step when using a
+ * {@link android.graphics.Bitmap} as the source.
+ * <p>
+ * Good values for depend on the source image type. For landscapes, good values are in
+ * the range 10-16. For images which are largely made up of people's faces then this
+ * value should be increased to ~24.
+ */
+ public Builder maximumColorCount(int colors) {
+ mMaxColors = colors;
+ return this;
+ }
+
+ /**
+ * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
+ * If the bitmap's largest dimension is greater than the value specified, then the bitmap
+ * will be resized so that it's largest dimension matches {@code maxDimension}. If the
+ * bitmap is smaller or equal, the original is used as-is.
+ * <p>
+ * This value has a large effect on the processing time. The larger the resized image is,
+ * the greater time it will take to generate the palette. The smaller the image is, the
+ * more detail is lost in the resulting image and thus less precision for color selection.
+ */
+ public Builder resizeBitmapSize(int maxDimension) {
+ mResizeMaxDimension = maxDimension;
+ return this;
+ }
+
+ /**
+ * Clear all added filters. This includes any default filters added automatically by
+ * {@link Palette}.
+ */
+ public Builder clearFilters() {
+ mFilters.clear();
+ return this;
+ }
+
+ /**
+ * Add a filter to be able to have fine grained controlled over the colors which are
+ * allowed in the resulting palette.
+ *
+ * @param filter filter to add.
+ */
+ public Builder addFilter(Filter filter) {
+ if (filter != null) {
+ mFilters.add(filter);
+ }
+ return this;
+ }
+
+ /**
+ * Generate and return the {@link Palette} synchronously.
+ */
+ public Palette generate() {
+ final TimingLogger logger = LOG_TIMINGS
+ ? new TimingLogger(LOG_TAG, "Generation")
+ : null;
+
+ List<Swatch> swatches;
+
+ if (mBitmap != null) {
+ // We have a Bitmap so we need to quantization to reduce the number of colors
+
+ if (mResizeMaxDimension <= 0) {
+ throw new IllegalArgumentException(
+ "Minimum dimension size for resizing should should be >= 1");
+ }
+
+ // First we'll scale down the bitmap so it's largest dimension is as specified
+ final Bitmap scaledBitmap = scaleBitmapDown(mBitmap, mResizeMaxDimension);
+
+ if (logger != null) {
+ logger.addSplit("Processed Bitmap");
+ }
+
+ // Now generate a quantizer from the Bitmap
+ final int width = scaledBitmap.getWidth();
+ final int height = scaledBitmap.getHeight();
+ final int[] pixels = new int[width * height];
+ scaledBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
+
+ final ColorCutQuantizer quantizer = new ColorCutQuantizer(pixels, mMaxColors,
+ mFilters.isEmpty() ? null : mFilters.toArray(new Filter[mFilters.size()]));
+
+ // If created a new bitmap, recycle it
+ if (scaledBitmap != mBitmap) {
+ scaledBitmap.recycle();
+ }
+ swatches = quantizer.getQuantizedColors();
+
+ if (logger != null) {
+ logger.addSplit("Color quantization completed");
+ }
+ } else {
+ // Else we're using the provided swatches
+ swatches = mSwatches;
+ }
+
+ // If we haven't been provided with a generator, use the default
+ if (mGenerator == null) {
+ mGenerator = new DefaultGenerator();
+ }
+
+ // Now call let the Generator do it's thing
+ mGenerator.generate(swatches);
+
+ if (logger != null) {
+ logger.addSplit("Generator.generate() completed");
+ }
+
+ // Now create a Palette instance
+ Palette p = new Palette(swatches, mGenerator);
+
+ if (logger != null) {
+ logger.addSplit("Created Palette");
+ logger.dumpToLog();
+ }
+
+ return p;
+ }
+
+ /**
+ * Generate the {@link Palette} asynchronously. The provided listener's
+ * {@link PaletteAsyncListener#onGenerated} method will be called with the palette when
+ * generated.
+ */
+ public AsyncTask<Bitmap, Void, Palette> generate(final PaletteAsyncListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener can not be null");
+ }
+
+ AsyncTask<Bitmap, Void, Palette> task = new AsyncTask<Bitmap, Void, Palette>() {
+ @Override
+ protected Palette doInBackground(Bitmap... params) {
+ return generate();
+ }
+
+ @Override
+ protected void onPostExecute(Palette colorExtractor) {
+ listener.onGenerated(colorExtractor);
+ }
+ };
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
+ return task;
+ }
+ }
+
+ static abstract class Generator {
+
+ /**
+ * This method will be called with the {@link Palette.Swatch} that represent an image.
+ * You should process this list so that you have appropriate values when the other methods in
+ * class are called.
+ * <p>
+ * This method will probably be called on a background thread.
+ */
+ public abstract void generate(List<Palette.Swatch> swatches);
+
+ /**
+ * Return the most vibrant {@link Palette.Swatch}
+ */
+ public Palette.Swatch getVibrantSwatch() {
+ return null;
+ }
+
+ /**
+ * Return a light and vibrant {@link Palette.Swatch}
+ */
+ public Palette.Swatch getLightVibrantSwatch() {
+ return null;
+ }
+
+ /**
+ * Return a dark and vibrant {@link Palette.Swatch}
+ */
+ public Palette.Swatch getDarkVibrantSwatch() {
+ return null;
+ }
+
+ /**
+ * Return a muted {@link Palette.Swatch}
+ */
+ public Palette.Swatch getMutedSwatch() {
+ return null;
+ }
+
+ /**
+ * Return a muted and light {@link Palette.Swatch}
+ */
+ public Palette.Swatch getLightMutedSwatch() {
+ return null;
+ }
+
+ /**
+ * Return a muted and dark {@link Palette.Swatch}
+ */
+ public Palette.Swatch getDarkMutedSwatch() {
+ return null;
+ }
+ }
+
+ /**
+ * A Filter provides a mechanism for exercising fine-grained control over which colors
+ * are valid within a resulting {@link Palette}.
+ */
+ public interface Filter {
+ /**
+ * Hook to allow clients to be able filter colors from resulting palette.
+ *
+ * @param rgb the color in RGB888.
+ * @param hsl HSL representation of the color.
+ *
+ * @return true if the color is allowed, false if not.
+ *
+ * @see Builder#addFilter(Filter)
+ */
+ boolean isAllowed(int rgb, float[] hsl);
+ }
+
+ /**
+ * The default filter.
+ */
+ private static final Filter DEFAULT_FILTER = new Filter() {
+ private static final float BLACK_MAX_LIGHTNESS = 0.05f;
+ private static final float WHITE_MIN_LIGHTNESS = 0.95f;
+
+ @Override
+ public boolean isAllowed(int rgb, float[] hsl) {
+ return !isWhite(hsl) && !isBlack(hsl) && !isNearRedILine(hsl);
+ }
+
+ /**
+ * @return true if the color represents a color which is close to black.
+ */
+ private boolean isBlack(float[] hslColor) {
+ return hslColor[2] <= BLACK_MAX_LIGHTNESS;
+ }
+
+ /**
+ * @return true if the color represents a color which is close to white.
+ */
+ private boolean isWhite(float[] hslColor) {
+ return hslColor[2] >= WHITE_MIN_LIGHTNESS;
+ }
+
+ /**
+ * @return true if the color lies close to the red side of the I line.
+ */
+ private boolean isNearRedILine(float[] hslColor) {
+ return hslColor[0] >= 10f && hslColor[0] <= 37f && hslColor[1] <= 0.82f;
+ }
+ };
+}
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index b479cb1..9b4910e 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -25,6 +25,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -41,7 +42,8 @@ import com.android.internal.R;
public final class RotationPolicy {
private static final String TAG = "RotationPolicy";
private static final int CURRENT_ROTATION = -1;
- private static final int NATURAL_ROTATION = Surface.ROTATION_0;
+ private static final int NATURAL_ROTATION =
+ SystemProperties.getInt("persist.panel.orientation", Surface.ROTATION_0) / 90;
private RotationPolicy() {
}
@@ -72,7 +74,7 @@ public final class RotationPolicy {
* otherwise Configuration.ORIENTATION_UNDEFINED if any orientation is lockable.
*/
public static int getRotationLockOrientation(Context context) {
- if (!areAllRotationsAllowed(context)) {
+ if (!isCurrentRotationAllowed(context)) {
final Point size = new Point();
final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
@@ -112,7 +114,8 @@ public final class RotationPolicy {
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
UserHandle.USER_CURRENT);
- final int rotation = areAllRotationsAllowed(context) ? CURRENT_ROTATION : NATURAL_ROTATION;
+ final int rotation = isCurrentRotationAllowed(context)
+ ? CURRENT_ROTATION : NATURAL_ROTATION;
setRotationLock(enabled, rotation);
}
@@ -129,8 +132,39 @@ public final class RotationPolicy {
setRotationLock(enabled, NATURAL_ROTATION);
}
- private static boolean areAllRotationsAllowed(Context context) {
- return context.getResources().getBoolean(R.bool.config_allowAllRotations);
+ public static boolean isRotationAllowed(int rotation,
+ int userRotationAngles, boolean allowAllRotations) {
+ if (userRotationAngles < 0) {
+ // Not set by user so use these defaults
+ userRotationAngles = allowAllRotations ?
+ (1 | 2 | 4 | 8) : // All angles
+ (1 | 2 | 8); // All except 180
+ }
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return (userRotationAngles & 1) != 0;
+ case Surface.ROTATION_90:
+ return (userRotationAngles & 2) != 0;
+ case Surface.ROTATION_180:
+ return (userRotationAngles & 4) != 0;
+ case Surface.ROTATION_270:
+ return (userRotationAngles & 8) != 0;
+ }
+ return false;
+ }
+
+ private static boolean isCurrentRotationAllowed(Context context) {
+ int userRotationAngles = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION_ANGLES, -1);
+ boolean allowAllRotations = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowAllRotations);
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ try {
+ return isRotationAllowed(wm.getRotation(), userRotationAngles, allowAllRotations);
+ } catch (RemoteException exc) {
+ Log.w(TAG, "Unable to getWindowManagerService.getRotation()");
+ }
+ return false;
}
private static void setRotationLock(final boolean enabled, final int rotation) {
@@ -194,4 +228,4 @@ public final class RotationPolicy {
public abstract void onChange();
}
-} \ No newline at end of file
+}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 4e4552d..cc951a5 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -33,10 +33,12 @@ interface ILockSettings {
void setLockPassword(in String password, in String savedPassword, int userId);
VerifyCredentialResponse checkPassword(in String password, int userId);
VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
+ byte getLockPatternSize(int userId);
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
void registerStrongAuthTracker(in IStrongAuthTracker tracker);
void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
void requireStrongAuth(int strongAuthReason, int userId);
+ void sanitizePassword();
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2e9f4f6..d9c2a92 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -96,6 +96,11 @@ public class LockPatternUtils {
*/
public static final int MIN_LOCK_PASSWORD_SIZE = 4;
+ /*
+ * The default size of the pattern lockscreen. Ex: 3x3
+ */
+ public static final byte PATTERN_SIZE_DEFAULT = 3;
+
/**
* The minimum number of dots the user must include in a wrong pattern
* attempt for it to be counted against the counts that affect
@@ -538,6 +543,17 @@ public class LockPatternUtils {
}
}
+ /**
+ * clears stored password.
+ */
+ public void sanitizePassword() {
+ try {
+ getLockSettings().sanitizePassword();
+ } catch (RemoteException re) {
+ Log.e(TAG, "Couldn't sanitize password" + re);
+ }
+ }
+
private void updateCryptoUserInfo(int userId) {
if (userId != UserHandle.USER_OWNER) {
return;
@@ -841,17 +857,18 @@ public class LockPatternUtils {
* @param string The pattern serialized with {@link #patternToString}
* @return The pattern.
*/
- public static List<LockPatternView.Cell> stringToPattern(String string) {
+ public static List<LockPatternView.Cell> stringToPattern(String string, byte gridSize) {
if (string == null) {
return null;
}
-
List<LockPatternView.Cell> result = Lists.newArrayList();
+ LockPatternView.Cell.updateSize(gridSize);
+
final byte[] bytes = string.getBytes();
for (int i = 0; i < bytes.length; i++) {
byte b = (byte) (bytes[i] - '1');
- result.add(LockPatternView.Cell.of(b / 3, b % 3));
+ result.add(LockPatternView.Cell.of(b / gridSize, b % gridSize, gridSize));
}
return result;
}
@@ -861,16 +878,26 @@ public class LockPatternUtils {
* @param pattern The pattern.
* @return The pattern in string form.
*/
- public static String patternToString(List<LockPatternView.Cell> pattern) {
+ public String patternToString(List<LockPatternView.Cell> pattern) {
+ return patternToString(pattern, getLockPatternSize());
+ }
+
+ /**
+ * Serialize a pattern.
+ * @param pattern The pattern.
+ * @return The pattern in string form.
+ */
+ public static String patternToString(List<LockPatternView.Cell> pattern, byte gridSize) {
if (pattern == null) {
return "";
}
final int patternSize = pattern.size();
+ LockPatternView.Cell.updateSize(gridSize);
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
+ res[i] = (byte) (cell.getRow() * gridSize + cell.getColumn() + '1');
}
return new String(res);
}
@@ -880,7 +907,6 @@ public class LockPatternUtils {
return "";
}
final int patternSize = pattern.length();
-
byte[] res = new byte[patternSize];
final byte[] bytes = pattern.getBytes();
for (int i = 0; i < patternSize; i++) {
@@ -896,7 +922,7 @@ public class LockPatternUtils {
* @param pattern the gesture pattern.
* @return the hash of the pattern in a byte array.
*/
- public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
+ public static byte[] patternToHash(List<LockPatternView.Cell> pattern, byte gridSize) {
if (pattern == null) {
return null;
}
@@ -905,7 +931,7 @@ public class LockPatternUtils {
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
+ res[i] = (byte) (cell.getRow() * gridSize + cell.getColumn());
}
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
@@ -1072,6 +1098,40 @@ public class LockPatternUtils {
}
/**
+ * @return the pattern lockscreen size
+ */
+ public byte getLockPatternSize() {
+ long size = getLong(Settings.Secure.LOCK_PATTERN_SIZE, -1, UserHandle.USER_CURRENT);
+ if (size > 0 && size < 128) {
+ return (byte) size;
+ }
+ return LockPatternUtils.PATTERN_SIZE_DEFAULT;
+ }
+
+ /**
+ * Set the pattern lockscreen size
+ */
+ public void setLockPatternSize(long size) {
+ setLong(Settings.Secure.LOCK_PATTERN_SIZE, size, UserHandle.USER_CURRENT);
+ }
+
+ public void setVisibleDotsEnabled(boolean enabled, int userId) {
+ setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled, userId);
+ }
+
+ public boolean isVisibleDotsEnabled(int userId) {
+ return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true, userId);
+ }
+
+ public void setShowErrorPath(boolean enabled, int userId) {
+ setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled, userId);
+ }
+
+ public boolean isShowErrorPath(int userId) {
+ return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true, userId);
+ }
+
+ /**
* Set and store the lockout deadline, meaning the user can't attempt his/her unlock
* pattern until the deadline has passed.
* @return the chosen deadline.
@@ -1108,7 +1168,7 @@ public class LockPatternUtils {
return deadline;
}
- private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
+ protected boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
try {
return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
} catch (RemoteException re) {
@@ -1116,7 +1176,7 @@ public class LockPatternUtils {
}
}
- private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
+ protected void setBoolean(String secureSettingKey, boolean enabled, int userId) {
try {
getLockSettings().setBoolean(secureSettingKey, enabled, userId);
} catch (RemoteException re) {
@@ -1125,7 +1185,7 @@ public class LockPatternUtils {
}
}
- private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
+ protected long getLong(String secureSettingKey, long defaultValue, int userHandle) {
try {
return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
} catch (RemoteException re) {
@@ -1133,7 +1193,7 @@ public class LockPatternUtils {
}
}
- private void setLong(String secureSettingKey, long value, int userHandle) {
+ protected void setLong(String secureSettingKey, long value, int userHandle) {
try {
getLockSettings().setLong(secureSettingKey, value, userHandle);
} catch (RemoteException re) {
@@ -1142,7 +1202,7 @@ public class LockPatternUtils {
}
}
- private String getString(String secureSettingKey, int userHandle) {
+ protected String getString(String secureSettingKey, int userHandle) {
try {
return getLockSettings().getString(secureSettingKey, null, userHandle);
} catch (RemoteException re) {
@@ -1150,7 +1210,7 @@ public class LockPatternUtils {
}
}
- private void setString(String secureSettingKey, String value, int userHandle) {
+ protected void setString(String secureSettingKey, String value, int userHandle) {
try {
getLockSettings().setString(secureSettingKey, value, userHandle);
} catch (RemoteException re) {
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 9211eaa..baa228f 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -51,6 +51,7 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
import java.util.ArrayList;
import java.util.HashMap;
@@ -58,7 +59,7 @@ import java.util.List;
/**
* Displays and detects the user's unlock attempt, which is a drag of a finger
- * across 9 regions of the screen.
+ * across regions of the screen.
*
* Is also capable of displaying a static pattern in "in progress", "wrong" or
* "correct" states.
@@ -70,7 +71,7 @@ public class LockPatternView extends View {
private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h)
private static final boolean PROFILE_DRAWING = false;
- private final CellState[][] mCellStates;
+ private CellState[][] mCellStates;
private final int mDotSize;
private final int mDotSizeActivated;
@@ -88,6 +89,8 @@ public class LockPatternView extends View {
*/
private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;
+ private byte mPatternSize = LockPatternUtils.PATTERN_SIZE_DEFAULT;
+
/**
* This can be used to avoid updating the display for very small motions or noisy panels.
* It didn't seem to have much impact on the devices tested, so currently set to 0.
@@ -98,7 +101,7 @@ public class LockPatternView extends View {
private static final String TAG = "LockPatternView";
private OnPatternListener mOnPatternListener;
- private final ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
+ private ArrayList<Cell> mPattern = new ArrayList<Cell>(mPatternSize * mPatternSize);
/**
* Lookup table for the circles of the pattern we are currently drawing.
@@ -106,7 +109,7 @@ public class LockPatternView extends View {
* in which case we use this to hold the cells we are drawing for the in
* progress animation.
*/
- private final boolean[][] mPatternDrawLookup = new boolean[3][3];
+ private boolean[][] mPatternDrawLookup = new boolean[mPatternSize][mPatternSize];
/**
* the in progress point:
@@ -123,6 +126,8 @@ public class LockPatternView extends View {
private boolean mInStealthMode = false;
private boolean mEnableHapticFeedback = true;
private boolean mPatternInProgress = false;
+ private boolean mVisibleDots = true;
+ private boolean mShowErrorPath = true;
private float mHitFactor = 0.6f;
@@ -143,32 +148,26 @@ public class LockPatternView extends View {
private PatternExploreByTouchHelper mExploreByTouchHelper;
private AudioManager mAudioManager;
+ private LockPatternUtils mLockPatternUtils;
+
/**
- * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
+ * Represents a cell in the matrix of the unlock pattern view.
*/
public static final class Cell {
final int row;
final int column;
- // keep # objects limited to 9
- private static final Cell[][] sCells = createCells();
-
- private static Cell[][] createCells() {
- Cell[][] res = new Cell[3][3];
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- res[i][j] = new Cell(i, j);
- }
- }
- return res;
+ static Cell[][] sCells;
+ static {
+ updateSize(LockPatternUtils.PATTERN_SIZE_DEFAULT);
}
/**
* @param row The row of the cell.
* @param column The column of the cell.
*/
- private Cell(int row, int column) {
- checkRange(row, column);
+ private Cell(int row, int column, byte size) {
+ checkRange(row, column, size);
this.row = row;
this.column = column;
}
@@ -181,17 +180,30 @@ public class LockPatternView extends View {
return column;
}
- public static Cell of(int row, int column) {
- checkRange(row, column);
+ /**
+ * @param row The row of the cell.
+ * @param column The column of the cell.
+ */
+ public static synchronized Cell of(int row, int column, byte size) {
+ checkRange(row, column, size);
return sCells[row][column];
}
- private static void checkRange(int row, int column) {
- if (row < 0 || row > 2) {
- throw new IllegalArgumentException("row must be in range 0-2");
+ public static void updateSize(byte size) {
+ sCells = new Cell[size][size];
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ sCells[i][j] = new Cell(i, j, size);
+ }
}
- if (column < 0 || column > 2) {
- throw new IllegalArgumentException("column must be in range 0-2");
+ }
+
+ private static void checkRange(int row, int column, byte size) {
+ if (row < 0 || row > size - 1) {
+ throw new IllegalArgumentException("row must be in range 0-" + (size - 1));
+ }
+ if (column < 0 || column > size - 1) {
+ throw new IllegalArgumentException("column must be in range 0-" + (size - 1));
}
}
@@ -317,9 +329,9 @@ public class LockPatternView extends View {
mPaint.setAntiAlias(true);
mPaint.setDither(true);
- mCellStates = new CellState[3][3];
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
+ mCellStates = new CellState[mPatternSize][mPatternSize];
+ for (int i = 0; i < mPatternSize; i++) {
+ for (int j = 0; j < mPatternSize; j++) {
mCellStates[i][j] = new CellState();
mCellStates[i][j].radius = mDotSize/2;
mCellStates[i][j].row = i;
@@ -355,6 +367,13 @@ public class LockPatternView extends View {
}
/**
+ * @return the current pattern lockscreen size.
+ */
+ public byte getLockPatternSize() {
+ return mPatternSize;
+ }
+
+ /**
* Set whether the view is in stealth mode. If true, there will be no
* visible feedback as the user enters the pattern.
*
@@ -364,6 +383,22 @@ public class LockPatternView extends View {
mInStealthMode = inStealthMode;
}
+ public void setVisibleDots(boolean visibleDots) {
+ mVisibleDots = visibleDots;
+ }
+
+ public boolean isVisibleDots() {
+ return mVisibleDots;
+ }
+
+ public void setShowErrorPath(boolean showErrorPath) {
+ mShowErrorPath = showErrorPath;
+ }
+
+ public boolean isShowErrorPath() {
+ return mShowErrorPath;
+ }
+
/**
* Set whether the view will use tactile feedback. If true, there will be
* tactile feedback as the user enters the pattern.
@@ -375,6 +410,35 @@ public class LockPatternView extends View {
}
/**
+ * Set the pattern size of the lockscreen
+ *
+ * @param size The pattern size.
+ */
+ public void setLockPatternSize(byte size) {
+ mPatternSize = size;
+ Cell.updateSize(size);
+ mCellStates = new CellState[mPatternSize][mPatternSize];
+ for (int i = 0; i < mPatternSize; i++) {
+ for (int j = 0; j < mPatternSize; j++) {
+ mCellStates[i][j] = new CellState();
+ mCellStates[i][j].radius = mDotSize / 2;
+ mCellStates[i][j].row = i;
+ mCellStates[i][j].col = j;
+ }
+ }
+ mPattern = new ArrayList<Cell>(size * size);
+ mPatternDrawLookup = new boolean[size][size];
+ }
+
+ /**
+ * Set the LockPatternUtil instance used to encode a pattern to a string
+ * @param utils The instance.
+ */
+ public void setLockPatternUtils(LockPatternUtils utils) {
+ mLockPatternUtils = utils;
+ }
+
+ /**
* Set the call back for pattern detection.
* @param onPatternListener The call back.
*/
@@ -589,8 +653,8 @@ public class LockPatternView extends View {
* Clear the pattern lookup table.
*/
private void clearPatternDrawLookup() {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
+ for (int i = 0; i < mPatternSize; i++) {
+ for (int j = 0; j < mPatternSize; j++) {
mPatternDrawLookup[i][j] = false;
}
}
@@ -614,11 +678,11 @@ public class LockPatternView extends View {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
final int width = w - mPaddingLeft - mPaddingRight;
- mSquareWidth = width / 3.0f;
+ mSquareWidth = width / (float) mPatternSize;
if (DEBUG_A11Y) Log.v(TAG, "onSizeChanged(" + w + "," + h + ")");
final int height = h - mPaddingTop - mPaddingBottom;
- mSquareHeight = height / 3.0f;
+ mSquareHeight = height / (float) mPatternSize;
mExploreByTouchHelper.invalidateRoot();
}
@@ -674,7 +738,6 @@ public class LockPatternView extends View {
if (cell != null) {
// check for gaps in existing pattern
- Cell fillInGapCell = null;
final ArrayList<Cell> pattern = mPattern;
if (!pattern.isEmpty()) {
final Cell lastCell = pattern.get(pattern.size() - 1);
@@ -684,21 +747,19 @@ public class LockPatternView extends View {
int fillInRow = lastCell.row;
int fillInColumn = lastCell.column;
- if (Math.abs(dRow) == 2 && Math.abs(dColumn) != 1) {
- fillInRow = lastCell.row + ((dRow > 0) ? 1 : -1);
- }
-
- if (Math.abs(dColumn) == 2 && Math.abs(dRow) != 1) {
- fillInColumn = lastCell.column + ((dColumn > 0) ? 1 : -1);
+ if (dRow == 0 || dColumn == 0 || Math.abs(dRow) == Math.abs(dColumn)) {
+ while (true) {
+ fillInRow += Integer.signum(dRow);
+ fillInColumn += Integer.signum(dColumn);
+ if (fillInRow == cell.row && fillInColumn == cell.column) break;
+ Cell fillInGapCell = Cell.of(fillInRow, fillInColumn, mPatternSize);
+ if (!mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
+ addCellToPattern(fillInGapCell);
+ }
+ }
}
-
- fillInGapCell = Cell.of(fillInRow, fillInColumn);
}
- if (fillInGapCell != null &&
- !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
- addCellToPattern(fillInGapCell);
- }
addCellToPattern(cell);
if (mEnableHapticFeedback) {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
@@ -796,7 +857,7 @@ public class LockPatternView extends View {
if (mPatternDrawLookup[rowHit][columnHit]) {
return null;
}
- return Cell.of(rowHit, columnHit);
+ return Cell.of(rowHit, columnHit, mPatternSize);
}
/**
@@ -810,7 +871,7 @@ public class LockPatternView extends View {
float hitSize = squareHeight * mHitFactor;
float offset = mPaddingTop + (squareHeight - hitSize) / 2f;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < mPatternSize; i++) {
final float hitTop = offset + squareHeight * i;
if (y >= hitTop && y <= hitTop + hitSize) {
@@ -830,7 +891,7 @@ public class LockPatternView extends View {
float hitSize = squareWidth * mHitFactor;
float offset = mPaddingLeft + (squareWidth - hitSize) / 2f;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < mPatternSize; i++) {
final float hitLeft = offset + squareWidth * i;
if (x >= hitLeft && x <= hitLeft + hitSize) {
@@ -984,8 +1045,8 @@ public class LockPatternView extends View {
}
private void cancelLineAnimations() {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
+ for (int i = 0; i < mPatternSize; i++) {
+ for (int j = 0; j < mPatternSize; j++) {
CellState state = mCellStates[i][j];
if (state.lineAnimator != null) {
state.lineAnimator.cancel();
@@ -1088,20 +1149,21 @@ public class LockPatternView extends View {
currentPath.rewind();
// draw the circles
- for (int i = 0; i < 3; i++) {
- float centerY = getCenterYForRow(i);
- for (int j = 0; j < 3; j++) {
- CellState cellState = mCellStates[i][j];
- float centerX = getCenterXForColumn(j);
- float translationY = cellState.translationY;
- if (isHardwareAccelerated() && cellState.hwAnimating) {
- DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
- displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
- cellState.hwRadius, cellState.hwPaint);
- } else {
- drawCircle(canvas, (int) centerX, (int) centerY + translationY,
- cellState.radius, drawLookup[i][j], cellState.alpha);
-
+ if (mVisibleDots) {
+ for (int i = 0; i < mPatternSize; i++) {
+ float centerY = getCenterYForRow(i);
+ for (int j = 0; j < mPatternSize; j++) {
+ CellState cellState = mCellStates[i][j];
+ float centerX = getCenterXForColumn(j);
+ float translationY = cellState.translationY;
+ if (isHardwareAccelerated() && cellState.hwAnimating) {
+ DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
+ cellState.hwRadius, cellState.hwPaint);
+ } else {
+ drawCircle(canvas, (int) centerX, (int) centerY + translationY,
+ cellState.radius, drawLookup[i][j], cellState.alpha);
+ }
}
}
}
@@ -1109,8 +1171,8 @@ public class LockPatternView extends View {
// TODO: the path should be created and cached every time we hit-detect a cell
// only the last segment of the path should be computed here
// draw the path of the pattern (unless we are in stealth mode)
- final boolean drawPath = !mInStealthMode;
-
+ final boolean drawPath = ((!mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
+ || (mPatternDisplayMode == DisplayMode.Wrong && mShowErrorPath));
if (drawPath) {
mPathPaint.setColor(getCurrentColor(true /* partOfPattern */));
@@ -1168,7 +1230,9 @@ public class LockPatternView extends View {
}
private int getCurrentColor(boolean partOfPattern) {
- if (!partOfPattern || mInStealthMode || mPatternInProgress) {
+ if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
+ || (mPatternDisplayMode == DisplayMode.Wrong && !mShowErrorPath)
+ || mPatternInProgress) {
// unselected circle
return mRegularColor;
} else if (mPatternDisplayMode == DisplayMode.Wrong) {
@@ -1196,9 +1260,9 @@ public class LockPatternView extends View {
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
return new SavedState(superState,
- LockPatternUtils.patternToString(mPattern),
- mPatternDisplayMode.ordinal(),
- mInputEnabled, mInStealthMode, mEnableHapticFeedback);
+ LockPatternUtils.patternToString(mPattern, mPatternSize),
+ mPatternDisplayMode.ordinal(), mPatternSize,
+ mInputEnabled, mInStealthMode, mEnableHapticFeedback, mVisibleDots, mShowErrorPath);
}
@Override
@@ -1207,11 +1271,14 @@ public class LockPatternView extends View {
super.onRestoreInstanceState(ss.getSuperState());
setPattern(
DisplayMode.Correct,
- LockPatternUtils.stringToPattern(ss.getSerializedPattern()));
+ LockPatternUtils.stringToPattern(ss.getSerializedPattern(), ss.getPatternSize()));
mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
+ mPatternSize = ss.getPatternSize();
mInputEnabled = ss.isInputEnabled();
mInStealthMode = ss.isInStealthMode();
mEnableHapticFeedback = ss.isTactileFeedbackEnabled();
+ mVisibleDots = ss.isVisibleDots();
+ mShowErrorPath = ss.isShowErrorPath();
}
/**
@@ -1221,21 +1288,28 @@ public class LockPatternView extends View {
private final String mSerializedPattern;
private final int mDisplayMode;
+ private final byte mPatternSize;
private final boolean mInputEnabled;
private final boolean mInStealthMode;
private final boolean mTactileFeedbackEnabled;
+ private final boolean mVisibleDots;
+ private final boolean mShowErrorPath;
/**
* Constructor called from {@link LockPatternView#onSaveInstanceState()}
*/
private SavedState(Parcelable superState, String serializedPattern, int displayMode,
- boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
+ byte patternSize, boolean inputEnabled, boolean inStealthMode,
+ boolean tactileFeedbackEnabled, boolean visibleDots, boolean showErrorPath) {
super(superState);
mSerializedPattern = serializedPattern;
mDisplayMode = displayMode;
+ mPatternSize = patternSize;
mInputEnabled = inputEnabled;
mInStealthMode = inStealthMode;
mTactileFeedbackEnabled = tactileFeedbackEnabled;
+ mVisibleDots = visibleDots;
+ mShowErrorPath = showErrorPath;
}
/**
@@ -1245,9 +1319,12 @@ public class LockPatternView extends View {
super(in);
mSerializedPattern = in.readString();
mDisplayMode = in.readInt();
+ mPatternSize = (byte) in.readByte();
mInputEnabled = (Boolean) in.readValue(null);
mInStealthMode = (Boolean) in.readValue(null);
mTactileFeedbackEnabled = (Boolean) in.readValue(null);
+ mVisibleDots = (Boolean) in.readValue(null);
+ mShowErrorPath = (Boolean) in.readValue(null);
}
public String getSerializedPattern() {
@@ -1258,6 +1335,10 @@ public class LockPatternView extends View {
return mDisplayMode;
}
+ public byte getPatternSize() {
+ return mPatternSize;
+ }
+
public boolean isInputEnabled() {
return mInputEnabled;
}
@@ -1270,14 +1351,25 @@ public class LockPatternView extends View {
return mTactileFeedbackEnabled;
}
+ public boolean isVisibleDots() {
+ return mVisibleDots;
+ }
+
+ public boolean isShowErrorPath() {
+ return mShowErrorPath;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(mSerializedPattern);
dest.writeInt(mDisplayMode);
+ dest.writeByte(mPatternSize);
dest.writeValue(mInputEnabled);
dest.writeValue(mInStealthMode);
dest.writeValue(mTactileFeedbackEnabled);
+ dest.writeValue(mVisibleDots);
+ dest.writeValue(mShowErrorPath);
}
@SuppressWarnings({ "unused", "hiding" }) // Found using reflection
diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java
index 3d9fb5c..c3dcd40 100644
--- a/core/java/com/android/server/net/BaseNetworkObserver.java
+++ b/core/java/com/android/server/net/BaseNetworkObserver.java
@@ -63,6 +63,11 @@ public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {
}
@Override
+ public void interfaceMessageRecevied(String message) {
+ // default no-op
+ }
+
+ @Override
public void limitReached(String limitName, String iface) {
// default no-op
}
diff --git a/core/java/org/codeaurora/camera/Android.mk b/core/java/org/codeaurora/camera/Android.mk
new file mode 100644
index 0000000..2e005f7
--- /dev/null
+++ b/core/java/org/codeaurora/camera/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE:= org.codeaurora.camera
+
+# This will install the file in /system/framework
+LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)
+
+include $(BUILD_JAVA_LIBRARY)
+
+# ==== permissions ========================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := org.codeaurora.camera.xml
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_CLASS := ETC
+
+# This will install the file in /system/etc/permissions
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
diff --git a/core/java/org/codeaurora/camera/ExtendedFace.java b/core/java/org/codeaurora/camera/ExtendedFace.java
new file mode 100644
index 0000000..afda0b6
--- /dev/null
+++ b/core/java/org/codeaurora/camera/ExtendedFace.java
@@ -0,0 +1,211 @@
+/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+package org.codeaurora.camera;
+
+import android.hardware.Camera;
+
+import java.util.ArrayList;
+
+import android.os.Bundle;
+
+import android.os.SystemProperties;
+
+/**
+ * {@hide} Information about a face identified through Extended camera face
+ *
+ * <p>
+ * When face detection is used with a camera, the {@link FaceDetectionListener}
+ * returns a list of face objects for use in focusing and metering.
+ * </p>
+ *
+ * @see FaceDetectionListener
+ */
+public class ExtendedFace extends android.hardware.Camera.Face {
+ public ExtendedFace() {
+ super();
+ }
+
+ private int smileDegree = 0;
+ private int smileScore = 0;
+ private int blinkDetected = 0;
+ private int faceRecognized = 0;
+ private int gazeAngle = 0;
+ private int updownDir = 0;
+ private int leftrightDir = 0;
+ private int rollDir = 0;
+ private int leyeBlink = 0;
+ private int reyeBlink = 0;
+ private int leftrightGaze = 0;
+ private int topbottomGaze = 0;
+
+ private static final String STR_TRUE = "true";
+ private static final String STR_FALSE = "false";
+
+ /**
+ * The smilie degree for the detection of the face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getSmileDegree() {
+ return smileDegree;
+ }
+
+ /**
+ * The smilie score for the detection of the face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getSmileScore() {
+ return smileScore;
+ }
+
+ /**
+ * The smilie degree for the detection of the face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getBlinkDetected() {
+ return blinkDetected;
+ }
+
+ /**
+ * If face is recognized.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getFaceRecognized() {
+ return faceRecognized;
+ }
+
+ /**
+ * The gaze angle for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getGazeAngle() {
+ return gazeAngle;
+ }
+
+ /**
+ * The up down direction for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getUpDownDirection() {
+ return updownDir;
+ }
+
+ /**
+ * The left right direction for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getLeftRightDirection() {
+ return leftrightDir;
+ }
+
+ /**
+ * The roll direction for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getRollDirection() {
+ return rollDir;
+ }
+
+ /**
+ * The degree of left eye blink for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getLeftEyeBlinkDegree() {
+ return leyeBlink;
+ }
+
+ /**
+ * The degree of right eye blink for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getRightEyeBlinkDegree() {
+ return reyeBlink;
+ }
+
+ /**
+ * The gaze degree of left-right direction for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getLeftRightGazeDegree() {
+ return leftrightGaze;
+ }
+
+ /**
+ * The gaze degree of up-down direction for the detected face.
+ *
+ * @see #startFaceDetection()
+ */
+ public int getTopBottomGazeDegree() {
+ return topbottomGaze;
+ }
+
+ private static final String BUNDLE_KEY_SMILE_SCORE = "smileScore";
+ private static final String BUNDLE_KEY_SMILE_VALUE = "smileValue";
+ private static final String BUNDLE_KEY_BLINK_DETECTED = "blinkDetected";
+ private static final String BUNDLE_KEY_LEFT_EYE_CLOSED_VALUE = "leftEyeClosedValue";
+ private static final String BUNDLE_KEY_RIGHT_EYE_CLOSED_VALUE = "rightEyeClosedValue";
+ private static final String BUNDLE_KEY_FACE_PITCH_DEGREE = "facePitchDegree";
+ private static final String BUNDLE_KEY_FACE_YAW_DEGREE = "faceYawDegree";
+ private static final String BUNDLE_KEY_FACE_ROLL_DEGREE = "faceRollDegree";
+ private static final String BUNDLE_KEY_GAZE_UP_DOWN_DEGREE = "gazeUpDownDegree";
+ private static final String BUNDLE_KEY_GAZE_LEFT_RIGHT_DEGREE = "gazeLeftRightDegree";
+ private static final String BUNDLE_KEY_FACE_RECOGNIZED = "faceRecognized";
+
+ public Bundle getExtendedFaceInfo() {
+ Bundle faceInfo = new Bundle();
+ faceInfo.putInt(BUNDLE_KEY_SMILE_VALUE, this.smileDegree);
+
+ faceInfo.putInt(BUNDLE_KEY_LEFT_EYE_CLOSED_VALUE, this.leyeBlink);
+ faceInfo.putInt(BUNDLE_KEY_RIGHT_EYE_CLOSED_VALUE, this.reyeBlink);
+
+ faceInfo.putInt(BUNDLE_KEY_FACE_PITCH_DEGREE, this.updownDir);
+ faceInfo.putInt(BUNDLE_KEY_FACE_YAW_DEGREE, this.leftrightDir);
+ faceInfo.putInt(BUNDLE_KEY_FACE_ROLL_DEGREE, this.rollDir);
+ faceInfo.putInt(BUNDLE_KEY_GAZE_UP_DOWN_DEGREE, this.topbottomGaze);
+ faceInfo.putInt(BUNDLE_KEY_GAZE_LEFT_RIGHT_DEGREE, this.leftrightGaze);
+
+ faceInfo.putInt(BUNDLE_KEY_BLINK_DETECTED, this.blinkDetected);
+ faceInfo.putInt(BUNDLE_KEY_SMILE_SCORE, this.smileScore);
+ faceInfo.putInt(BUNDLE_KEY_FACE_RECOGNIZED, this.faceRecognized);
+
+ return faceInfo;
+ }
+
+}
diff --git a/core/java/org/codeaurora/camera/org.codeaurora.camera.xml b/core/java/org/codeaurora/camera/org.codeaurora.camera.xml
new file mode 100644
index 0000000..20b2aa0
--- /dev/null
+++ b/core/java/org/codeaurora/camera/org.codeaurora.camera.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!-- This is the library that allows devices to use Camera QFace APIs. -->
+<permissions>
+ <library name="org.codeaurora.camera"
+ file="/system/framework/org.codeaurora.camera.jar" />
+</permissions>
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index fc15b964..42b10c4 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -16,6 +16,10 @@ else
LOCAL_CFLAGS += -DPACKED=""
endif
+ifeq ($(TARGET_ARCH), x86)
+ LOCAL_CFLAGS += -DPICK_SUPPORTED_ABI_WITH_MAX_LIBS
+endif
+
ifneq ($(ENABLE_CPUSETS),)
LOCAL_CFLAGS += -DENABLE_CPUSETS
endif
@@ -29,6 +33,7 @@ LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -DU_USING_ICU_NAMESPACE=0
LOCAL_SRC_FILES:= \
+ android_util_SeempLog.cpp \
AndroidRuntime.cpp \
com_android_internal_content_NativeLibraryHelper.cpp \
com_google_android_gles_jni_EGLImpl.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2fad2f6..9acdab4 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -100,6 +100,7 @@ extern int register_android_media_JetPlayer(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
namespace android {
+extern int register_android_util_SeempLog(JNIEnv* env);
/*
* JNI-based registration functions. Note these are properly contained in
@@ -1033,6 +1034,16 @@ void AndroidRuntime::start(const char* className, const Vector<String8>& options
setenv("ANDROID_ROOT", rootDir, 1);
}
+ const char* prebundledDir = getenv("PREBUNDLED_ROOT");
+ if (prebundledDir == NULL) {
+ if (hasDir("/system/bundled-app")) {
+ prebundledDir = "/system/bundled-app";
+ } else {
+ prebundledDir = "/vendor/bundled-app";
+ }
+ setenv("PREBUNDLED_ROOT", prebundledDir, 1);
+ }
+
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
@@ -1294,6 +1305,7 @@ static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env
}
static const RegJNIRec gRegJNI[] = {
+ REG_JNI(register_android_util_SeempLog),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 40029bb..1bf861a 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -1088,8 +1088,8 @@ static jint etc1_getHeight(JNIEnv *env, jclass clazz,
*/
static JNINativeMethod gMatrixMethods[] = {
- { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
- { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
+ { "multiplyMM", "!([FI[FI[FI)V", (void*)util_multiplyMM },
+ { "multiplyMV", "!([FI[FI[FI)V", (void*)util_multiplyMV },
};
static JNINativeMethod gVisibilityMethods[] = {
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 4f44c26..4cf317e 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -62,6 +62,18 @@ struct fields_t {
jmethodID rect_constructor;
jmethodID face_constructor;
jmethodID point_constructor;
+ jfieldID face_sm_degree;
+ jfieldID face_sm_score;
+ jfieldID face_blink_detected;
+ jfieldID face_gaze_angle;
+ jfieldID face_updown_dir;
+ jfieldID face_leftright_dir;
+ jfieldID face_roll_dir;
+ jfieldID face_leye_blink;
+ jfieldID face_reye_blink;
+ jfieldID face_left_right_gaze;
+ jfieldID face_top_bottom_gaze;
+ jfieldID face_recognised;
};
static fields_t fields;
@@ -96,6 +108,7 @@ private:
jclass mFaceClass; // strong reference to Face class
jclass mRectClass; // strong reference to Rect class
jclass mPointClass; // strong reference to Point class
+ bool mIsExtendedFace;
Mutex mLock;
/*
@@ -147,8 +160,16 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz,
mCameraJClass = (jclass)env->NewGlobalRef(clazz);
mCamera = camera;
- jclass faceClazz = env->FindClass("android/hardware/Camera$Face");
- mFaceClass = (jclass) env->NewGlobalRef(faceClazz);
+ jclass extendedfaceClazz = env->FindClass("org/codeaurora/camera/ExtendedFace");
+ if (NULL != extendedfaceClazz) {
+ mFaceClass = (jclass) env->NewGlobalRef(extendedfaceClazz);
+ mIsExtendedFace = true;
+ } else {
+ env->ExceptionClear();
+ jclass faceClazz = env->FindClass("android/hardware/Camera$Face");
+ mFaceClass = (jclass) env->NewGlobalRef(faceClazz);
+ mIsExtendedFace = false;
+ }
jclass rectClazz = env->FindClass("android/graphics/Rect");
mRectClass = (jclass) env->NewGlobalRef(rectClazz);
@@ -368,7 +389,6 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m
env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]);
env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]);
env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]);
-
env->SetObjectField(face, fields.face_rect, rect);
env->SetIntField(face, fields.face_score, metadata->faces[i].score);
@@ -397,6 +417,21 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m
env->SetIntField(mouth, fields.point_y, metadata->faces[i].mouth[1]);
env->SetObjectField(face, fields.face_mouth, mouth);
env->DeleteLocalRef(mouth);
+
+ if (mIsExtendedFace) {
+ env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree);
+ env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score);
+ env->SetIntField(face, fields.face_blink_detected, metadata->faces[i].blink_detected);
+ env->SetIntField(face, fields.face_recognised, metadata->faces[i].face_recognised);
+ env->SetIntField(face, fields.face_gaze_angle, metadata->faces[i].gaze_angle);
+ env->SetIntField(face, fields.face_updown_dir, metadata->faces[i].updown_dir);
+ env->SetIntField(face, fields.face_leftright_dir, metadata->faces[i].leftright_dir);
+ env->SetIntField(face, fields.face_roll_dir, metadata->faces[i].roll_dir);
+ env->SetIntField(face, fields.face_leye_blink, metadata->faces[i].leye_blink);
+ env->SetIntField(face, fields.face_reye_blink, metadata->faces[i].reye_blink);
+ env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze);
+ env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze);
+ }
}
env->DeleteLocalRef(face);
@@ -434,6 +469,71 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM
}
}
+static void android_hardware_Camera_setLongshot(JNIEnv *env, jobject thiz, jboolean enable)
+{
+ ALOGV("setLongshot");
+ JNICameraContext* context;
+ status_t rc;
+ sp<Camera> camera = get_native_camera(env, thiz, &context);
+ if (camera == 0) return;
+
+ if ( enable ) {
+ rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_ON, 0, 0);
+ } else {
+ rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_OFF, 0, 0);
+ }
+
+ if (rc != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed");
+ }
+}
+
+static void android_hardware_Camera_stopLongshot(JNIEnv *env, jobject thiz)
+{
+ ALOGV("stopLongshot");
+ JNICameraContext* context;
+ status_t rc;
+ sp<Camera> camera = get_native_camera(env, thiz, &context);
+ if (camera == 0) return;
+
+ rc = camera->sendCommand(CAMERA_CMD_STOP_LONGSHOT, 0, 0);
+
+ if (rc != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed");
+ }
+}
+
+static void android_hardware_Camera_sendHistogramData(JNIEnv *env, jobject thiz)
+ {
+ ALOGV("sendHistogramData" );
+ JNICameraContext* context;
+ status_t rc;
+ sp<Camera> camera = get_native_camera(env, thiz, &context);
+ if (camera == 0) return;
+
+ rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_SEND_DATA, 0, 0);
+
+ if (rc != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "send histogram data failed");
+ }
+ }
+ static void android_hardware_Camera_setHistogramMode(JNIEnv *env, jobject thiz, jboolean mode)
+ {
+ ALOGV("setHistogramMode: mode:%d", (int)mode);
+ JNICameraContext* context;
+ status_t rc;
+ sp<Camera> camera = get_native_camera(env, thiz, &context);
+ if (camera == 0) return;
+
+ if(mode == true)
+ rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_ON, 0, 0);
+ else
+ rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_OFF, 0, 0);
+
+ if (rc != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "set histogram mode failed");
+ }
+ }
void JNICameraContext::addCallbackBuffer(
JNIEnv *env, jbyteArray cbb, int msgType)
{
@@ -717,7 +817,25 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t
context->setCallbackMode(env, installed, manualBuffer);
}
-static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) {
+static void android_hardware_Camera_setMetadataCb(JNIEnv *env, jobject thiz, jboolean mode)
+{
+ ALOGV("setMetadataCb: mode:%d", (int)mode);
+ JNICameraContext* context;
+ status_t rc;
+ sp<Camera> camera = get_native_camera(env, thiz, &context);
+ if (camera == 0) return;
+
+ if(mode == true)
+ rc = camera->sendCommand(CAMERA_CMD_METADATA_ON, 0, 0);
+ else
+ rc = camera->sendCommand(CAMERA_CMD_METADATA_OFF, 0, 0);
+
+ if (rc != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "set metadata mode failed");
+ }
+}
+
+static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) {
ALOGV("addCallbackBuffer: 0x%x", msgType);
JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context));
@@ -947,6 +1065,18 @@ static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject
}
}
+static void android_hardware_Camera_sendVendorCommand(JNIEnv *env, jobject thiz,
+ jint cmd, jint arg1, jint arg2)
+{
+ ALOGV("sendVendorCommand");
+ sp<Camera> camera = get_native_camera(env, thiz, NULL);
+ if (camera == 0) return;
+
+ if (camera->sendCommand(cmd, arg1, arg2) != NO_ERROR) {
+ jniThrowRuntimeException(env, "sending vendor command failed");
+ }
+}
+
//-------------------------------------------------
static JNINativeMethod camMethods[] = {
@@ -995,6 +1125,21 @@ static JNINativeMethod camMethods[] = {
{ "native_takePicture",
"(I)V",
(void *)android_hardware_Camera_takePicture },
+ { "native_setHistogramMode",
+ "(Z)V",
+ (void *)android_hardware_Camera_setHistogramMode },
+ { "native_setMetadataCb",
+ "(Z)V",
+ (void *)android_hardware_Camera_setMetadataCb },
+ { "native_sendHistogramData",
+ "()V",
+ (void *)android_hardware_Camera_sendHistogramData },
+ { "native_setLongshot",
+ "(Z)V",
+ (void *)android_hardware_Camera_setLongshot },
+ { "native_stopLongshot",
+ "()V",
+ (void *)android_hardware_Camera_stopLongshot },
{ "native_setParameters",
"(Ljava/lang/String;)V",
(void *)android_hardware_Camera_setParameters },
@@ -1031,6 +1176,9 @@ static JNINativeMethod camMethods[] = {
{ "enableFocusMoveCallback",
"(I)V",
(void *)android_hardware_Camera_enableFocusMoveCallback},
+ { "_sendVendorCommand",
+ "(III)V",
+ (void *)android_hardware_Camera_sendVendorCommand },
};
struct field {
@@ -1073,6 +1221,27 @@ int register_android_hardware_Camera(JNIEnv *env)
{ "android/graphics/Point", "y", "I", &fields.point_y},
};
+ field extendedfacefields_to_find[] = {
+ { "org/codeaurora/camera/ExtendedFace", "rect", "Landroid/graphics/Rect;", &fields.face_rect },
+ { "org/codeaurora/camera/ExtendedFace", "score", "I", &fields.face_score },
+ { "org/codeaurora/camera/ExtendedFace", "id", "I", &fields.face_id },
+ { "org/codeaurora/camera/ExtendedFace", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye },
+ { "org/codeaurora/camera/ExtendedFace", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye },
+ { "org/codeaurora/camera/ExtendedFace", "mouth", "Landroid/graphics/Point;", &fields.face_mouth },
+ { "org/codeaurora/camera/ExtendedFace", "smileDegree", "I", &fields.face_sm_degree },
+ { "org/codeaurora/camera/ExtendedFace", "smileScore", "I", &fields.face_sm_score },
+ { "org/codeaurora/camera/ExtendedFace", "blinkDetected", "I", &fields.face_blink_detected },
+ { "org/codeaurora/camera/ExtendedFace", "faceRecognized", "I", &fields.face_recognised },
+ { "org/codeaurora/camera/ExtendedFace", "gazeAngle", "I", &fields.face_gaze_angle },
+ { "org/codeaurora/camera/ExtendedFace", "updownDir", "I", &fields.face_updown_dir },
+ { "org/codeaurora/camera/ExtendedFace", "leftrightDir", "I", &fields.face_leftright_dir },
+ { "org/codeaurora/camera/ExtendedFace", "rollDir", "I", &fields.face_roll_dir },
+ { "org/codeaurora/camera/ExtendedFace", "leyeBlink", "I", &fields.face_leye_blink },
+ { "org/codeaurora/camera/ExtendedFace", "reyeBlink", "I", &fields.face_reye_blink },
+ { "org/codeaurora/camera/ExtendedFace", "leftrightGaze", "I", &fields.face_left_right_gaze },
+ { "org/codeaurora/camera/ExtendedFace", "topbottomGaze", "I", &fields.face_top_bottom_gaze },
+ };
+
find_fields(env, fields_to_find, NELEM(fields_to_find));
jclass clazz = FindClassOrDie(env, "android/hardware/Camera");
@@ -1092,6 +1261,12 @@ int register_android_hardware_Camera(JNIEnv *env)
return -1;
}
+ clazz = env->FindClass("org/codeaurora/camera/ExtendedFace");
+ if (NULL != clazz) {
+ fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V");
+ find_fields(env, extendedfacefields_to_find, NELEM(extendedfacefields_to_find));
+ }
+
// Register native functions
return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
}
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index bb13c35..211b4f0 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -31,6 +31,14 @@
#define ENCODING_AAC_LC 10
#define ENCODING_AAC_HE_V1 11
#define ENCODING_AAC_HE_V2 12
+
+#define ENCODING_AMR_NB 100
+#define ENCODING_AMR_WB 101
+#define ENCODING_EVRC 102
+#define ENCODING_EVRC_B 103
+#define ENCODING_EVRC_WB 104
+#define ENCODING_EVRC_NW 105
+
#define ENCODING_INVALID 0
#define ENCODING_DEFAULT 1
@@ -64,6 +72,18 @@ static inline audio_format_t audioFormatToNative(int audioFormat)
return AUDIO_FORMAT_AAC_HE_V1;
case ENCODING_AAC_HE_V2:
return AUDIO_FORMAT_AAC_HE_V2;
+ case ENCODING_AMR_NB:
+ return AUDIO_FORMAT_AMR_NB;
+ case ENCODING_AMR_WB:
+ return AUDIO_FORMAT_AMR_WB;
+ case ENCODING_EVRC:
+ return AUDIO_FORMAT_EVRC;
+ case ENCODING_EVRC_B:
+ return AUDIO_FORMAT_EVRCB;
+ case ENCODING_EVRC_WB:
+ return AUDIO_FORMAT_EVRCWB;
+ case ENCODING_EVRC_NW:
+ return AUDIO_FORMAT_EVRCNW;
case ENCODING_DEFAULT:
return AUDIO_FORMAT_DEFAULT;
default:
@@ -103,6 +123,18 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
return ENCODING_AAC_HE_V1;
case AUDIO_FORMAT_AAC_HE_V2:
return ENCODING_AAC_HE_V2;
+ case AUDIO_FORMAT_AMR_NB:
+ return ENCODING_AMR_NB;
+ case AUDIO_FORMAT_AMR_WB:
+ return ENCODING_AMR_WB;
+ case AUDIO_FORMAT_EVRC:
+ return ENCODING_EVRC;
+ case AUDIO_FORMAT_EVRCB:
+ return ENCODING_EVRC_B;
+ case AUDIO_FORMAT_EVRCWB:
+ return ENCODING_EVRC_WB;
+ case AUDIO_FORMAT_EVRCNW:
+ return ENCODING_EVRC_NW;
case AUDIO_FORMAT_DEFAULT:
return ENCODING_DEFAULT;
default:
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 91b3278..1acf867 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -154,6 +154,11 @@ static struct {
jmethodID postDynPolicyEventFromNative;
} gDynPolicyEventHandlerMethods;
+static struct {
+ jmethodID postEffectSessionEventFromNative;
+} gEffectSessionEventHandlerMethods;
+
+
static Mutex gLock;
enum AudioError {
@@ -386,6 +391,24 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
}
+static void
+android_media_AudioSystem_effect_session_callback(int event, audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added)
+{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ return;
+ }
+
+ jclass clazz = env->FindClass(kClassPathName);
+
+ env->CallStaticVoidMethod(clazz, gEffectSessionEventHandlerMethods.postEffectSessionEventFromNative,
+ event, stream, sessionId, added);
+
+ env->DeleteLocalRef(clazz);
+
+}
+
static jint
android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
{
@@ -1487,6 +1510,12 @@ android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
}
+static void
+android_media_AudioSystem_registerEffectSessionCallback(JNIEnv *env, jobject thiz)
+{
+ AudioSystem::setEffectSessionCallback(android_media_AudioSystem_effect_session_callback);
+}
+
static jint convertAudioMixToNative(JNIEnv *env,
AudioMix *nAudioMix,
@@ -1659,6 +1688,8 @@ static JNINativeMethod gMethods[] = {
(void *)android_media_AudioSystem_registerPolicyMixes},
{"native_register_dynamic_policy_callback", "()V",
(void *)android_media_AudioSystem_registerDynPolicyCallback},
+ {"native_register_effect_session_callback", "()V",
+ (void *)android_media_AudioSystem_registerEffectSessionCallback},
{"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
};
@@ -1766,6 +1797,10 @@ int register_android_media_AudioSystem(JNIEnv *env)
GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
"dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
+ gEffectSessionEventHandlerMethods.postEffectSessionEventFromNative =
+ GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
+ "effectSessionCallbackFromNative", "(IIIZ)V");
+
jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index f9a0dfe..65331b0 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -6154,14 +6154,14 @@ static const char *classPathName = "android/opengl/GLES20";
static JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
-{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
+{"glActiveTexture", "!(I)V", (void *) android_glActiveTexture__I },
{"glAttachShader", "(II)V", (void *) android_glAttachShader__II },
{"glBindAttribLocation", "(IILjava/lang/String;)V", (void *) android_glBindAttribLocation__IILjava_lang_String_2 },
-{"glBindBuffer", "(II)V", (void *) android_glBindBuffer__II },
+{"glBindBuffer", "!(II)V", (void *) android_glBindBuffer__II },
{"glBindFramebuffer", "(II)V", (void *) android_glBindFramebuffer__II },
{"glBindRenderbuffer", "(II)V", (void *) android_glBindRenderbuffer__II },
-{"glBindTexture", "(II)V", (void *) android_glBindTexture__II },
-{"glBlendColor", "(FFFF)V", (void *) android_glBlendColor__FFFF },
+{"glBindTexture", "!(II)V", (void *) android_glBindTexture__II },
+{"glBlendColor", "!(FFFF)V", (void *) android_glBlendColor__FFFF },
{"glBlendEquation", "(I)V", (void *) android_glBlendEquation__I },
{"glBlendEquationSeparate", "(II)V", (void *) android_glBlendEquationSeparate__II },
{"glBlendFunc", "(II)V", (void *) android_glBlendFunc__II },
@@ -6171,9 +6171,9 @@ static JNINativeMethod methods[] = {
{"glCheckFramebufferStatus", "(I)I", (void *) android_glCheckFramebufferStatus__I },
{"glClear", "(I)V", (void *) android_glClear__I },
{"glClearColor", "(FFFF)V", (void *) android_glClearColor__FFFF },
-{"glClearDepthf", "(F)V", (void *) android_glClearDepthf__F },
-{"glClearStencil", "(I)V", (void *) android_glClearStencil__I },
-{"glColorMask", "(ZZZZ)V", (void *) android_glColorMask__ZZZZ },
+{"glClearDepthf", "!(F)V", (void *) android_glClearDepthf__F },
+{"glClearStencil", "!(I)V", (void *) android_glClearStencil__I },
+{"glColorMask", "!(ZZZZ)V", (void *) android_glColorMask__ZZZZ },
{"glCompileShader", "(I)V", (void *) android_glCompileShader__I },
{"glCompressedTexImage2D", "(IIIIIIILjava/nio/Buffer;)V", (void *) android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2 },
{"glCompressedTexSubImage2D", "(IIIIIIIILjava/nio/Buffer;)V", (void *) android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 },
@@ -6181,7 +6181,7 @@ static JNINativeMethod methods[] = {
{"glCopyTexSubImage2D", "(IIIIIIII)V", (void *) android_glCopyTexSubImage2D__IIIIIIII },
{"glCreateProgram", "()I", (void *) android_glCreateProgram__ },
{"glCreateShader", "(I)I", (void *) android_glCreateShader__I },
-{"glCullFace", "(I)V", (void *) android_glCullFace__I },
+{"glCullFace", "!(I)V", (void *) android_glCullFace__I },
{"glDeleteBuffers", "(I[II)V", (void *) android_glDeleteBuffers__I_3II },
{"glDeleteBuffers", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteBuffers__ILjava_nio_IntBuffer_2 },
{"glDeleteFramebuffers", "(I[II)V", (void *) android_glDeleteFramebuffers__I_3II },
@@ -6192,22 +6192,22 @@ static JNINativeMethod methods[] = {
{"glDeleteShader", "(I)V", (void *) android_glDeleteShader__I },
{"glDeleteTextures", "(I[II)V", (void *) android_glDeleteTextures__I_3II },
{"glDeleteTextures", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteTextures__ILjava_nio_IntBuffer_2 },
-{"glDepthFunc", "(I)V", (void *) android_glDepthFunc__I },
-{"glDepthMask", "(Z)V", (void *) android_glDepthMask__Z },
+{"glDepthFunc", "!(I)V", (void *) android_glDepthFunc__I },
+{"glDepthMask", "!(Z)V", (void *) android_glDepthMask__Z },
{"glDepthRangef", "(FF)V", (void *) android_glDepthRangef__FF },
{"glDetachShader", "(II)V", (void *) android_glDetachShader__II },
-{"glDisable", "(I)V", (void *) android_glDisable__I },
-{"glDisableVertexAttribArray", "(I)V", (void *) android_glDisableVertexAttribArray__I },
-{"glDrawArrays", "(III)V", (void *) android_glDrawArrays__III },
-{"glDrawElements", "(IIII)V", (void *) android_glDrawElements__IIII },
-{"glDrawElements", "(IIILjava/nio/Buffer;)V", (void *) android_glDrawElements__IIILjava_nio_Buffer_2 },
-{"glEnable", "(I)V", (void *) android_glEnable__I },
-{"glEnableVertexAttribArray", "(I)V", (void *) android_glEnableVertexAttribArray__I },
+{"glDisable", "!(I)V", (void *) android_glDisable__I },
+{"glDisableVertexAttribArray", "!(I)V", (void *) android_glDisableVertexAttribArray__I },
+{"glDrawArrays", "!(III)V", (void *) android_glDrawArrays__III },
+{"glDrawElements", "!(IIII)V", (void *) android_glDrawElements__IIII },
+{"glDrawElements", "!(IIILjava/nio/Buffer;)V", (void *) android_glDrawElements__IIILjava_nio_Buffer_2 },
+{"glEnable", "!(I)V", (void *) android_glEnable__I },
+{"glEnableVertexAttribArray", "!(I)V", (void *) android_glEnableVertexAttribArray__I },
{"glFinish", "()V", (void *) android_glFinish__ },
{"glFlush", "()V", (void *) android_glFlush__ },
{"glFramebufferRenderbuffer", "(IIII)V", (void *) android_glFramebufferRenderbuffer__IIII },
{"glFramebufferTexture2D", "(IIIII)V", (void *) android_glFramebufferTexture2D__IIIII },
-{"glFrontFace", "(I)V", (void *) android_glFrontFace__I },
+{"glFrontFace", "!(I)V", (void *) android_glFrontFace__I },
{"glGenBuffers", "(I[II)V", (void *) android_glGenBuffers__I_3II },
{"glGenBuffers", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenBuffers__ILjava_nio_IntBuffer_2 },
{"glGenerateMipmap", "(I)V", (void *) android_glGenerateMipmap__I },
@@ -6232,12 +6232,12 @@ static JNINativeMethod methods[] = {
{"glGetBooleanv", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetBooleanv__ILjava_nio_IntBuffer_2 },
{"glGetBufferParameteriv", "(II[II)V", (void *) android_glGetBufferParameteriv__II_3II },
{"glGetBufferParameteriv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2 },
-{"glGetError", "()I", (void *) android_glGetError__ },
-{"glGetFloatv", "(I[FI)V", (void *) android_glGetFloatv__I_3FI },
+{"glGetError", "!()I", (void *) android_glGetError__ },
+{"glGetFloatv", "!(I[FI)V", (void *) android_glGetFloatv__I_3FI },
{"glGetFloatv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glGetFloatv__ILjava_nio_FloatBuffer_2 },
{"glGetFramebufferAttachmentParameteriv", "(III[II)V", (void *) android_glGetFramebufferAttachmentParameteriv__III_3II },
{"glGetFramebufferAttachmentParameteriv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glGetFramebufferAttachmentParameteriv__IIILjava_nio_IntBuffer_2 },
-{"glGetIntegerv", "(I[II)V", (void *) android_glGetIntegerv__I_3II },
+{"glGetIntegerv", "!(I[II)V", (void *) android_glGetIntegerv__I_3II },
{"glGetIntegerv", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetIntegerv__ILjava_nio_IntBuffer_2 },
{"glGetProgramiv", "(II[II)V", (void *) android_glGetProgramiv__II_3II },
{"glGetProgramiv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetProgramiv__IILjava_nio_IntBuffer_2 },
@@ -6282,16 +6282,16 @@ static JNINativeMethod methods[] = {
{"glReleaseShaderCompiler", "()V", (void *) android_glReleaseShaderCompiler__ },
{"glRenderbufferStorage", "(IIII)V", (void *) android_glRenderbufferStorage__IIII },
{"glSampleCoverage", "(FZ)V", (void *) android_glSampleCoverage__FZ },
-{"glScissor", "(IIII)V", (void *) android_glScissor__IIII },
+{"glScissor", "!(IIII)V", (void *) android_glScissor__IIII },
{"glShaderBinary", "(I[IIILjava/nio/Buffer;I)V", (void *) android_glShaderBinary__I_3IIILjava_nio_Buffer_2I },
{"glShaderBinary", "(ILjava/nio/IntBuffer;ILjava/nio/Buffer;I)V", (void *) android_glShaderBinary__ILjava_nio_IntBuffer_2ILjava_nio_Buffer_2I },
{"glShaderSource", "(ILjava/lang/String;)V", (void *) android_glShaderSource },
-{"glStencilFunc", "(III)V", (void *) android_glStencilFunc__III },
-{"glStencilFuncSeparate", "(IIII)V", (void *) android_glStencilFuncSeparate__IIII },
-{"glStencilMask", "(I)V", (void *) android_glStencilMask__I },
-{"glStencilMaskSeparate", "(II)V", (void *) android_glStencilMaskSeparate__II },
-{"glStencilOp", "(III)V", (void *) android_glStencilOp__III },
-{"glStencilOpSeparate", "(IIII)V", (void *) android_glStencilOpSeparate__IIII },
+{"glStencilFunc", "!(III)V", (void *) android_glStencilFunc__III },
+{"glStencilFuncSeparate", "!(IIII)V", (void *) android_glStencilFuncSeparate__IIII },
+{"glStencilMask", "!(I)V", (void *) android_glStencilMask__I },
+{"glStencilMaskSeparate", "!(II)V", (void *) android_glStencilMaskSeparate__II },
+{"glStencilOp", "!(III)V", (void *) android_glStencilOp__III },
+{"glStencilOpSeparate", "!(IIII)V", (void *) android_glStencilOpSeparate__IIII },
{"glTexImage2D", "(IIIIIIIILjava/nio/Buffer;)V", (void *) android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2 },
{"glTexParameterf", "(IIF)V", (void *) android_glTexParameterf__IIF },
{"glTexParameterfv", "(II[FI)V", (void *) android_glTexParameterfv__II_3FI },
@@ -6300,53 +6300,53 @@ static JNINativeMethod methods[] = {
{"glTexParameteriv", "(II[II)V", (void *) android_glTexParameteriv__II_3II },
{"glTexParameteriv", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexParameteriv__IILjava_nio_IntBuffer_2 },
{"glTexSubImage2D", "(IIIIIIIILjava/nio/Buffer;)V", (void *) android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 },
-{"glUniform1f", "(IF)V", (void *) android_glUniform1f__IF },
-{"glUniform1fv", "(II[FI)V", (void *) android_glUniform1fv__II_3FI },
-{"glUniform1fv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform1fv__IILjava_nio_FloatBuffer_2 },
-{"glUniform1i", "(II)V", (void *) android_glUniform1i__II },
-{"glUniform1iv", "(II[II)V", (void *) android_glUniform1iv__II_3II },
-{"glUniform1iv", "(IILjava/nio/IntBuffer;)V", (void *) android_glUniform1iv__IILjava_nio_IntBuffer_2 },
-{"glUniform2f", "(IFF)V", (void *) android_glUniform2f__IFF },
-{"glUniform2fv", "(II[FI)V", (void *) android_glUniform2fv__II_3FI },
-{"glUniform2fv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform2fv__IILjava_nio_FloatBuffer_2 },
-{"glUniform2i", "(III)V", (void *) android_glUniform2i__III },
-{"glUniform2iv", "(II[II)V", (void *) android_glUniform2iv__II_3II },
-{"glUniform2iv", "(IILjava/nio/IntBuffer;)V", (void *) android_glUniform2iv__IILjava_nio_IntBuffer_2 },
-{"glUniform3f", "(IFFF)V", (void *) android_glUniform3f__IFFF },
-{"glUniform3fv", "(II[FI)V", (void *) android_glUniform3fv__II_3FI },
-{"glUniform3fv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform3fv__IILjava_nio_FloatBuffer_2 },
-{"glUniform3i", "(IIII)V", (void *) android_glUniform3i__IIII },
-{"glUniform3iv", "(II[II)V", (void *) android_glUniform3iv__II_3II },
-{"glUniform3iv", "(IILjava/nio/IntBuffer;)V", (void *) android_glUniform3iv__IILjava_nio_IntBuffer_2 },
-{"glUniform4f", "(IFFFF)V", (void *) android_glUniform4f__IFFFF },
-{"glUniform4fv", "(II[FI)V", (void *) android_glUniform4fv__II_3FI },
-{"glUniform4fv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform4fv__IILjava_nio_FloatBuffer_2 },
-{"glUniform4i", "(IIIII)V", (void *) android_glUniform4i__IIIII },
-{"glUniform4iv", "(II[II)V", (void *) android_glUniform4iv__II_3II },
-{"glUniform4iv", "(IILjava/nio/IntBuffer;)V", (void *) android_glUniform4iv__IILjava_nio_IntBuffer_2 },
-{"glUniformMatrix2fv", "(IIZ[FI)V", (void *) android_glUniformMatrix2fv__IIZ_3FI },
-{"glUniformMatrix2fv", "(IIZLjava/nio/FloatBuffer;)V", (void *) android_glUniformMatrix2fv__IIZLjava_nio_FloatBuffer_2 },
-{"glUniformMatrix3fv", "(IIZ[FI)V", (void *) android_glUniformMatrix3fv__IIZ_3FI },
-{"glUniformMatrix3fv", "(IIZLjava/nio/FloatBuffer;)V", (void *) android_glUniformMatrix3fv__IIZLjava_nio_FloatBuffer_2 },
-{"glUniformMatrix4fv", "(IIZ[FI)V", (void *) android_glUniformMatrix4fv__IIZ_3FI },
-{"glUniformMatrix4fv", "(IIZLjava/nio/FloatBuffer;)V", (void *) android_glUniformMatrix4fv__IIZLjava_nio_FloatBuffer_2 },
-{"glUseProgram", "(I)V", (void *) android_glUseProgram__I },
+{"glUniform1f", "!(IF)V", (void *) android_glUniform1f__IF },
+{"glUniform1fv", "!(II[FI)V", (void *) android_glUniform1fv__II_3FI },
+{"glUniform1fv", "!(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform1fv__IILjava_nio_FloatBuffer_2 },
+{"glUniform1i", "!(II)V", (void *) android_glUniform1i__II },
+{"glUniform1iv", "!(II[II)V", (void *) android_glUniform1iv__II_3II },
+{"glUniform1iv", "!(IILjava/nio/IntBuffer;)V", (void *) android_glUniform1iv__IILjava_nio_IntBuffer_2 },
+{"glUniform2f", "!(IFF)V", (void *) android_glUniform2f__IFF },
+{"glUniform2fv", "!(II[FI)V", (void *) android_glUniform2fv__II_3FI },
+{"glUniform2fv", "!(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform2fv__IILjava_nio_FloatBuffer_2 },
+{"glUniform2i", "!(III)V", (void *) android_glUniform2i__III },
+{"glUniform2iv", "!(II[II)V", (void *) android_glUniform2iv__II_3II },
+{"glUniform2iv", "!(IILjava/nio/IntBuffer;)V", (void *) android_glUniform2iv__IILjava_nio_IntBuffer_2 },
+{"glUniform3f", "!(IFFF)V", (void *) android_glUniform3f__IFFF },
+{"glUniform3fv", "!(II[FI)V", (void *) android_glUniform3fv__II_3FI },
+{"glUniform3fv", "!(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform3fv__IILjava_nio_FloatBuffer_2 },
+{"glUniform3i", "!(IIII)V", (void *) android_glUniform3i__IIII },
+{"glUniform3iv", "!(II[II)V", (void *) android_glUniform3iv__II_3II },
+{"glUniform3iv", "!(IILjava/nio/IntBuffer;)V", (void *) android_glUniform3iv__IILjava_nio_IntBuffer_2 },
+{"glUniform4f", "!(IFFFF)V", (void *) android_glUniform4f__IFFFF },
+{"glUniform4fv", "!(II[FI)V", (void *) android_glUniform4fv__II_3FI },
+{"glUniform4fv", "!(IILjava/nio/FloatBuffer;)V", (void *) android_glUniform4fv__IILjava_nio_FloatBuffer_2 },
+{"glUniform4i", "!(IIIII)V", (void *) android_glUniform4i__IIIII },
+{"glUniform4iv", "!(II[II)V", (void *) android_glUniform4iv__II_3II },
+{"glUniform4iv", "!(IILjava/nio/IntBuffer;)V", (void *) android_glUniform4iv__IILjava_nio_IntBuffer_2 },
+{"glUniformMatrix2fv", "!(IIZ[FI)V", (void *) android_glUniformMatrix2fv__IIZ_3FI },
+{"glUniformMatrix2fv", "!(IIZLjava/nio/FloatBuffer;)V", (void *) android_glUniformMatrix2fv__IIZLjava_nio_FloatBuffer_2 },
+{"glUniformMatrix3fv", "!(IIZ[FI)V", (void *) android_glUniformMatrix3fv__IIZ_3FI },
+{"glUniformMatrix3fv", "!(IIZLjava/nio/FloatBuffer;)V", (void *) android_glUniformMatrix3fv__IIZLjava_nio_FloatBuffer_2 },
+{"glUniformMatrix4fv", "!(IIZ[FI)V", (void *) android_glUniformMatrix4fv__IIZ_3FI },
+{"glUniformMatrix4fv", "!(IIZLjava/nio/FloatBuffer;)V", (void *) android_glUniformMatrix4fv__IIZLjava_nio_FloatBuffer_2 },
+{"glUseProgram", "!(I)V", (void *) android_glUseProgram__I },
{"glValidateProgram", "(I)V", (void *) android_glValidateProgram__I },
-{"glVertexAttrib1f", "(IF)V", (void *) android_glVertexAttrib1f__IF },
-{"glVertexAttrib1fv", "(I[FI)V", (void *) android_glVertexAttrib1fv__I_3FI },
-{"glVertexAttrib1fv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib1fv__ILjava_nio_FloatBuffer_2 },
-{"glVertexAttrib2f", "(IFF)V", (void *) android_glVertexAttrib2f__IFF },
-{"glVertexAttrib2fv", "(I[FI)V", (void *) android_glVertexAttrib2fv__I_3FI },
-{"glVertexAttrib2fv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib2fv__ILjava_nio_FloatBuffer_2 },
-{"glVertexAttrib3f", "(IFFF)V", (void *) android_glVertexAttrib3f__IFFF },
-{"glVertexAttrib3fv", "(I[FI)V", (void *) android_glVertexAttrib3fv__I_3FI },
-{"glVertexAttrib3fv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib3fv__ILjava_nio_FloatBuffer_2 },
-{"glVertexAttrib4f", "(IFFFF)V", (void *) android_glVertexAttrib4f__IFFFF },
-{"glVertexAttrib4fv", "(I[FI)V", (void *) android_glVertexAttrib4fv__I_3FI },
-{"glVertexAttrib4fv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib4fv__ILjava_nio_FloatBuffer_2 },
-{"glVertexAttribPointer", "(IIIZII)V", (void *) android_glVertexAttribPointer__IIIZII },
-{"glVertexAttribPointerBounds", "(IIIZILjava/nio/Buffer;I)V", (void *) android_glVertexAttribPointerBounds__IIIZILjava_nio_Buffer_2I },
-{"glViewport", "(IIII)V", (void *) android_glViewport__IIII },
+{"glVertexAttrib1f", "!(IF)V", (void *) android_glVertexAttrib1f__IF },
+{"glVertexAttrib1fv", "!(I[FI)V", (void *) android_glVertexAttrib1fv__I_3FI },
+{"glVertexAttrib1fv", "!(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib1fv__ILjava_nio_FloatBuffer_2 },
+{"glVertexAttrib2f", "!(IFF)V", (void *) android_glVertexAttrib2f__IFF },
+{"glVertexAttrib2fv", "!(I[FI)V", (void *) android_glVertexAttrib2fv__I_3FI },
+{"glVertexAttrib2fv", "!(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib2fv__ILjava_nio_FloatBuffer_2 },
+{"glVertexAttrib3f", "!(IFFF)V", (void *) android_glVertexAttrib3f__IFFF },
+{"glVertexAttrib3fv", "!(I[FI)V", (void *) android_glVertexAttrib3fv__I_3FI },
+{"glVertexAttrib3fv", "!(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib3fv__ILjava_nio_FloatBuffer_2 },
+{"glVertexAttrib4f", "!(IFFFF)V", (void *) android_glVertexAttrib4f__IFFFF },
+{"glVertexAttrib4fv", "!(I[FI)V", (void *) android_glVertexAttrib4fv__I_3FI },
+{"glVertexAttrib4fv", "!(ILjava/nio/FloatBuffer;)V", (void *) android_glVertexAttrib4fv__ILjava_nio_FloatBuffer_2 },
+{"glVertexAttribPointer", "!(IIIZII)V", (void *) android_glVertexAttribPointer__IIIZII },
+{"glVertexAttribPointerBounds", "!(IIIZILjava/nio/Buffer;I)V", (void *) android_glVertexAttribPointerBounds__IIIZILjava_nio_Buffer_2I },
+{"glViewport", "!(IIII)V", (void *) android_glViewport__IIII },
};
int register_android_opengl_jni_GLES20(JNIEnv *_env)
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index dca04f5..6257265 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -520,24 +520,143 @@ static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz
}
static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
- jstring idmapPath)
+ jstring idmapPath,
+ jstring packagePath,
+ jstring resApkPath, jstring targetPkgPath,
+ jstring prefixPath)
{
ScopedUtfChars idmapPath8(env, idmapPath);
if (idmapPath8.c_str() == NULL) {
return 0;
}
+ ScopedUtfChars packagePath8(env, packagePath);
+ if (packagePath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars resApkPath8(env, resApkPath);
+ if (resApkPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars prefixPath8(env, prefixPath);
+ if (prefixPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars targetPkgPath8(env, targetPkgPath);
+ if (targetPkgPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ int32_t cookie;
+ bool res = am->addOverlayPath(
+ String8(idmapPath8.c_str()),
+ String8(packagePath8.c_str()),
+ &cookie,
+ String8(resApkPath8.c_str()),
+ String8(targetPkgPath8.c_str()),
+ String8(prefixPath8.c_str()));
+
+ return (res) ? (jint)cookie : 0;
+}
+
+static jint android_content_AssetManager_addCommonOverlayPath(JNIEnv* env, jobject clazz,
+ jstring packagePath,
+ jstring resApkPath, jstring prefixPath)
+{
+ ScopedUtfChars packagePath8(env, packagePath);
+ if (packagePath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars resApkPath8(env, resApkPath);
+ if (resApkPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars prefixPath8(env, prefixPath);
+ if (prefixPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ if (!access(packagePath8.c_str(), R_OK) == 0 ||
+ !access(resApkPath8.c_str(), R_OK) == 0) {
+ return 0;
+ }
+
AssetManager* am = assetManagerForJavaObject(env, clazz);
if (am == NULL) {
return 0;
}
int32_t cookie;
- bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
+ bool res = am->addCommonOverlayPath(String8(packagePath8.c_str()), &cookie,
+ String8(resApkPath8.c_str()),
+ String8(prefixPath8.c_str()));
return (res) ? (jint)cookie : 0;
}
+static jint android_content_AssetManager_addIconPath(JNIEnv* env, jobject clazz,
+ jstring packagePath,
+ jstring resApkPath, jstring prefixPath,
+ jint pkgIdOverride)
+{
+ ScopedUtfChars packagePath8(env, packagePath);
+ if (packagePath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars resApkPath8(env, resApkPath);
+ if (resApkPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ ScopedUtfChars prefixPath8(env, prefixPath);
+ if (prefixPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ int32_t cookie;
+ bool res = am->addIconPath(String8(packagePath8.c_str()), &cookie,
+ String8(resApkPath8.c_str()),
+ String8(prefixPath8.c_str()), pkgIdOverride);
+
+ return (res) ? (jint)cookie : 0;
+}
+
+static jboolean android_content_AssetManager_removeOverlayPath(JNIEnv* env, jobject clazz,
+ jstring packageName, jint cookie)
+{
+ if (packageName == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", "packageName");
+ return JNI_FALSE;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+
+ const char* name8 = env->GetStringUTFChars(packageName, NULL);
+ bool res = am->removeOverlayPath(String8(name8), cookie);
+ env->ReleaseStringUTFChars(packageName, name8);
+
+ return res;
+}
+
static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
{
AssetManager* am = assetManagerForJavaObject(env, clazz);
@@ -1139,7 +1258,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
const ResTable::bag_entry* defStyleStart = NULL;
uint32_t defStyleTypeSetFlags = 0;
ssize_t bagOff = defStyleRes != 0
- ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
+ ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags, true) : -1;
defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
@@ -1358,7 +1477,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
const ResTable::bag_entry* defStyleAttrStart = NULL;
uint32_t defStyleTypeSetFlags = 0;
ssize_t bagOff = defStyleRes != 0
- ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
+ ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags, true) : -1;
defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
@@ -1366,7 +1485,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
// Retrieve the style class bag, if requested.
const ResTable::bag_entry* styleAttrStart = NULL;
uint32_t styleTypeSetFlags = 0;
- bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
+ bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags, true) : -1;
styleTypeSetFlags |= styleBagTypeSetFlags;
const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
@@ -1710,7 +1829,7 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz
const ResTable::bag_entry* arrayEnt = NULL;
uint32_t arrayTypeSetFlags = 0;
- ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
+ ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags, true);
const ResTable::bag_entry* endArrayEnt = arrayEnt +
(bagOff >= 0 ? bagOff : 0);
@@ -2048,6 +2167,50 @@ static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env,
return AssetManager::getGlobalCount();
}
+static jint android_content_AssetManager_getBasePackageCount(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+
+ return am->getResources().getBasePackageCount();
+}
+
+static jstring android_content_AssetManager_getBasePackageName(JNIEnv* env, jobject clazz,
+ jint index)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+
+ String16 packageName(am->getBasePackageName(index));
+ return env->NewString((const jchar*)packageName.string(), packageName.size());
+}
+
+static jstring android_content_AssetManager_getBaseResourcePackageName(JNIEnv* env, jobject clazz,
+ jint index)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+
+ String16 packageName(am->getResources().getBasePackageName(index));
+ return env->NewString((const jchar*)packageName.string(), packageName.size());
+}
+
+static jint android_content_AssetManager_getBasePackageId(JNIEnv* env, jobject clazz, jint index)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+
+ return am->getResources().getBasePackageId(index);
+}
+
// ----------------------------------------------------------------------------
/*
@@ -2081,8 +2244,22 @@ static JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_getAssetRemainingLength },
{ "addAssetPathNative", "(Ljava/lang/String;)I",
(void*) android_content_AssetManager_addAssetPath },
- { "addOverlayPathNative", "(Ljava/lang/String;)I",
+ { "addOverlayPathNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
(void*) android_content_AssetManager_addOverlayPath },
+ { "addCommonOverlayPathNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+ (void*) android_content_AssetManager_addCommonOverlayPath },
+ { "addIconPathNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)I",
+ (void*) android_content_AssetManager_addIconPath },
+ { "removeOverlayPathNative", "(Ljava/lang/String;I)Z",
+ (void*) android_content_AssetManager_removeOverlayPath },
+ { "getBasePackageCount", "()I",
+ (void*) android_content_AssetManager_getBasePackageCount },
+ { "getBasePackageName", "(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getBasePackageName },
+ { "getBaseResourcePackageName", "(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getBaseResourcePackageName },
+ { "getBasePackageId", "(I)I",
+ (void*) android_content_AssetManager_getBasePackageId },
{ "isUpToDate", "()Z",
(void*) android_content_AssetManager_isUpToDate },
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c139cd7..9718fd7 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -144,7 +144,7 @@ static volatile int32_t gNumDeathRefs = 0;
static void incRefsCreated(JNIEnv* env)
{
int old = android_atomic_inc(&gNumRefsCreated);
- if (old == 200) {
+ if (old == 2000) {
android_atomic_and(0, &gNumRefsCreated);
env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
gBinderInternalOffsets.mForceGc);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index ee8fb19..8967cf2 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -370,27 +370,40 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz,
return pri;
}
+static bool memcgSupported = false;
+static int memcgTasksFd = -1;
+static int memcgSwapTasksFd = -1;
+static pthread_once_t memcgInitOnce = PTHREAD_ONCE_INIT;
+
+static void memcgInit(void) {
+ if (!access("/sys/fs/cgroup/memory/tasks", F_OK)) {
+ memcgTasksFd = open("/sys/fs/cgroup/memory/tasks", O_WRONLY);
+ if (memcgTasksFd < 0) {
+ return;
+ }
+ memcgSwapTasksFd = open("/sys/fs/cgroup/memory/sw/tasks", O_WRONLY);
+ if (memcgSwapTasksFd < 0) {
+ close(memcgTasksFd);
+ return;
+ }
+ memcgSupported = true;
+ }
+}
+
jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz,
jint pid, jboolean is_increased)
{
- char text[64];
-
- if (is_increased) {
- strcpy(text, "/sys/fs/cgroup/memory/sw/tasks");
- } else {
- strcpy(text, "/sys/fs/cgroup/memory/tasks");
- }
-
- struct stat st;
- if (stat(text, &st) || !S_ISREG(st.st_mode)) {
+ pthread_once(&memcgInitOnce, memcgInit);
+ if (!memcgSupported) {
return false;
}
- int fd = open(text, O_WRONLY);
+ int fd = is_increased ? memcgSwapTasksFd : memcgTasksFd;
+ char text[64];
+
if (fd >= 0) {
sprintf(text, "%" PRId32, pid);
write(fd, text, strlen(text));
- close(fd);
}
return true;
diff --git a/core/jni/android_util_SeempLog.cpp b/core/jni/android_util_SeempLog.cpp
new file mode 100644
index 0000000..734490a
--- /dev/null
+++ b/core/jni/android_util_SeempLog.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2007-2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <assert.h>
+#include <cutils/properties.h>
+#include <utils/String8.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+#ifdef __BIONIC__
+#include <android/set_abort_message.h>
+#endif
+#include <utils/Log.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "utils/misc.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#define LOG_BUF_SIZE 1024
+#define SEEMP_SOCK_NAME "/dev/socket/seempdw"
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+static int __write_to_log_init(struct iovec *vec, size_t nr);
+static int (*write_to_log)(struct iovec *vec, size_t nr) = __write_to_log_init;
+static int logd_fd = -1;
+
+/* give up, resources too limited */
+static int __write_to_log_null(struct iovec *vec __unused,
+ size_t nr __unused)
+{
+ return -1;
+}
+
+/* log_init_lock assumed */
+static int __write_to_log_initialize()
+{
+ int i, ret = 0;
+ if (logd_fd >= 0) {
+ i = logd_fd;
+ logd_fd = -1;
+ close(i);
+ }
+
+ i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (i < 0) {
+ ret = -errno;
+ write_to_log = __write_to_log_null;
+ } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) {
+ ret = -errno;
+ close(i);
+ i = -1;
+ write_to_log = __write_to_log_null;
+ } else {
+ struct sockaddr_un un;
+ memset(&un, 0, sizeof(struct sockaddr_un));
+ un.sun_family = AF_UNIX;
+ strlcpy(un.sun_path, SEEMP_SOCK_NAME, sizeof(un.sun_path));
+ if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) {
+ ret = -errno;
+ close(i);
+ i = -1;
+ }
+ }
+ logd_fd = i;
+ return ret;
+}
+
+static int __write_to_log_socket(struct iovec *vec, size_t nr)
+{
+ ssize_t ret;
+ if (logd_fd < 0) {
+ return -EBADF;
+ }
+
+ /*
+ * The write below could be lost, but will never block.
+ *
+ * ENOTCONN occurs if logd dies.
+ * EAGAIN occurs if logd is overloaded.
+ */
+ ret = writev(logd_fd, vec, nr);
+ if (ret < 0) {
+ ret = -errno;
+ if (ret == -ENOTCONN) {
+ ret = __write_to_log_initialize();
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = writev(logd_fd, vec, nr);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int __write_to_log_init(struct iovec *vec, size_t nr)
+{
+ if (write_to_log == __write_to_log_init) {
+ int ret;
+
+ ret = __write_to_log_initialize();
+ if (ret < 0) {
+ return ret;
+ }
+
+ write_to_log = __write_to_log_socket;
+ }
+ return write_to_log(vec, nr);
+}
+
+int __android_seemp_socket_write(int len, const char *msg)
+{
+ struct iovec vec;
+ vec.iov_base = (void *) msg;
+ vec.iov_len = len;
+
+ return write_to_log(&vec, 1);
+}
+
+namespace android {
+
+/*
+ * In class android.util.Log:
+ * public static native int println_native(int buffer, int priority, String tag, String msg)
+ */
+static jint android_util_SeempLog_println_native(JNIEnv* env, jobject clazz,
+ jint api, jstring msgObj)
+{
+ if (msgObj == NULL) {
+ jniThrowNullPointerException(env, "seemp_println needs a message");
+ return -1;
+ }
+
+ int apiId = (int)api;
+ int apiIdLen = sizeof(apiId);
+ int utf8MsgLen = env->GetStringUTFLength(msgObj);
+ int len = apiIdLen + 1 + utf8MsgLen + 1;
+ char *msg = (char*)malloc(len);
+ if ( NULL == msg )
+ {
+ return -1;
+ }
+ char *params = msg + apiIdLen + 1; // api_id + encoding byte + params
+
+ *((int*)msg) = apiId; // copy api id
+ // // skip encoding byte
+ env->GetStringUTFRegion(msgObj, 0, env->GetStringLength(msgObj), params); // copy message
+ msg[len - 1] = 0; // copy terminating zero
+
+ int res = __android_seemp_socket_write(len, msg); // send message
+
+ free(msg);
+
+ return res;
+}
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "seemp_println_native", "(ILjava/lang/String;)I",
+ (void*) android_util_SeempLog_println_native },
+};
+
+int register_android_util_SeempLog(JNIEnv* env)
+{
+ jclass clazz = env->FindClass("android/util/SeempLog");
+ if (clazz == NULL) {
+ return -1;
+ }
+
+ return AndroidRuntime::registerNativeMethods(env, "android/util/SeempLog", gMethods,
+ NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index bb8ef83..ef1e4ab 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -102,10 +102,16 @@ static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobje
// ----------------------------------------------------------------------------
static jint android_view_DisplayListCanvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
+ if (!Caches::hasInstance()) {
+ android::uirenderer::renderthread::RenderProxy::staticFence();
+ }
return Caches::getInstance().maxTextureSize;
}
static jint android_view_DisplayListCanvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
+ if (!Caches::hasInstance()) {
+ android::uirenderer::renderthread::RenderProxy::staticFence();
+ }
return Caches::getInstance().maxTextureSize;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 20352eb..7156c0f 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -316,6 +316,39 @@ static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, j
}
}
+static void nativeSetBlur(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat blur) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->setBlur(blur);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+}
+
+static void nativeSetBlurMaskSurface(JNIEnv* env, jclass clazz, jlong nativeObject, jlong maskLayerNativeObject) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ SurfaceControl* const maskLayer = reinterpret_cast<SurfaceControl *>(maskLayerNativeObject);
+ status_t err = ctrl->setBlurMaskSurface(maskLayer);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+}
+
+static void nativeSetBlurMaskSampling(JNIEnv* env, jclass clazz, jlong nativeObject, jint blurMaskSampling) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->setBlurMaskSampling(blurMaskSampling);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+}
+
+static void nativeSetBlurMaskAlphaThreshold(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->setBlurMaskAlphaThreshold(alpha);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+}
+
static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
return javaObjectForIBinder(env, token);
@@ -614,6 +647,14 @@ static JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetWindowCrop },
{"nativeSetLayerStack", "(JI)V",
(void*)nativeSetLayerStack },
+ {"nativeSetBlur", "(JF)V",
+ (void*)nativeSetBlur },
+ {"nativeSetBlurMaskSurface", "(JJ)V",
+ (void*)nativeSetBlurMaskSurface },
+ {"nativeSetBlurMaskSampling", "(JI)V",
+ (void*)nativeSetBlurMaskSampling },
+ {"nativeSetBlurMaskAlphaThreshold", "(JF)V",
+ (void*)nativeSetBlurMaskAlphaThreshold },
{"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
(void*)nativeGetBuiltInDisplay },
{"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 47132f4..7400ef0 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -262,11 +262,11 @@ static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
env->ReleaseStringUTFChars(jname, name);
}
-static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jsurface) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
- return proxy->initialize(window);
+ proxy->initialize(window);
}
static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
@@ -461,7 +461,7 @@ static JNINativeMethod gMethods[] = {
{ "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
{ "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
{ "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
- { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
+ { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
{ "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
{ "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
{ "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index daa6f82..91765f9 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -36,7 +36,7 @@
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
-
+#include <dlfcn.h>
#define APK_LIB "lib/"
#define APK_LIB_LEN (sizeof(APK_LIB) - 1)
@@ -55,6 +55,10 @@
#define TMP_FILE_PATTERN "/tmp.XXXXXX"
#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1)
+#define LIB_UNINIT 0
+#define LIB_INITED_AND_FAIL -1
+#define LIB_INITED_AND_SUCCESS 1
+
namespace android {
// These match PackageManager.java install codes
@@ -70,6 +74,24 @@ enum install_status_t {
typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
+typedef int (*PGetAssetsStatusFunc) (ZipFileRO*, Vector<ScopedUtfChars*>, const int);
+static PGetAssetsStatusFunc GetAssetsStatusFunc = NULL;
+static int g_assetLibInit = LIB_UNINIT;
+
+static int initAssetsVerifierLib() {
+ if (g_assetLibInit != LIB_UNINIT) return g_assetLibInit;
+ void* handle = dlopen("libassetsverifier.so", RTLD_NOW);
+ if (handle != NULL) {
+ GetAssetsStatusFunc = (PGetAssetsStatusFunc)dlsym(handle, "getAssetsStatus");
+ if (GetAssetsStatusFunc != NULL) {
+ g_assetLibInit = LIB_INITED_AND_SUCCESS;
+ } else {
+ g_assetLibInit = LIB_INITED_AND_FAIL;
+ }
+ }
+ return g_assetLibInit;
+}
+
// Equivalent to android.os.FileUtils.isFilenameSafe
static bool
isFilenameSafe(const char* filename)
@@ -435,6 +457,10 @@ iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi,
static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) {
const int numAbis = env->GetArrayLength(supportedAbisArray);
Vector<ScopedUtfChars*> supportedAbis;
+#ifdef PICK_SUPPORTED_ABI_WITH_MAX_LIBS
+ int numLibs[numAbis+1] = {0}; // +1 to avoid 0 sized array
+ int maxLibs = 0;
+#endif
for (int i = 0; i < numAbis; ++i) {
supportedAbis.add(new ScopedUtfChars(env,
@@ -470,14 +496,47 @@ static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supported
for (int i = 0; i < numAbis; i++) {
const ScopedUtfChars* abi = supportedAbis[i];
if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) {
- // The entry that comes in first (i.e. with a lower index) has the higher priority.
- if (((i < status) && (status >= 0)) || (status < 0) ) {
+#ifdef PICK_SUPPORTED_ABI_WITH_MAX_LIBS
+ numLibs[i]++;
+ if (numLibs[i] > maxLibs) {
+ maxLibs = numLibs[i];
status = i;
+ } else if (numLibs[i] == maxLibs) {
+#endif
+ // The entry that comes in first (i.e. with a lower index) has the higher priority.
+ if (((i < status) && (status >= 0)) || (status < 0) ) {
+ status = i;
+ }
+#ifdef PICK_SUPPORTED_ABI_WITH_MAX_LIBS
}
+#endif
}
}
}
+ if(status <= 0) {
+ // Scan the 'assets' folder only if
+ // the abi (after scanning the lib folder)
+ // is not already set to 32-bit (i.e '1' or '2').
+
+ int asset_status = NO_NATIVE_LIBRARIES;
+ int rc = initAssetsVerifierLib();
+
+ if (rc == LIB_INITED_AND_SUCCESS) {
+ asset_status = GetAssetsStatusFunc(zipFile, supportedAbis, numAbis);
+ } else {
+ ALOGV("Failed to load assets verifier: %d", rc);
+ }
+ if(asset_status >= 0) {
+ // Override the ABI only if
+ // 'asset_status' is a valid ABI (64-bit or 32-bit).
+ // This is to prevent cases where 'lib' folder
+ // has native libraries, but
+ // 'assets' folder has none.
+ status = asset_status;
+ }
+ }
+
for (int i = 0; i < numAbis; ++i) {
delete supportedAbis[i];
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1d1685a..ac64edf 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -368,8 +368,8 @@ static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
return;
}
jsize count = env->GetArrayLength(fdsToClose);
- jint *ar = env->GetIntArrayElements(fdsToClose, 0);
- if (!ar) {
+ ScopedIntArrayRO ar(env, fdsToClose);
+ if (ar.get() == NULL) {
ALOGE("Bad fd array");
RuntimeAbort(env);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 28933e1..50a4b38 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -18,6 +18,7 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="android" coreApp="true" android:sharedUserId="android.uid.system"
android:sharedUserLabel="@string/android_system_label">
@@ -77,6 +78,7 @@
<protected-broadcast android:name="android.intent.action.USER_FOREGROUND" />
<protected-broadcast android:name="android.intent.action.USER_SWITCHED" />
<protected-broadcast android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
+ <protected-broadcast android:name="android.intent.action.SU_SESSION_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
@@ -237,6 +239,7 @@
<protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
<protected-broadcast android:name="android.os.UpdateLock.UPDATE_LOCK_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.NAVBAR_EDIT" />
<protected-broadcast android:name="android.intent.action.DREAMING_STARTED" />
<protected-broadcast android:name="android.intent.action.DREAMING_STOPPED" />
@@ -321,8 +324,11 @@
<protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" />
<protected-broadcast android:name="android.app.action.SYSTEM_UPDATE_POLICY_CHANGED" />
<protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" />
+ <protected-broadcast android:name="org.cyanogenmod.intent.action.THEME_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.THEME_RESOURCES_CACHED" />
<protected-broadcast android:name="android.net.action.SHOW_NETWORK_POLICY_NOTIFICATION" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
@@ -1233,6 +1239,12 @@
<permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to override the power key action
+ @hide <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.PREVENT_POWER_KEY"
+ android:protectionLevel="signature|privileged" />
+
<!-- =========================================== -->
<!-- Permissions associated with camera and image capture -->
<!-- =========================================== -->
@@ -1268,7 +1280,8 @@
<!-- @SystemApi Allows read access to privileged phone state.
@hide Used internally. -->
<permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
@@ -1330,14 +1343,15 @@
<!-- @SystemApi Allows an application to write to internal media storage
@hide -->
<permission android:name="android.permission.WRITE_MEDIA_STORAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows an application to manage access to documents, usually as part
of a document picker.
<p>Protection level: signature
-->
<permission android:name="android.permission.MANAGE_DOCUMENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|system" />
<!-- ================================== -->
<!-- Permissions for screenlock -->
@@ -1392,7 +1406,8 @@
that removes restrictions on where broadcasts can be sent and allows other
types of interactions. -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
users on the device. This permission is not available to
@@ -1492,6 +1507,14 @@
android:description="@string/permdesc_setWallpaperHints"
android:protectionLevel="normal" />
+ <!-- Allows applications to set the keyguard wallpaper
+ @hide -->
+ <permission android:name="android.permission.SET_KEYGUARD_WALLPAPER"
+ android:permissionGroup="android.permission-group.WALLPAPER"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_setKeyguardWallpaper"
+ android:description="@string/permdesc_setKeyguardWallpaper" />
+
<!-- ============================================ -->
<!-- Permissions for changing the system clock -->
<!-- ============================================ -->
@@ -1635,7 +1658,8 @@
{@link android.content.pm.PackageManager#addPackageToPreferred}
for details. -->
<permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows an application to receive the
{@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -1736,7 +1760,8 @@
interacting with the recovery (system update) system.
@hide -->
<permission android:name="android.permission.RECOVERY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows the system to bind to an application's task services
@hide -->
@@ -1760,7 +1785,8 @@
<!-- @SystemApi Allows an application to read or write the secure system settings.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_SECURE_SETTINGS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows an application to retrieve state dump information from system services.
<p>Not for use by third-party applications. -->
@@ -1802,7 +1828,8 @@
<!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
<permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows applications to RW to diagnostic resources.
<p>Not for use by third-party applications. -->
@@ -1896,7 +1923,8 @@
@hide
-->
<permission android:name="android.permission.SET_ACTIVITY_WATCHER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows an application to call the activity manager shutdown() API
to put the higher-level system there into a shutdown state.
@@ -2150,7 +2178,8 @@
get access to the frame buffer data.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_FRAME_BUFFER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows an application to use InputFlinger's low level features.
@hide -->
@@ -2192,7 +2221,8 @@
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
<p>Not for use by third-party applications.</p>
@@ -2203,12 +2233,14 @@
<!-- @SystemApi Allows an application to capture video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows an application to capture secure video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows an application to know what content is playing and control its playback.
<p>Not for use by third-party applications due to privacy of media consumption</p> -->
@@ -2225,7 +2257,8 @@
<!-- @SystemApi Required to be able to reboot the device.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.REBOOT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- @SystemApi Allows low-level access to power management.
<p>Not for use by third-party applications.
@@ -2257,6 +2290,24 @@
<permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
android:protectionLevel="signature" />
+ <!-- Allows an application to add an address to the whitelisted protected sms
+ list
+ @hide -->
+ <permission android:name="android.permission.MODIFY_PROTECTED_SMS_LIST"
+ android:permissionGroup="android.permission-group.MESSAGES"
+ android:label="@string/permlab_modifyProtectedSmsList"
+ android:description="@string/permdesc_modifyProtectedSmsList"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to receive sms (usually for auth or registration)
+ from whitelisted addresses
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_PROTECTED_SMS"
+ android:permissionGroup="android.permission-group.MESSAGES"
+ android:label="@string/permlab_receiveProtectedSms"
+ android:description="@string/permdesc_receiveProtectedSms"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to broadcast an SMS receipt notification.
<p>Not for use by third-party applications.
-->
@@ -2335,11 +2386,21 @@
<permission android:name="android.permission.BATTERY_STATS"
android:protectionLevel="signature|privileged|development" />
+ <!-- Allows an application to reset the device battery statistics.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.RESET_BATTERY_STATS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:label="@string/permlab_resetBatteryStats"
+ android:description="@string/permdesc_resetBatteryStats"
+ android:protectionLevel="signature|system|development" />
+
<!-- @SystemApi Allows an application to control the backup and restore process.
<p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.BACKUP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows a package to launch the secure full-backup confirmation UI.
ONLY the system process may hold this permission.
@@ -2424,7 +2485,8 @@
<!-- @SystemApi Allow an application to read and write the cache partition.
@hide -->
<permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ androidprv:allowViaWhitelist="true" />
<!-- Must be required by default container service so that only
the system can bind to it and use it to copy
@@ -2526,7 +2588,8 @@
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
<permission android:name="android.permission.MANAGE_FINGERPRINT"
@@ -2539,7 +2602,8 @@
<!-- Allows an application to control keyguard. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.CONTROL_KEYGUARD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ androidprv:allowViaWhitelist="true" />
<!-- Allows an application to listen to trust changes. Only allowed for system processes.
@hide -->
@@ -2675,6 +2739,36 @@
<permission android:name="android.permission.DISPATCH_NFC_MESSAGE"
android:protectionLevel="signature|privileged" />
+ <!-- =============================================================== -->
+ <!-- Permissions for accessing security data -->
+ <!-- =============================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that allow an application to access or configure
+ the device security information.
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission-group android:name="android.permission-group.SECURITY"
+ android:label="@string/permgrouplab_security"
+ android:icon="@drawable/perm_group_security"
+ android:description="@string/permgroupdesc_security"
+ android:priority="400"/>
+
+ <!-- Allows an application to read the phone blacklist data.
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.READ_PHONE_BLACKLIST"
+ android:permissionGroup="android.permission-group.SECURITY"
+ android:protectionLevel="signature|system"
+ android:label="@string/permlab_readPhoneBlacklist"
+ android:description="@string/permdesc_readPhoneBlacklist" />
+
+ <!-- Allows an application to change the phone blacklist data.
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.CHANGE_PHONE_BLACKLIST"
+ android:permissionGroup="android.permission-group.SECURITY"
+ android:protectionLevel="signature|system"
+ android:label="@string/permlab_changePhoneBlacklist"
+ android:description="@string/permdesc_changePhoneBlacklist" />
+
<!-- The system process is explicitly the only one allowed to launch the
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
@@ -2882,6 +2976,10 @@
</intent-filter>
</receiver>
+ <service android:name="com.android.internal.os.storage.ExternalStorageFormatter"
+ android:permission="android.permission.MASTER_CLEAR"
+ android:exported="true" />
+
<service android:name="android.hardware.location.GeofenceHardwareService"
android:permission="android.permission.LOCATION_HARDWARE"
android:exported="false" />
diff --git a/core/res/res/anim/last_app_in.xml b/core/res/res/anim/last_app_in.xml
new file mode 100644
index 0000000..bf89dbf
--- /dev/null
+++ b/core/res/res/anim/last_app_in.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The CyanogenMod 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ >
+
+ <translate android:fromXDelta="0%" android:toXDelta="-35%"
+ android:zAdjustment="bottom"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/fast_out_linear_in"
+ />
+ <scale android:fromXScale="0.80" android:toXScale="1.0"
+ android:fromYScale="0.80" android:toYScale="1.0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/linear"
+ />
+ <translate android:fromXDelta="-35%" android:toXDelta="35%"
+ android:zAdjustment="top"
+ android:startOffset="@android:integer/config_shortAnimTime"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ />
+ <alpha android:fromAlpha="0.6" android:toAlpha="1.0"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/linear"
+ />
+</set>
diff --git a/core/res/res/anim/last_app_out.xml b/core/res/res/anim/last_app_out.xml
new file mode 100644
index 0000000..834dfff
--- /dev/null
+++ b/core/res/res/anim/last_app_out.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The CyanogenMod 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ >
+
+ <translate android:fromXDelta="-35%" android:toXDelta="35%"
+ android:zAdjustment="top"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/fast_out_linear_in"
+ />
+ <scale android:fromXScale="1.0" android:toXScale="0.80"
+ android:fromYScale="1.0" android:toYScale="0.80"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/linear"
+ />
+ <translate android:fromXDelta="35%" android:toXDelta="-35%"
+ android:zAdjustment="bottom"
+ android:startOffset="@android:integer/config_shortAnimTime"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:interpolator="@android:interpolator/linear"
+ />
+</set>
diff --git a/core/res/res/anim/lock_screen_wallpaper_exit_noop.xml b/core/res/res/anim/lock_screen_wallpaper_exit_noop.xml
new file mode 100644
index 0000000..4cc5c70
--- /dev/null
+++ b/core/res/res/anim/lock_screen_wallpaper_exit_noop.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" android:startOffset="100">
+ <alpha
+ android:fromAlpha="0.0" android:toAlpha="0.0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_linear_in"
+ android:duration="150"/>
+
+ <!-- Empty animation so the animation has same duration as lock_screen_behind_enter animation
+ -->
+ <translate android:fromYDelta="0" android:toYDelta="0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:duration="300" />
+</set> \ No newline at end of file
diff --git a/core/res/res/color/preference_category_text_color.xml b/core/res/res/color/preference_category_text_color.xml
new file mode 100644
index 0000000..7916a5c
--- /dev/null
+++ b/core/res/res/color/preference_category_text_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorAccent" />
+</selector>
diff --git a/core/res/res/drawable-hdpi/ic_launcher_android.png b/core/res/res/drawable-hdpi/ic_launcher_android.png
index cce5187..cde69bc 100644
--- a/core/res/res/drawable-hdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-hdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png
new file mode 100644
index 0000000..ca00936
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_security.png b/core/res/res/drawable-hdpi/perm_group_security.png
new file mode 100644
index 0000000..47f0d6f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_security.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
index 39d2c95..3a9031e 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
index 3a9031e..39d2c95 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_launcher_android.png b/core/res/res/drawable-mdpi/ic_launcher_android.png
index 6a97d5b..c133a0c 100644
--- a/core/res/res/drawable-mdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-mdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png
new file mode 100644
index 0000000..2b125b9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_security.png b/core/res/res/drawable-mdpi/perm_group_security.png
new file mode 100644
index 0000000..cc00c16
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_security.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png
index b9c364c..217ea4e 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png
index 217ea4e..b9c364c 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo_cm.xml b/core/res/res/drawable-nodpi/platlogo_cm.xml
new file mode 100644
index 0000000..b863c27
--- /dev/null
+++ b/core/res/res/drawable-nodpi/platlogo_cm.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+
+ <path
+ android:name="body"
+ android:fillColor="#FFFFFF"
+ android:pathData="M24,12L24,12L24,12L24,12L24,12c7.7,0,14,1.2,14.9,2.6c0,0,0,0,0,0c1,1.5,1.1,6.5,1.1,9.4s-0.1,7.8-1.1,9.4
+c0,0,0,0,0,0C38,34.8,31.7,36,24,36l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0c-7.7,0-14-1.2-14.9-2.6c0,0,0,0,0,0C8.1,31.8,8,26.9,8,24
+s0.1-7.8,1.1-9.4c0,0,0,0,0,0C10,13.2,16.3,12,24,12L24,12L24,12L24,12L24,12z" />
+ <path
+ android:name="top"
+ android:fillColor="#EBEBEB"
+ android:pathData="M39,15c0,1.7-6.7,3-15,3S9,16.7,9,15s6.7-3,15-3S39,13.3,39,15z" />
+ <path
+ android:name="r_ant"
+ android:fillColor="#FFFFFF"
+ android:pathData="M35,15c-0.1,0-0.3,0-0.4-0.1c-0.5-0.2-0.8-0.8-0.5-1.3l2-5c0.2-0.5,0.8-0.8,1.3-0.5
+c0.5,0.2,0.8,0.8,0.5,1.3l-2,5C35.7,14.8,35.3,15,35,15z" />
+ <path
+ android:name="l_ant"
+ android:fillColor="#FFFFFF"
+ android:pathData="M13,15c0.1,0,0.3,0,0.4-0.1c0.5-0.2,0.8-0.8,0.5-1.3l-2-5c-0.2-0.5-0.8-0.8-1.3-0.5
+c-0.5,0.2-0.8,0.8-0.5,1.3l2,5C12.3,14.8,12.7,15,13,15z" />
+ <path
+ android:name="smile"
+ android:fillColor="#EBEBEB"
+ android:pathData="M22,32C22,32,22,32.1,22,32c0,0.9,0.6,1.5,1.4,1.5h1.1c0.8,0,1.5-0.7,1.5-1.5c0,0,0-0.1,0-0.1H22z" />
+ <path
+ android:name="l_eye"
+ android:fillColor="#EBEBEB"
+ android:pathData="M16,20c-2.8,0-5,2.2-5,5c0,2.8,2.2,5,5,5c2.8,0,5-2.2,5-5C21,22.2,18.8,20,16,20z" />
+ <path
+ android:name="r_eye"
+ android:fillColor="#EBEBEB"
+ android:pathData="M32,20c-2.8,0-5,2.2-5,5c0,2.8,2.2,5,5,5c2.8,0,5-2.2,5-5C37,22.2,34.8,20,32,20z" />
+</vector>
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 8cc9961..9dd9497 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,11 +1,11 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (c) 2015 The CyanogenMod Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
+ 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,
@@ -14,23 +14,26 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M21.3,6.6L21,6.9c0,1-3.8,1.7-9,1.7S3,7.9,3,6.9L2.7,6.6C2.1,7.6,2,10.7,2,12.5
+c0,1.8,0.1,4.9,0.7,5.8l0,0C3.2,19.3,7.2,20,12,20c4.8,0,8.8-0.7,9.3-1.7l0,0c0.6-1,0.7-4.1,0.7-5.8C22,10.7,21.9,7.6,21.3,6.6z
+M7,17c-1.7,0-3-1.3-3-3s1.3-3,3-3c1.7,0,3,1.3,3,3S8.7,17,7,17z
+M17,17c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3c1.7,0,3,1.3,3,3 C20,15.7,18.7,17,17,17z" />
<path
- android:pathData="M8.4,5.3c-0.2,0.0 -0.4,-0.2 -0.5,-0.4L7.1,1.6C7.0,1.4 7.2,1.1 7.4,1.0C7.7,0.9 8.0,1.1 8.0,1.4l0.8,3.3c0.1,0.3 -0.1,0.5 -0.4,0.6C8.5,5.3 8.4,5.3 8.4,5.3z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#BBFFFFFF"
+ android:pathData="M21.4,6.9c0,1-4.2,1.9-9.4,1.9S2.6,7.9,2.6,6.9S6.8,5,12,5S21.4,5.8,21.4,6.9z" />
<path
- android:pathData="M15.6,5.3c0.0,0.0 -0.1,0.0 -0.1,0.0c-0.3,-0.1 -0.4,-0.3 -0.4,-0.6L16.0,1.4C16.0,1.1 16.3,0.9 16.6,1.0c0.3,0.1 0.4,0.3 0.4,0.6l-0.8,3.3C16.1,5.1 15.9,5.3 15.6,5.3z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.7,6.5c-0.1,0.3-0.5,0.5-0.8,0.3c-0.3-0.1-0.5-0.5-0.3-0.8l1.3-3.1c0.1-0.3,0.5-0.5,0.8-0.3
+C20.9,2.7,21.1,3,21,3.4L19.7,6.5z" />
<path
- android:pathData="M18.6,5.4c-0.1,-0.1 -0.2,-0.1 -0.3,-0.2c0.2,0.2 0.3,0.3 0.3,0.5c0.0,0.9 -2.9,1.7 -6.6,1.7S5.4,6.7 5.4,5.7c0.0,-0.2 0.1,-0.3 0.3,-0.5C5.6,5.3 5.5,5.4 5.4,5.4C5.0,5.9 4.0,8.0 4.0,12.0s1.0,6.1 1.4,6.6C5.9,19.0 8.0,20.0 12.0,20.0s6.1,-1.0 6.6,-1.4C19.0,18.1 20.0,16.0 20.0,12.0S19.0,5.9 18.6,5.4zM8.0,13.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0c0.0,-0.6 0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0C9.0,12.6 8.6,13.0 8.0,13.0zM16.0,13.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0c0.0,-0.6 0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0C17.0,12.6 16.6,13.0 16.0,13.0z"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M5.35,5.7
- a 6.6 1.75 0 1 1 13.25 0
- a 6.6 1.75 0 1 1 -13.25 0
- z"
- android:fillColor="#BBFFFFFF" />
+ android:fillColor="#FFFFFF"
+ android:pathData="M4.3,6.5C4.5,6.8,4.8,7,5.1,6.8C5.5,6.7,5.6,6.3,5.5,6L4.2,2.9C4.1,2.6,3.7,2.4,3.4,2.5
+C3.1,2.7,2.9,3,3,3.4L4.3,6.5z" />
</vector>
diff --git a/core/res/res/drawable-xhdpi/ic_launcher_android.png b/core/res/res/drawable-xhdpi/ic_launcher_android.png
index b1097d6..bfa42f0 100644
--- a/core/res/res/drawable-xhdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-xhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png
new file mode 100644
index 0000000..653970f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_security.png b/core/res/res/drawable-xhdpi/perm_group_security.png
new file mode 100644
index 0000000..d165c74
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_security.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png
index cd0ca73..e443f45 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png
index e443f45..cd0ca73 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_launcher_android.png b/core/res/res/drawable-xxhdpi/ic_launcher_android.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png
new file mode 100644
index 0000000..362bf28
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_security.png b/core/res/res/drawable-xxhdpi/perm_group_security.png
new file mode 100644
index 0000000..670ae68
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_security.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
index 39dd3b8..b828430 100755
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
index b828430..39dd3b8 100755
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_launcher_android.png b/core/res/res/drawable-xxxhdpi/ic_launcher_android.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable/ic_lock_dnd_priority.xml b/core/res/res/drawable/ic_lock_dnd_priority.xml
new file mode 100644
index 0000000..0d45552
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_dnd_priority.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportHeight="48.0"
+ android:viewportWidth="48.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M24,4C12.95,4,4,12.95,4,24s8.95,20,20,20s20-8.95,20-20S35.05,4,24,4z M34,26h-8v8h-4v-8h-8v-4h8v-8h4v8h8V26z" />
+
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_lock_dnd_total_silence.xml b/core/res/res/drawable/ic_lock_dnd_total_silence.xml
new file mode 100644
index 0000000..0128dfe
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_dnd_total_silence.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0s10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,20.5c-4.7,0.0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12.0,3.5s8.5,3.8 8.5,8.5S16.7,20.5 12.0,20.5z"/>
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M12.0,6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,3.3 2.7,6.0 6.0,6.0s6.0,-2.7 6.0,-6.0C18.0,8.7 15.4,6.0 12.0,6.0zM15.0,13.0L9.0,13.0l0.0,-2.0l6.0,0.0L15.0,13.0z"/>
+
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_lock_lock.xml b/core/res/res/drawable/ic_lock_lock.xml
index 39f268a..6c87b42 100644
--- a/core/res/res/drawable/ic_lock_lock.xml
+++ b/core/res/res/drawable/ic_lock_lock.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_lock_lock_alpha"
- android:tint="?attr/colorControlActivated" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_lock_power_reboot.xml b/core/res/res/drawable/ic_lock_power_reboot.xml
new file mode 100644
index 0000000..82c7927
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_power_reboot.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2014, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_lock_power_reboot_alpha"
+ android:tint="?attr/colorControlNormal" />
+
diff --git a/core/res/res/drawable/ic_lock_ring.xml b/core/res/res/drawable/ic_lock_ring.xml
new file mode 100644
index 0000000..92b4b2e
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_ring.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z"/>
+
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/ic_lock_screenshot.xml b/core/res/res/drawable/ic_lock_screenshot.xml
new file mode 100644
index 0000000..b682f92
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_screenshot.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="@color/white"
+ android:pathData="M16 1H8C6.34 1 5 2.34 5 4v16c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V4c0-1.66-1.34-3-3-3zm-2 20h-4v-1h4v1zm3.25-3H6.75V4h10.5v14z" />
+</vector>
diff --git a/core/res/res/drawable/ic_lock_settings.xml b/core/res/res/drawable/ic_lock_settings.xml
new file mode 100644
index 0000000..4c6ded2
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_settings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="@color/white"
+ android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" />
+</vector>
diff --git a/core/res/res/drawable/ic_lock_user.xml b/core/res/res/drawable/ic_lock_user.xml
new file mode 100644
index 0000000..e951319
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_user.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="@color/white"
+ android:pathData="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
+</vector>
diff --git a/core/res/res/drawable/ic_lock_vibrate.xml b/core/res/res/drawable/ic_lock_vibrate.xml
new file mode 100644
index 0000000..f38ebc2
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_vibrate.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z"/>
+
+</vector> \ No newline at end of file
diff --git a/core/res/res/drawable/progress_large.xml b/core/res/res/drawable/progress_large.xml
index 4f016bc..44b4103 100644
--- a/core/res/res/drawable/progress_large.xml
+++ b/core/res/res/drawable/progress_large.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_black_76"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/progress_large_white.xml b/core/res/res/drawable/progress_large_white.xml
index c690ed4..6c2388c 100644
--- a/core/res/res/drawable/progress_large_white.xml
+++ b/core/res/res/drawable/progress_large_white.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_white_76"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/progress_medium.xml b/core/res/res/drawable/progress_medium.xml
index eb1bd50..82ad686 100644
--- a/core/res/res/drawable/progress_medium.xml
+++ b/core/res/res/drawable/progress_medium.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_black_48"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/progress_medium_white.xml b/core/res/res/drawable/progress_medium_white.xml
index b4f9b31..886ee05 100644
--- a/core/res/res/drawable/progress_medium_white.xml
+++ b/core/res/res/drawable/progress_medium_white.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_white_48"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/progress_small.xml b/core/res/res/drawable/progress_small.xml
index e0ee5e4..1881da3 100644
--- a/core/res/res/drawable/progress_small.xml
+++ b/core/res/res/drawable/progress_small.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_black_16"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/progress_small_titlebar.xml b/core/res/res/drawable/progress_small_titlebar.xml
index 8cfba86..5bb5cf8 100644
--- a/core/res/res/drawable/progress_small_titlebar.xml
+++ b/core/res/res/drawable/progress_small_titlebar.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_white_16"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/progress_small_white.xml b/core/res/res/drawable/progress_small_white.xml
index 8cfba86..5bb5cf8 100644
--- a/core/res/res/drawable/progress_small_white.xml
+++ b/core/res/res/drawable/progress_small_white.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_white_16"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/search_spinner.xml b/core/res/res/drawable/search_spinner.xml
index 31a77c3..b8c8b09 100644
--- a/core/res/res/drawable/search_spinner.xml
+++ b/core/res/res/drawable/search_spinner.xml
@@ -21,5 +21,5 @@
android:drawable="@drawable/spinner_black_20"
android:pivotX="50%"
android:pivotY="50%"
- android:framesCount="12"
- android:frameDuration="100" />
+ android:framesCount="48"
+ android:frameDuration="25" />
diff --git a/core/res/res/drawable/stat_notify_privacy_guard.xml b/core/res/res/drawable/stat_notify_privacy_guard.xml
new file mode 100644
index 0000000..bcf3a7f
--- /dev/null
+++ b/core/res/res/drawable/stat_notify_privacy_guard.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26dp"
+ android:height="24dp"
+ android:viewportWidth="26"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M11.999,11.488c0.017,0.148,0.013,0.301-0.017,0.455c-0.155,0.804-0.932,1.33-1.736,1.175 c-0.804-0.155-1.33-0.933-1.175-1.736c0.03-0.154,0.083-0.297,0.154-0.428L11.999,11.488Z M16.775,10.953l-2.774,0.535 c-0.017,0.148-0.013,0.301,0.017,0.455c0.155,0.804,0.932,1.33,1.736,1.175c0.804-0.155,1.33-0.933,1.175-1.736 C16.899,11.228,16.846,11.084,16.775,10.953z M21.539,8.978c-0.132,2.629-0.803,5.264-2.162,7.534 c-1.186,1.991-2.889,3.675-4.905,4.82c-0.459,0.259-0.932,0.494-1.427,0.676c-0.061,0.029-0.122-0.014-0.18-0.032 c-1.047-0.415-2.019-1.006-2.909-1.693c-1.807-1.397-3.239-3.263-4.151-5.356c-0.725-1.651-1.137-3.429-1.297-5.222 C4.33,7.77,4.442,5.816,4.73,3.896c0.601,0.053,1.207,0.031,1.807-0.017c1.309-0.115,2.596-0.41,3.849-0.799 c0.888-0.283,1.766-0.604,2.611-0.999c1.13,0.523,2.311,0.935,3.512,1.26c1.549,0.412,3.157,0.666,4.763,0.562 c0.116,0.846,0.216,1.695,0.261,2.548c0.002,0.241,0.042,0.481,0.037,0.723C21.574,7.776,21.594,8.379,21.539,8.978z M17.957,10.132 c0-0.787-0.345-1.322-1.002-1.675V6.396c0-0.179-0.145-0.324-0.324-0.324c-0.179,0-0.324,0.145-0.324,0.324v1.799 c-0.821-0.248-1.933-0.34-3.307-0.34V7.86h0V7.856c-0.155,0-0.305,0.002-0.453,0.004h-0.001c-1.075,0.018-1.973,0.101-2.677,0.286 v-1.75c0-0.179-0.145-0.324-0.324-0.324c-0.179,0-0.324,0.145-0.324,0.324v1.975C8.449,8.72,8.043,9.277,8.043,10.132v1.943v0.504 v0.554c0,1.702,1.613,2.225,4.503,2.272v0.003h0.179c0.09,0.001,0.182,0.001,0.275,0.001v-0.001h0v0.001 c0.093,0,0.184-0.001,0.275-0.001h0.013c2.995-0.03,4.67-0.54,4.67-2.275v-0.554v-0.504V10.132z"
+ android:fillColor="#FFFFFFFF" />
+</vector>
diff --git a/core/res/res/drawable/stat_notify_protected.xml b/core/res/res/drawable/stat_notify_protected.xml
new file mode 100644
index 0000000..d67a348
--- /dev/null
+++ b/core/res/res/drawable/stat_notify_protected.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26dp"
+ android:height="24dp"
+ android:viewportWidth="26"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="#000000"
+ android:pathData="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml
index bf46af8..abd9b64 100644
--- a/core/res/res/layout-xlarge/activity_list.xml
+++ b/core/res/res/layout-xlarge/activity_list.xml
@@ -58,7 +58,7 @@
<View android:id="@+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
- android:background="@android:color/holo_blue_light" />
+ android:background="@color/activity_list_divider_color" />
<!-- If the client uses a customTitle, it will be added here. -->
</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 34cb21d..44a11d9 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -34,7 +34,7 @@
android:layout_width="match_parent"
android:layout_height="2dip"
android:visibility="gone"
- android:background="@android:color/holo_blue_light" />
+ android:background="@color/dialog_divider_color" />
<LinearLayout android:id="@+id/title_template"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -60,7 +60,7 @@
android:layout_width="match_parent"
android:layout_height="2dip"
android:visibility="gone"
- android:background="@android:color/holo_blue_light" />
+ android:background="@color/dialog_divider_color" />
<!-- If the client uses a customTitle, it will be added here. -->
</LinearLayout>
diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
index 383d771..a80d40e 100644
--- a/core/res/res/layout/app_permission_item.xml
+++ b/core/res/res/layout/app_permission_item.xml
@@ -32,7 +32,7 @@
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:scaleType="fitCenter"
- android:tint="@android:color/black"/>
+ android:tint="@color/app_permission_icon_tint"/>
<ImageView
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/app_permission_item_money.xml b/core/res/res/layout/app_permission_item_money.xml
index 2056285..f66be6e 100644
--- a/core/res/res/layout/app_permission_item_money.xml
+++ b/core/res/res/layout/app_permission_item_money.xml
@@ -64,7 +64,7 @@
android:id="@+id/perm_money_label"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="16sp"
- android:textColor="@color/perms_costs_money"
+ android:textColor="@color/perms_costs_money_text_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/perm_money_icon"
diff --git a/core/res/res/layout/character_picker_button.xml b/core/res/res/layout/character_picker_button.xml
index b74e620..0213dc1 100644
--- a/core/res/res/layout/character_picker_button.xml
+++ b/core/res/res/layout/character_picker_button.xml
@@ -21,6 +21,6 @@
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceLarge"
android:background="@drawable/btn_keyboard_key_trans"
- android:textColor="#FFFFFFFF"
+ android:textColor="@color/character_picker_button_text_color"
/>
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 41726fb..c969060 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -31,7 +31,7 @@
android:layout_alwaysShow="true"
android:elevation="8dp"
android:paddingStart="16dp"
- android:background="@color/white" >
+ android:background="@color/resolver_list_bg" >
<ImageView android:id="@+id/title_icon"
android:layout_width="24dp"
android:layout_height="24dp"
@@ -89,7 +89,7 @@
android:id="@+id/resolver_list"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:background="@color/white"
+ android:background="@color/resolver_list_bg"
android:elevation="8dp"
android:listSelector="@color/transparent"
android:divider="@null"
@@ -100,7 +100,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
- android:background="@color/white"
+ android:background="@color/resolver_list_bg"
android:text="@string/noApplications"
android:padding="32dp"
android:gravity="center"
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index f8a2bf7..856e20b 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -31,7 +31,7 @@ This is a custom layout for a dialog.
<View android:id="@+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
- android:background="@android:color/holo_blue_light" />
+ android:background="@color/dialog_divider_color" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
index 0a692ee..94ecfa7 100644
--- a/core/res/res/layout/dialog_title_holo.xml
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -33,7 +33,7 @@ enabled.
<View android:id="@+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
- android:background="@android:color/holo_blue_light" />
+ android:background="@color/dialog_divider_color" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
index e3d771c..3f20a5f 100644
--- a/core/res/res/layout/dialog_title_icons_holo.xml
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -51,7 +51,7 @@ enabled.
<View android:id="@+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="1dip"
- android:background="@android:color/holo_blue_light" />
+ android:background="@color/dialog_divider_color" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
diff --git a/core/res/res/layout/global_actions_silent_mode.xml b/core/res/res/layout/global_actions_silent_mode.xml
index a358623..56fa28b 100644
--- a/core/res/res/layout/global_actions_silent_mode.xml
+++ b/core/res/res/layout/global_actions_silent_mode.xml
@@ -26,7 +26,7 @@
android:layout_width="64dp"
android:layout_height="match_parent"
android:background="?android:attr/actionBarItemBackground"
- android:contentDescription="@string/silent_mode_silent"
+ android:contentDescription="@string/silent_mode_none"
android:focusable="true"
>
<ImageView
@@ -37,12 +37,13 @@
android:layout_marginEnd="8dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
- android:src="@drawable/ic_audio_ring_notif_mute"
+ android:src="@drawable/ic_lock_dnd_total_silence"
android:scaleType="center"
android:duplicateParentState="true"
android:background="@drawable/silent_mode_indicator"
/>
</LinearLayout>
+
<!-- Spacer -->
<View android:layout_width="0dp"
android:layout_height="match_parent"
@@ -54,7 +55,7 @@
android:layout_width="64dp"
android:layout_height="match_parent"
android:background="?android:attr/actionBarItemBackground"
- android:contentDescription="@string/silent_mode_vibrate"
+ android:contentDescription="@string/silent_mode_priority"
android:focusable="true"
>
<ImageView
@@ -65,7 +66,7 @@
android:layout_marginEnd="8dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
- android:src="@drawable/ic_audio_ring_notif_vibrate"
+ android:src="@drawable/ic_lock_dnd_priority"
android:scaleType="center"
android:duplicateParentState="true"
android:background="@drawable/silent_mode_indicator"
@@ -83,6 +84,35 @@
android:layout_width="64dp"
android:layout_height="match_parent"
android:background="?android:attr/actionBarItemBackground"
+ android:contentDescription="@string/silent_mode_vibrate"
+ android:focusable="true"
+ >
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:src="@drawable/ic_lock_vibrate"
+ android:scaleType="center"
+ android:duplicateParentState="true"
+ android:background="@drawable/silent_mode_indicator"
+ />
+ </LinearLayout>
+
+ <!-- Spacer -->
+ <View android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible"/>
+
+ <LinearLayout
+ android:id="@+id/option4"
+ android:layout_width="64dp"
+ android:layout_height="match_parent"
+ android:background="?android:attr/actionBarItemBackground"
android:contentDescription="@string/silent_mode_ring"
android:focusable="true"
>
@@ -94,10 +124,10 @@
android:layout_marginEnd="8dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
- android:src="@drawable/ic_audio_ring_notif"
+ android:src="@drawable/ic_lock_ring"
android:scaleType="center"
android:duplicateParentState="true"
android:background="@drawable/silent_mode_indicator"
/>
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
index 28fbea5..9f3d44d 100644
--- a/core/res/res/layout/immersive_mode_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -16,7 +16,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#ff009688"
+ android:background="@color/immersive_cling_bg_color"
android:gravity="center_vertical"
android:paddingBottom="24dp">
@@ -47,7 +47,7 @@
android:paddingTop="8dp"
android:scaleType="center"
android:src="@drawable/ic_expand_more_48dp"
- android:tint="#ff009688"/>
+ android:tint="@color/immersive_cling_bg_color"/>
</FrameLayout>
<TextView
@@ -59,7 +59,7 @@
android:paddingStart="48dp"
android:paddingTop="40dp"
android:text="@string/immersive_cling_title"
- android:textColor="@color/primary_text_default_material_light"
+ android:textColor="@color/immersive_cling_text_color"
android:textSize="24sp" />
<TextView
@@ -71,7 +71,7 @@
android:paddingStart="48dp"
android:paddingTop="12.6dp"
android:text="@string/immersive_cling_description"
- android:textColor="@color/primary_text_default_material_light"
+ android:textColor="@color/immersive_cling_text_color"
android:textSize="16sp" />
<Button
@@ -86,7 +86,7 @@
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:text="@string/immersive_cling_positive"
- android:textColor="@android:color/white"
+ android:textColor="@color/immersive_cling_button_text_color"
android:textSize="14sp" />
</RelativeLayout> \ No newline at end of file
diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml
index 24c2866..729d838 100644
--- a/core/res/res/layout/media_controller.xml
+++ b/core/res/res/layout/media_controller.xml
@@ -17,7 +17,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#CC000000"
+ android:background="@color/media_controller_background_color"
android:orientation="vertical"
android:layoutDirection="ltr">
diff --git a/core/res/res/layout/notification_material_action.xml b/core/res/res/layout/notification_material_action.xml
index da8b2e7..0a4109a 100644
--- a/core/res/res/layout/notification_material_action.xml
+++ b/core/res/res/layout/notification_material_action.xml
@@ -25,7 +25,7 @@
android:gravity="start|center_vertical"
android:drawablePadding="8dp"
android:paddingStart="8dp"
- android:textColor="@color/secondary_text_material_light"
+ android:textColor="@color/notification_mtrl_action_textcolor"
android:textSize="13sp"
android:singleLine="true"
android:ellipsize="end"
diff --git a/core/res/res/layout/notification_material_action_tombstone.xml b/core/res/res/layout/notification_material_action_tombstone.xml
index 976448b..7e53c46 100644
--- a/core/res/res/layout/notification_material_action_tombstone.xml
+++ b/core/res/res/layout/notification_material_action_tombstone.xml
@@ -24,7 +24,7 @@
android:gravity="start|center_vertical"
android:drawablePadding="8dp"
android:paddingStart="8dp"
- android:textColor="#555555"
+ android:textColor="@color/notification_action_tombstone_text_color"
android:textSize="@dimen/notification_text_size"
android:singleLine="true"
android:ellipsize="end"
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index f3768b5..81715a5 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -46,7 +46,7 @@
android:layout_marginTop="208dp"
android:paddingStart="@dimen/notification_large_icon_width"
android:layout_gravity="bottom"
- android:background="#CCEEEEEE"
+ android:background="@color/notification_mtrl_big_picture_bg"
>
<include
layout="@layout/notification_material_action_list"
diff --git a/core/res/res/layout/permission_confirmation_dialog.xml b/core/res/res/layout/permission_confirmation_dialog.xml
new file mode 100644
index 0000000..1727286
--- /dev/null
+++ b/core/res/res/layout/permission_confirmation_dialog.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
+**
+** Copyright 2012 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/parentPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/permission_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip"
+ android:paddingTop="16dip"
+ android:paddingBottom="16dip" />
+
+ <TableLayout android:id="@+id/permission_remember_layout"
+ android:shrinkColumns="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip">
+
+ <TableRow
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+ <RelativeLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="8dip" >
+ <CheckBox android:id="@+id/permission_remember_choice_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </RelativeLayout>
+ <TextView android:id="@+id/permission_remember_choice_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/permission_remember_choice" />
+ </TableRow>
+
+ </TableLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/preference_category_material.xml b/core/res/res/layout/preference_category_material.xml
index 456b252..08f051f 100644
--- a/core/res/res/layout/preference_category_material.xml
+++ b/core/res/res/layout/preference_category_material.xml
@@ -21,7 +21,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="16dip"
android:textAppearance="@style/TextAppearance.Material.Body2"
- android:textColor="?android:attr/colorAccent"
+ android:textColor="@color/preference_category_text_color"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingEnd="?attr/listPreferredItemPaddingEnd"
android:paddingTop="16dip" />
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index 4e895b0..f073c33 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -41,6 +41,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/preference_fragment_padding_side"
+ android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:visibility="gone" />
diff --git a/core/res/res/layout/remote_views_adapter_default_loading_view.xml b/core/res/res/layout/remote_views_adapter_default_loading_view.xml
index 864e435..83ad177 100644
--- a/core/res/res/layout/remote_views_adapter_default_loading_view.xml
+++ b/core/res/res/layout/remote_views_adapter_default_loading_view.xml
@@ -23,9 +23,9 @@
android:gravity="center_horizontal|center_vertical"
android:text="@string/loading"
- android:textColor="#60FFFFFF"
+ android:textColor="@color/loading_view_text_color"
android:textSize="18sp"
- android:shadowColor="#FF000000"
+ android:shadowColor="@color/loading_view_text_shadow_color"
android:shadowDx="0.0"
android:shadowDy="1.0"
android:shadowRadius="1.0" />
diff --git a/core/res/res/layout/resolver_different_item_header.xml b/core/res/res/layout/resolver_different_item_header.xml
index 5889136..1386a70 100644
--- a/core/res/res/layout/resolver_different_item_header.xml
+++ b/core/res/res/layout/resolver_different_item_header.xml
@@ -29,6 +29,5 @@
android:paddingEnd="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
- android:background="@color/white"
- android:elevation="8dp"
+ android:background="@color/resolver_list_bg"
/>
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 00c25e6..f849197 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -30,7 +30,7 @@
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
android:elevation="8dp"
- android:background="@color/white" >
+ android:background="@color/resolver_list_bg" >
<TextView android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -38,6 +38,7 @@
android:minHeight="56dp"
android:textAppearance="?attr/textAppearanceMedium"
android:gravity="start|center_vertical"
+ android:background="@color/resolver_list_bg"
android:paddingStart="?attr/dialogPreferredPadding"
android:paddingEnd="?attr/dialogPreferredPadding"
android:paddingTop="8dp"
@@ -82,7 +83,7 @@
android:id="@+id/resolver_list"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:background="@color/white"
+ android:background="@color/resolver_list_bg"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
android:divider="@null" />
@@ -108,7 +109,7 @@
android:orientation="horizontal"
android:layoutDirection="locale"
android:measureWithLargestChild="true"
- android:background="@color/white"
+ android:background="@color/resolver_list_bg"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingStart="12dp"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 31361e5..f11112f 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -30,13 +30,18 @@
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
android:orientation="vertical"
- android:background="@color/white"
+ android:background="@color/resolver_list_bg"
android:elevation="8dp" >
<LinearLayout
+ android:id="@+id/filtered_item_container"
android:layout_width="match_parent"
android:layout_height="64dp"
- android:orientation="horizontal" >
+ android:orientation="horizontal"
+ android:onClick="onButtonClick"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground"
+ >
<ImageView android:id="@+id/icon"
android:layout_width="24dp"
@@ -52,6 +57,7 @@
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_marginStart="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?attr/textColorPrimary"
android:gravity="start|center_vertical"
android:paddingEnd="16dp" />
<LinearLayout android:id="@+id/profile_button"
@@ -102,8 +108,7 @@
android:paddingBottom="8dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
- android:background="@color/white"
- android:elevation="8dp">
+ android:background="@color/resolver_list_bg">
<Button android:id="@+id/button_once"
android:layout_width="wrap_content"
android:layout_gravity="start"
@@ -136,7 +141,7 @@
android:id="@+id/resolver_list"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:background="@color/white"
+ android:background="@color/resolver_list_bg"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
android:divider="@null"
diff --git a/core/res/res/layout/status_bar_latest_event_content.xml b/core/res/res/layout/status_bar_latest_event_content.xml
index 9444164..0959ecc 100644
--- a/core/res/res/layout/status_bar_latest_event_content.xml
+++ b/core/res/res/layout/status_bar_latest_event_content.xml
@@ -20,7 +20,7 @@
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#FFFF00FF"
+ android:background="@color/status_bar_latest_event_content_bg_color"
>
<include layout="@layout/notification_template_material_base"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/text_edit_action_popup_text.xml b/core/res/res/layout/text_edit_action_popup_text.xml
index 16bf30e..12a8921 100644
--- a/core/res/res/layout/text_edit_action_popup_text.xml
+++ b/core/res/res/layout/text_edit_action_popup_text.xml
@@ -23,7 +23,7 @@
android:paddingBottom="8dip"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceSmallInverse"
- android:textColor="@android:color/black"
+ android:textColor="@color/edit_action_popup_text_color"
android:textAllCaps="true"
android:textStyle="bold"
/>
diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml
index 3b8dbf2..c032c34 100644
--- a/core/res/res/layout/text_edit_paste_window.xml
+++ b/core/res/res/layout/text_edit_paste_window.xml
@@ -28,7 +28,7 @@
android:drawablePadding="8dip"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
- android:textColor="@android:color/black"
+ android:textColor="@color/edit_paste_window_text_color"
android:background="@android:drawable/text_edit_paste_window"
android:text="@android:string/paste"
android:layout_marginBottom="12dip"
diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml
index c947a19..c154813 100644
--- a/core/res/res/layout/text_edit_side_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_paste_window.xml
@@ -28,7 +28,7 @@
android:drawablePadding="8dip"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
- android:textColor="@android:color/black"
+ android:textColor="@color/edit_side_paste_window_text_color"
android:background="@android:drawable/text_edit_side_paste_window"
android:text="@android:string/paste"
android:layout_marginBottom="12dip"
diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml
index daa9faf..5f9c1e8 100644
--- a/core/res/res/layout/transient_notification.xml
+++ b/core/res/res/layout/transient_notification.xml
@@ -18,24 +18,35 @@
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:background="?android:attr/toastFrameBackground">
+ android:clipChildren="false">
<TextView
android:id="@android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
android:layout_gravity="center_horizontal"
+ android:layout_marginTop="-16dp"
+ android:layout_marginStart="-16dp"
+ android:layout_toEndOf="@android:id/icon"
+ android:layout_below="@android:id/icon"
android:textAppearance="@style/TextAppearance.Toast"
android:textColor="@color/bright_foreground_dark"
android:shadowColor="#BB000000"
android:shadowRadius="2.75"
+ android:background="?android:attr/toastFrameBackground"
/>
-</LinearLayout>
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"/>
+
+</RelativeLayout>
diff --git a/core/res/res/layout/typing_filter.xml b/core/res/res/layout/typing_filter.xml
index d8d0a40..74a016a 100644
--- a/core/res/res/layout/typing_filter.xml
+++ b/core/res/res/layout/typing_filter.xml
@@ -16,8 +16,8 @@
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:textSize="36dp"
- android:textColor="#99FFFFFF"
- android:background="#BB000000"
+ android:textColor="@color/typing_filter_text_color"
+ android:background="@color/typing_filter_background_color"
android:minWidth="240dip"
android:maxWidth="240dip"
android:padding="10dip"
diff --git a/core/res/res/layout/web_text_view_dropdown.xml b/core/res/res/layout/web_text_view_dropdown.xml
index 1a6e9eb..fe09389 100644
--- a/core/res/res/layout/web_text_view_dropdown.xml
+++ b/core/res/res/layout/web_text_view_dropdown.xml
@@ -19,8 +19,8 @@ limitations under the License.
android:id="@android:id/text1"
style="?android:attr/dropDownItemStyle"
android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
- android:textColor="#ff000000"
- android:background="#ffffffff"
+ android:textColor="@color/web_view_dropdown_text_color"
+ android:background="@color/web_view_dropdown_background_color"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/values-af/cm_strings.xml b/core/res/res/values-af/cm_strings.xml
new file mode 100644
index 0000000..bd245b3
--- /dev/null
+++ b/core/res/res/values-af/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Skermfoto</string>
+ <string name="permlab_receiveProtectedSms">ontvang beskermde SMS</string>
+ <string name="permdesc_receiveProtectedSms">Laat die program toe om \'n beskermde inkomende SMS te ontvang.</string>
+ <string name="permlab_modifyProtectedSmsList">verander beskermde SMS lys</string>
+ <string name="permdesc_modifyProtectedSmsList">Laat die program toe om die beskermde SMS adres lys te verander.</string>
+ <string name="permgrouplab_security">Sekuriteit</string>
+ <string name="permgroupdesc_security">Regte met betrekking tot toestel sekuriteitsinligting.</string>
+ <string name="permlab_readPhoneBlacklist">lees foon swartlys</string>
+ <string name="permdesc_readPhoneBlacklist">Laat \'n program toe om inligting oor telefoonnommers wat geblokkeer is van inkomende oproepe of boodskappe te lees.</string>
+ <string name="permlab_changePhoneBlacklist">Verander selfoon swartlys</string>
+ <string name="permdesc_changePhoneBlacklist">Laat \'n program toe om van die telefoonnommers wat geblokkeer is vir inkomende oproepe of boodskappe te verander.</string>
+ <string name="permlab_setKeyguardWallpaper">Stel slotskerm agtergrond in</string>
+ <string name="permdesc_setKeyguardWallpaper">Laat \'n program toe om die slotskerm agtergrond te verander.</string>
+ <string name="global_action_reboot">Herlaai</string>
+ <string name="global_action_current_user">Huidige</string>
+ <string name="reboot_reboot">Herlaai</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Vinnige herlaai</string>
+ <string name="reboot_title">Herlaai</string>
+ <string name="reboot_confirm" product="tablet">Jou tablet gaan herlaai.</string>
+ <string name="reboot_confirm" product="default">Jou foon gaan herlaai.</string>
+ <string name="reboot_progress">Herlaai\u2026</string>
+ <string name="app_killed_message">Program beëindig</string>
+ <string name="adb_net_active_notification_title">ADB oor netwerk is aktief</string>
+ <string name="adb_both_active_notification_title">ADB oor USB &amp; netwerk is aktief</string>
+ <string name="adb_active_generic_notification_message">Raak om ontfouting af te skakel.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; netwerk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Netwerk</string>
+ <string name="permlab_interceptPackageLaunch">onderskep program begin</string>
+ <string name="stylus_app_not_installed">%s is nie geïnstalleer nie</string>
+ <string name="silent_mode_priority">Prioriteit</string>
+ <string name="silent_mode_none">Geen</string>
+ <string name="subscription_change_disabled_wifi_ap">Deaktiveer Wi-Fi warmkol weens SIM inskrywing verandering</string>
+ <string name="notify_turn_wifi_off_title">Skakel Wi-Fi af</string>
+ <string name="permlab_changePrivacyGuardState">aktiveer of deaktiveer Privaatheidswag</string>
+ <string name="permdesc_changePrivacyGuardState">Laat \'n program toe om te bepaal of \'n ander program met of sonder Privaatheidswag kan loop. Wanneer Privaatheidswag geaktiveer is kan die program nie toegang kry tot persoonlike data soos kontakte, boodskappe en oproep geskiedenis nie.</string>
+ <string name="privacy_guard_notification">Privaatheidswag aktief</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> het nie toegang tot persoonlike data nie</string>
+ <string name="privacy_guard_dialog_title">Privaatheidswag</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> wil <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Onthou my keuse</string>
+ <string name="app_ops_access_camera">toegang tot die kamera</string>
+ <string name="app_ops_access_location">toegang tot jou ligging</string>
+ <string name="app_ops_access_notifications">lees jou kennisgewing boodskappe</string>
+ <string name="app_ops_activate_vpn">Aktiveer \'n VPN</string>
+ <string name="app_ops_auto_start">begin by aanskakeling</string>
+ <string name="app_ops_delete_call_log">verwyder jou oproep rekord data</string>
+ <string name="app_ops_delete_contacts">verwyder jou kontakte</string>
+ <string name="app_ops_delete_mms">verwyder jou MMS boodskappe</string>
+ <string name="app_ops_delete_sms">verwyder jou SMS boodskappe</string>
+ <string name="app_ops_draw_on_top">teken bo</string>
+ <string name="app_ops_get_usage_stats">kry program gebruik stats</string>
+ <string name="app_ops_keep_device_awake">hou jou toestel geaktiveerd</string>
+ <string name="app_ops_make_phone_call">maak \'n oproep</string>
+ <string name="app_ops_modify_calendar">opdateer jou kalender</string>
+ <string name="app_ops_modify_call_log">opdateer die oproep lys</string>
+ <string name="app_ops_modify_clipboard">verander die knipbord</string>
+ <string name="app_ops_modify_contacts">opdateer jou kontakte</string>
+ <string name="app_ops_modify_settings">opdateer stelsel instellings</string>
+ <string name="app_ops_mute_unmute_microphone">demp / ontdemp die mikrofoon</string>
+ <string name="app_ops_play_audio">speel oudio</string>
+ <string name="app_ops_post_notification">plaas \'n kennisgewing</string>
+ <string name="app_ops_project_media">projek media</string>
+ <string name="app_ops_read_calendar">lees jou kalender</string>
+ <string name="app_ops_read_call_log">lees jou oproep lys</string>
+ <string name="app_ops_read_clipboard">lees die knipbord</string>
+ <string name="app_ops_read_contacts">lees jou kantakte</string>
+ <string name="app_ops_read_mms">lees jou MMS boodskappe</string>
+ <string name="app_ops_read_sms">lees jou SMS boodskappe</string>
+ <string name="app_ops_receive_sms">ontvang \'n SMS boodskap</string>
+ <string name="app_ops_record_audio">klank opneem</string>
+ <string name="app_ops_send_mms">stuur \'n MMS boodskap</string>
+ <string name="app_ops_send_sms">stuur \'n SMS boodskap</string>
+ <string name="app_ops_start_at_bootup">begin by aanskakeling</string>
+ <string name="app_ops_toast_window">vertoon uitspring boodskappe</string>
+ <string name="app_ops_toggle_bluetooth">wissel Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">skakel sellulêre data aan/af</string>
+ <string name="app_ops_toggle_nfc">wissel NFC</string>
+ <string name="app_ops_toggle_wifi">wissel Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">beheer alarmstelsel volume</string>
+ <string name="app_ops_use_audio_focus">beheer klank fokus</string>
+ <string name="app_ops_use_bluetooth_volume">beheer Bluetooth volume</string>
+ <string name="app_ops_use_master_volume">beheer meester volume</string>
+ <string name="app_ops_use_media_buttons">gebruik die media knoppies</string>
+ <string name="app_ops_use_media_volume">beheer media volume</string>
+ <string name="app_ops_use_notification_volume">beheer kennisgewing volume</string>
+ <string name="app_ops_use_ring_volume">beheer luitoon volume</string>
+ <string name="app_ops_use_vibrate">gebruik haptiese terugvoer</string>
+ <string name="app_ops_use_voice_volume">beheer stem oproep volume</string>
+ <string name="app_ops_write_mms">skryf \'n MMS boodskap</string>
+ <string name="app_ops_write_sms">Skryf \'n SMS boodskap</string>
+ <string name="app_ops_use_fingerprint">gebruik vingerfdruk</string>
+ <string name="app_ops_add_voicemail">voeg \'n stem boodskap by</string>
+ <string name="app_ops_read_phone_state">kry toegang na foon toestand</string>
+ <string name="app_ops_scan_wifi">skandeer Wi-Fi netwerke</string>
+ <string name="app_ops_change_wallpaper">verander die agtergrond</string>
+ <string name="app_ops_assist_structure">gebruik assistent struktuur</string>
+ <string name="app_ops_assist_screenshot">neem \'n skermfoto</string>
+ <string name="app_ops_use_body_sensors">gebruik liggaam sensors</string>
+ <string name="app_ops_read_cell_broadcasts">lees sel uitsendings</string>
+ <string name="app_ops_mock_location">simuleer jou plek</string>
+ <string name="app_ops_read_external_storage">lees eksterne spasie</string>
+ <string name="app_ops_write_external_storage">skryf eksterne spasie</string>
+ <string name="app_ops_turn_on_screen">skakel skerm aan</string>
+ <string name="app_ops_get_accounts">kry toestel rekeninge</string>
+ <string name="app_ops_wifi_change">verander Wi-Fi status</string>
+ <string name="app_ops_su">kry root toegang</string>
+ <string name="lock_to_app_toast_no_navbar">Om die skerm te ontspeld, raak en hou die Terug knoppie.</string>
+ <string name="live_display_auto">Outomaties</string>
+ <string name="live_display_auto_summary">Kleurtemperatuur van die skerm sal outomaties aanpas na sononder en sonop</string>
+ <string name="live_display_off">Af</string>
+ <string name="live_display_off_summary">Skakel al die aanpassings af</string>
+ <string name="live_display_day">Dag</string>
+ <string name="live_display_day_summary">Alleenlik gebruik dag instellings</string>
+ <string name="live_display_night">Nag</string>
+ <string name="live_display_night_summary">Alleenlik gebruik nag instellings</string>
+ <string name="live_display_outdoor">Buitekant (helder son)</string>
+ <string name="live_display_outdoor_summary">Alleenlik gebruik buite instellings</string>
+ <string name="live_display_hint">LewendigeVertoning kan jou oogspanning verminder en help jou slaap in die nag. Klik hier om dit uit te probeer!</string>
+ <string name="tethered_notification_no_device_message">Geen gekoppelde toestel</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> gekoppelde toestel</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> gekoppelde toestelle</string>
+ <string name="notify_package_component_protected_title">Aktiwiteit begin geblokkeer</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> is beskerm om uitgevoer te word. Raak om toestemming te gee en die toepassing te begin.</string>
+ <string name="notify_battery_fully_charged_title">Battery vol gelaai</string>
+ <string name="notify_battery_fully_charged_text">Diskonnekteer jou toestel van die laaier om die battery lewe te verleng.</string>
+</resources>
diff --git a/core/res/res/values-ar/cm_strings.xml b/core/res/res/values-ar/cm_strings.xml
new file mode 100644
index 0000000..8d7187d
--- /dev/null
+++ b/core/res/res/values-ar/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">لقطة شاشة</string>
+ <string name="permlab_receiveProtectedSms">استلام رسالة نصية قصيرة محمية</string>
+ <string name="permdesc_receiveProtectedSms">يسمح للتطبيق باستلام رسالة نصية قصيرة محمية واردة.</string>
+ <string name="permlab_modifyProtectedSmsList">تعديل قائمة الرسائل النصية القصيرة المحمية</string>
+ <string name="permdesc_modifyProtectedSmsList">السماح للتطبيق بتعديل قائمة عناوين الرسائل النصية القصيرة المحمية.</string>
+ <string name="permgrouplab_security">الأمان</string>
+ <string name="permgroupdesc_security">أذونات متعلقة بمعلومات حماية الجهاز.</string>
+ <string name="permlab_readPhoneBlacklist">قراءة القائمة السوداء للهاتف</string>
+ <string name="permdesc_readPhoneBlacklist">السماح للتطبيق بقراءة المعلومات الخاصة بأرقام الهاتف المحظورة بالنبسة للمكالمات أو الرسائل الواردة.</string>
+ <string name="permlab_changePhoneBlacklist">تغيير القائمة السوداء للهاتف</string>
+ <string name="permdesc_changePhoneBlacklist">السماح للتطبيق بتغيير أرقام الهاتف التي يتم حظر للمكالمات الواردة أو الرسائل.</string>
+ <string name="permlab_setKeyguardWallpaper">تعيين خلفية شاشة الحارس الرئيسي</string>
+ <string name="permdesc_setKeyguardWallpaper">السماج للتطبيق بتغيير خلفية شاشة التأمين.</string>
+ <string name="global_action_reboot">إعادة تمهيد</string>
+ <string name="global_action_current_user">الحالي</string>
+ <string name="reboot_reboot">إعادة التمهيد</string>
+ <string name="reboot_recovery">استرداد</string>
+ <string name="reboot_bootloader">محمل التمهيد</string>
+ <string name="reboot_download">التنزيل</string>
+ <string name="reboot_soft">إعادة تمهيد سريعة</string>
+ <string name="reboot_title">إعادة التمهيد</string>
+ <string name="reboot_confirm" product="tablet">ستتم إعادة تمهيد جهازك اللوحي.</string>
+ <string name="reboot_confirm" product="default">ستتم إعادة تمهيد هاتفك.</string>
+ <string name="reboot_progress">إعادة التمهيد\u2026</string>
+ <string name="app_killed_message">تم إنهاء التطبيق</string>
+ <string name="adb_net_active_notification_title">تمكين ADB عبر الشبكة</string>
+ <string name="adb_both_active_notification_title">ADB عبر USB &amp; تمكين الشبكة</string>
+ <string name="adb_active_generic_notification_message">انقر لتعطيل تصحيح الأخطاء.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; الشبكة</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">الشبكة</string>
+ <string name="permlab_interceptPackageLaunch">مقاطعة تشغيل التطبيق</string>
+ <string name="stylus_app_not_installed">%s لم يتم تثبيته</string>
+ <string name="silent_mode_priority">الأولوية</string>
+ <string name="silent_mode_none">بلا</string>
+ <string name="subscription_change_disabled_wifi_ap">ايقاف بث تقنية واي فاي بسبب تغيير اشتراك SIM</string>
+ <string name="notify_turn_wifi_off_title">إيقاف Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">تمكين أو تعطيل حارس الخصوصية</string>
+ <string name="permdesc_changePrivacyGuardState">يسمح للتطبيق بتغيير ما إذا كان تطبيق آخر يعمل مع \"حارس الخصوصية\". عندما يتم تشغيل تطبيق مع \"حارس الخصوصية\"، فلن يُسمح بالوصول إلى البيانات الشخصية كجهات الاتصال أو سجلات المكالمات أو الرسائل.</string>
+ <string name="privacy_guard_notification">حارس الخصوصية نشط</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> لن تكون قادراً على الوصول إلى البيانات الشخصية</string>
+ <string name="privacy_guard_dialog_title">حارس الخصوصية</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> يرغب في <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">تذكر خياري</string>
+ <string name="app_ops_access_camera">الوصول إلى الكاميرا</string>
+ <string name="app_ops_access_location">الوصول إلى موقعك</string>
+ <string name="app_ops_access_notifications">قراءة إشعاراتك</string>
+ <string name="app_ops_activate_vpn">تفعيل شبكة افتراضية خاصة (VPN)</string>
+ <string name="app_ops_auto_start">البدء عند تشغيل الجهاز</string>
+ <string name="app_ops_delete_call_log">حذف سجل مكالماتك</string>
+ <string name="app_ops_delete_contacts">حذف جهات الاتصال الخاصة بك</string>
+ <string name="app_ops_delete_mms">حذف رسائل MMS</string>
+ <string name="app_ops_delete_sms">حذف الرسائل النصية القصيرة (SMS)</string>
+ <string name="app_ops_draw_on_top">رسم نوافذ فوق الجزء العلوي</string>
+ <string name="app_ops_get_usage_stats">الحصول على إحصائيات باستخدام التطبيقات</string>
+ <string name="app_ops_keep_device_awake">إبقاء الجهاز في حالة تنبيه</string>
+ <string name="app_ops_make_phone_call">إجراء اتصال هاتفي</string>
+ <string name="app_ops_modify_calendar">تحديث تقويمك</string>
+ <string name="app_ops_modify_call_log">تحديث سجل المكالمات</string>
+ <string name="app_ops_modify_clipboard">تعديل الحافظة</string>
+ <string name="app_ops_modify_contacts">تحديث جهات الاتصال الخاصة بك</string>
+ <string name="app_ops_modify_settings">تحديث إعدادات النظام</string>
+ <string name="app_ops_mute_unmute_microphone">كتم/إلغاء كتم الميكروفون</string>
+ <string name="app_ops_play_audio">تشغيل الصوت</string>
+ <string name="app_ops_post_notification">آخر إشعار</string>
+ <string name="app_ops_project_media">وسائط المشروع</string>
+ <string name="app_ops_read_calendar">قراءة التقويم الخاص بك</string>
+ <string name="app_ops_read_call_log">قراءة سجل المكالمات</string>
+ <string name="app_ops_read_clipboard">قراءة الحافظة</string>
+ <string name="app_ops_read_contacts">قراءة جهات الاتصال الخاصة بك</string>
+ <string name="app_ops_read_mms">قراءة رسائل MMS الخاصة بك</string>
+ <string name="app_ops_read_sms">قراءة الرسائل النصية القصيرة الخاصة بك</string>
+ <string name="app_ops_receive_sms">استلام رسالة نصية قصيرة</string>
+ <string name="app_ops_record_audio">تسجيل الصوت</string>
+ <string name="app_ops_send_mms">إرسال رسالة نصية قصيرة</string>
+ <string name="app_ops_send_sms">إرسال رسالة نصية قصيرة</string>
+ <string name="app_ops_start_at_bootup">البدء في التشغيل</string>
+ <string name="app_ops_toast_window">عرض الإعلامات المنبثقة</string>
+ <string name="app_ops_toggle_bluetooth">تبديل بلوتوث</string>
+ <string name="app_ops_toggle_nfc">تبديل NFC</string>
+ <string name="app_ops_use_alarm_volume">التحكم في مستوى صوت الإنذار</string>
+ <string name="app_ops_use_audio_focus">التحكم في تركيز الصوت</string>
+ <string name="app_ops_use_bluetooth_volume">التحكم في مستوى صوت بلوتوث</string>
+ <string name="app_ops_use_master_volume">التحكم في مستوى الصوت الرئيسي</string>
+ <string name="app_ops_use_media_buttons">استخدم أزرار الوسائط</string>
+ <string name="app_ops_use_media_volume">التحكم في مستوى صوت الوسائط</string>
+ <string name="app_ops_use_notification_volume">التحكم في مستوى صوت الإشعار</string>
+ <string name="app_ops_use_ring_volume">التحكم في مستوى صوت نغمة الرنين</string>
+ <string name="app_ops_use_vibrate">إستخدام نتائج اللمس</string>
+ <string name="app_ops_use_voice_volume">التحكم في مستوى صوت المكالمة الصوتية</string>
+ <string name="app_ops_write_mms">كتابة رسالة MMS</string>
+ <string name="app_ops_write_sms">كتابة رسالة نصية قصيرة</string>
+ <string name="app_ops_su">الحصول على صلاحيات الجذر</string>
+ <string name="lock_to_app_toast_no_navbar">لإلغاء تثبيت هذه الشاشة، المس واستمر في ضغط زر الرجوع.</string>
+ <string name="live_display_auto">تلقائي</string>
+ <string name="live_display_auto_summary">ضبط درجة حرارة لون للشاشة تلقائياً بعد غروب الشمس وشروق الشمس</string>
+ <string name="live_display_off">إيقاف</string>
+ <string name="live_display_off_summary">تعطيل جميع التعديلات</string>
+ <string name="live_display_day">النهار</string>
+ <string name="live_display_day_summary">استخدام إعدادات النهار فقط</string>
+ <string name="live_display_night">الليل</string>
+ <string name="live_display_night_summary">استخدام إعدادات الليل فقط</string>
+ <string name="live_display_outdoor">خارج المنزل ( شمس ساطعة)</string>
+ <string name="live_display_outdoor_summary">استخدم إعدادات خارج المنزل فقط</string>
+ <string name="live_display_hint">ميزة LiveDisplay يمكن أن تساعد في تقليل إجهاد العين والمساعدة على النوم في الليل. انقر هنا لتجربته!</string>
+ <string name="tethered_notification_no_device_message">لا يوجد جهاز متصل</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> جهاز متصل</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> أجهزة متصلة</string>
+</resources>
diff --git a/core/res/res/values-ast-rES/cm_strings.xml b/core/res/res/values-ast-rES/cm_strings.xml
new file mode 100644
index 0000000..d254bbf
--- /dev/null
+++ b/core/res/res/values-ast-rES/cm_strings.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Capturar pantalla</string>
+ <string name="permlab_receiveProtectedSms">recibir SMS protexíos</string>
+ <string name="permdesc_receiveProtectedSms">Permite que l\'aplicación reciba mensaxes SMS entrantes protexíos.</string>
+ <string name="permlab_modifyProtectedSmsList">modificar llista de SMS protexíos</string>
+ <string name="permdesc_modifyProtectedSmsList">Permite que l\'aplicación modifique la llista de direiciones de mensaxes SMS protexíos.</string>
+ <string name="permgrouplab_security">Seguridá</string>
+ <string name="permgroupdesc_security">Permisos rellacionaos a la seguridá de la información del preséu.</string>
+ <string name="permlab_readPhoneBlacklist">Lleer llista prieta del teléfonu</string>
+ <string name="permdesc_readPhoneBlacklist">Permite a una aplicación lleer información sobre los númberos telefónicos bloquiaos pa llamaes o mensaxes entrantes.</string>
+ <string name="permlab_changePhoneBlacklist">camudar la llista prieta del teléfonu</string>
+ <string name="permdesc_changePhoneBlacklist">Permite qu\'una aplicación camude los númberos telefónicos bloquiaos pa llamaes o mensaxes entrantes.</string>
+ <string name="permlab_setKeyguardWallpaper">Afita\'l fondu de pantalla de bloquéu</string>
+ <string name="permdesc_setKeyguardWallpaper">Permite que l\'aplicación afite\'l fondu de la pantalla de bloquéu.</string>
+ <string name="global_action_reboot">Reaniciar</string>
+ <string name="global_action_current_user">Actual</string>
+ <string name="reboot_reboot">Reaniciar</string>
+ <string name="reboot_recovery">Mou Recovery</string>
+ <string name="reboot_bootloader">Mou Bootloader</string>
+ <string name="reboot_download">Descargar</string>
+ <string name="reboot_soft">Reaniciu suave</string>
+ <string name="reboot_title">Reaniciar</string>
+ <string name="reboot_confirm" product="tablet">La tablet va reaniciase.</string>
+ <string name="reboot_confirm" product="default">El teléfonu va reaniciase.</string>
+ <string name="reboot_progress">Reaniciando\u2026</string>
+ <string name="app_killed_message">Aplicación finada</string>
+ <string name="adb_net_active_notification_title">ADB sobre rede habilitáu</string>
+ <string name="adb_both_active_notification_title">ADB sobre USB y rede habilitáu</string>
+ <string name="adb_active_generic_notification_message">Toca pa deshabilitar la depuración.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB y rede</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Rede</string>
+ <string name="permlab_interceptPackageLaunch">interceutar la execución d\'aplicaciones</string>
+ <string name="stylus_app_not_installed">%s nun ta instalada</string>
+ <string name="silent_mode_priority">Prioridá</string>
+ <string name="silent_mode_none">Dengún</string>
+ <string name="subscription_change_disabled_wifi_ap">Deshabilitóse\'l puntu Wi-Fi pola mor del cambéu de la soscripción de la SIM</string>
+ <string name="notify_turn_wifi_off_title">Apagar Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">habilitar o deshabilitar la privacidá</string>
+ <string name="permdesc_changePrivacyGuardState">Permite que l\'aplicación cambie l\'estáu de privacidá d\'otra. Cuando una aplicación s\'executa cola privacidá habilitada, nun va poder acceder a los datos personales, talos como contautos, mensaxes o rexistros de llamaes.</string>
+ <string name="privacy_guard_notification">Privacidá activada</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> nun va poder acceder a los datos personales</string>
+ <string name="privacy_guard_dialog_title">Privacidá</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> quies <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Recordar la mio escoyeta</string>
+ <string name="app_ops_access_camera">acceder a la cámara</string>
+ <string name="app_ops_access_location">acceder a la to llocalización</string>
+ <string name="app_ops_access_notifications">lleer les tos notificaciones</string>
+ <string name="app_ops_activate_vpn">activar una VPN</string>
+ <string name="app_ops_auto_start">executase al aniciu</string>
+ <string name="app_ops_delete_call_log">desaniciar rexistru de llamaes</string>
+ <string name="app_ops_delete_contacts">desaniciar contautos</string>
+ <string name="app_ops_delete_mms">desaniciar los tos MMS</string>
+ <string name="app_ops_delete_sms">desaniciar los tos SMS</string>
+ <string name="app_ops_draw_on_top">dibuxar ventanes na parte superior</string>
+ <string name="app_ops_get_usage_stats">obtener estadístiques d\'usu de l\'app</string>
+ <string name="app_ops_keep_device_awake">caltener encesu\'l preséu</string>
+ <string name="app_ops_make_phone_call">facer una llamada</string>
+ <string name="app_ops_modify_calendar">anovar el to calendariu</string>
+ <string name="app_ops_modify_call_log">anovar el rexistru de llamaes</string>
+ <string name="app_ops_modify_clipboard">modificar el cartafueyu</string>
+ <string name="app_ops_modify_contacts">anovar los tos contautos</string>
+ <string name="app_ops_modify_settings">anovar los axustes del sistema</string>
+ <string name="app_ops_mute_unmute_microphone">activar/silenciar micrófonu</string>
+ <string name="app_ops_play_audio">reproducir soníu</string>
+ <string name="app_ops_post_notification">espublizar una notificación</string>
+ <string name="app_ops_project_media">Proyeutu Media</string>
+ <string name="app_ops_read_calendar">lleer el to calendariu</string>
+ <string name="app_ops_read_call_log">lleer el rexistru de llamaes</string>
+ <string name="app_ops_read_clipboard">lleer el cartafueyu</string>
+ <string name="app_ops_read_contacts">lleer los tos contautos</string>
+ <string name="app_ops_read_mms">lleer los tos mensaxes MMS</string>
+ <string name="app_ops_read_sms">lleer los tos mensaxes SMS</string>
+ <string name="app_ops_receive_sms">recibir un mensaxe SMS</string>
+ <string name="app_ops_record_audio">grabar soníu</string>
+ <string name="app_ops_send_mms">unviar un mensaxe MMS</string>
+ <string name="app_ops_send_sms">unviar un mensaxe SMS</string>
+ <string name="app_ops_start_at_bootup">executase al aniciu</string>
+ <string name="app_ops_toast_window">notificaciones emerxentes</string>
+ <string name="app_ops_toggle_bluetooth">cambiar Bluetooth</string>
+ <string name="app_ops_toggle_nfc">cambiar NFC</string>
+ <string name="app_ops_use_alarm_volume">remanar volume de l\'alarma</string>
+ <string name="app_ops_use_audio_focus">remanar el volume de soníu</string>
+ <string name="app_ops_use_bluetooth_volume">remanar el volume del Bluetooth</string>
+ <string name="app_ops_use_master_volume">remanar el volume principal</string>
+ <string name="app_ops_use_media_buttons">usar los botones multimedia</string>
+ <string name="app_ops_use_media_volume">remanar el volume multimedia</string>
+ <string name="app_ops_use_notification_volume">remanar el volume de notificaciones</string>
+ <string name="app_ops_use_ring_volume">remanar el volume de llamada</string>
+ <string name="app_ops_use_vibrate">usar rempuesta háptica</string>
+ <string name="app_ops_use_voice_volume">remanar el volume de la llamada</string>
+ <string name="app_ops_write_mms">escribir un mensaxe MMS</string>
+ <string name="app_ops_write_sms">escribir un mensaxe SMS</string>
+ <string name="app_ops_su">obtener accesu root</string>
+ <string name="live_display_auto">Automáticu</string>
+ <string name="live_display_auto_summary">Axustar automáticamente la temperatura del color de pantalla col alborecer y l\'atapecer</string>
+ <string name="live_display_off">Desactiváu</string>
+ <string name="live_display_off_summary">Deshabilitar tolos axustes</string>
+ <string name="live_display_day">Día</string>
+ <string name="live_display_day_summary">Usar namái los axustes de día</string>
+ <string name="live_display_night">Nueche</string>
+ <string name="live_display_night_summary">Usar namái los axustes de nueche</string>
+ <string name="live_display_outdoor">Esterior (lluz del sol)</string>
+ <string name="live_display_outdoor_summary">Usar namái axustes del esterior</string>
+ <string name="live_display_hint">LiveDisplay pue amenorgar reducir la fatiga visual y ayudar a dormir pela nueche. ¡Toca equí pa probalu!</string>
+ <string name="tethered_notification_no_device_message">Nun hai dengún preséu coneutáu</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> preséu coneutáu</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> preseos coneutaos</string>
+</resources>
diff --git a/core/res/res/values-ast-rES/donottranslate-maps.xml b/core/res/res/values-ast-rES/donottranslate-maps.xml
new file mode 100644
index 0000000..2e49ced
--- /dev/null
+++ b/core/res/res/values-ast-rES/donottranslate-maps.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 The CyanogenMod 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.
+-->
+<resources>
+ <!-- Stub for Asturian -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>40413496</item>
+ <item>-3713379</item>
+ </integer-array>
+ <integer-array name="maps_starting_zoom">
+ <item>6</item>
+ </integer-array>
+</resources>
diff --git a/core/res/res/values-ast-rES/strings.xml b/core/res/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..929fb6e
--- /dev/null
+++ b/core/res/res/values-ast-rES/strings.xml
@@ -0,0 +1,1261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="byteShort">B</string>
+ <string name="kilobyteShort">KB</string>
+ <string name="megabyteShort">MB</string>
+ <string name="gigabyteShort">GB</string>
+ <string name="terabyteShort">TB</string>
+ <string name="petabyteShort">PB</string>
+ <string name="durationDays"><xliff:g id="days">%1$d</xliff:g> díes</string>
+ <string name="durationDayHours"><xliff:g id="days">%1$d</xliff:g> día
+ <xliff:g id="hours">%2$d</xliff:g> hrs</string>
+ <string name="durationDayHour"><xliff:g id="days">%1$d</xliff:g> día
+ <xliff:g id="hours">%2$d</xliff:g> hrs</string>
+ <string name="durationHours"><xliff:g id="hours">%1$d</xliff:g> hrs</string>
+ <string name="durationHourMinutes"><xliff:g id="hours">%1$d</xliff:g> hr
+ <xliff:g id="minutes">%2$d</xliff:g> mins</string>
+ <string name="durationHourMinute"><xliff:g id="hours">%1$d</xliff:g> hr
+ <xliff:g id="minutes">%2$d</xliff:g> mins</string>
+ <string name="durationMinutes"><xliff:g id="minutes">%1$d</xliff:g> mins</string>
+ <string name="durationMinuteSeconds"><xliff:g id="minutes">%1$d</xliff:g> min
+ <xliff:g id="seconds">%2$d</xliff:g> segs</string>
+ <string name="durationMinuteSecond"><xliff:g id="minutes">%1$d</xliff:g> min
+ <xliff:g id="seconds">%2$d</xliff:g> segs</string>
+ <string name="durationSeconds"><xliff:g id="seconds">%1$d</xliff:g> segs</string>
+ <string name="durationSecond"><xliff:g id="seconds">%1$d</xliff:g> seg</string>
+ <string name="untitled">&lt;Ensin títulu&gt;</string>
+ <string name="emptyPhoneNumber">(Ensin númberu de teléfonu)</string>
+ <string name="defaultVoiceMailAlphaTag">Buzón de voz</string>
+ <string name="defaultMsisdnAlphaTag">MSISDN1</string>
+ <string name="mmiError">Hebo un fallu de conexón o\'l códigu MMI nun ye válidu.</string>
+ <string name="mmiFdnError">La operación namái ye válida pa númberos de marcación fixa.</string>
+ <string name="serviceEnabled">El serviciu habilitóse.</string>
+ <string name="serviceEnabledFor">Habilitóse\'l serviciu pa:</string>
+ <string name="serviceDisabled">El serviciu inhabilitóse.</string>
+ <string name="serviceRegistered">El rexistru féxose correutamente.</string>
+ <string name="serviceErased">L\'elementu desanicióse correutamente.</string>
+ <string name="passwordIncorrect">Contraseña incorreuta</string>
+ <string name="mmiComplete">MMI completu</string>
+ <string name="badPin">El códigu PIN antiguu qu\'introduxisti ye correutu.</string>
+ <string name="badPuk">El códigu PUK qu\'introduxisti nun ye correutu.</string>
+ <string name="mismatchPin">Los códigos PIN inxertaos nun concasen.</string>
+ <string name="invalidPin">Introduz un códigu PIN con una llonxitú ente cuatro y ocho díxitos.</string>
+ <string name="invalidPuk">Escribi un códigu PUK d\'ocho caráuteres o más.</string>
+ <string name="needPuk">La tarxeta SIM ta bloquiada col códigu PUK. Introduz el códigu PUK pa desbloquiala.</string>
+ <string name="needPuk2">Introduz el códigu PUK2 pa desbloquiar la tarxeta SIM.</string>
+ <string name="enablePin">Error, habilitar bloquéu de SIM/RUIM.</string>
+ <string name="imei">IMEI</string>
+ <string name="meid">MEID</string>
+ <string name="ClipMmi">ID d\'emisor de llamada entrante</string>
+ <string name="ClirMmi">ID d\'emisor de llamada saliente</string>
+ <string name="ColpMmi">ID de llinia coneutada</string>
+ <string name="ColrMmi">Restricción de ID de llinia coneutada</string>
+ <string name="CfMmi">Esvíu de llamada</string>
+ <string name="CwMmi">Llamada n\'espera</string>
+ <string name="BaMmi">Bloquéu de llamada</string>
+ <string name="PwdMmi">Cambéu de contraseña</string>
+ <string name="PinMmi">Cambéu de PIN</string>
+ <string name="CnipMmi">Númberu de llamada entrante presente</string>
+ <string name="CnirMmi">Númberu de llamada entrante restrinxíu</string>
+ <string name="ThreeWCMmi">Llamada a trés</string>
+ <string name="RuacMmi">Refugu de llamaes molestes non deseaes</string>
+ <string name="CndMmi">Entrega de númberu de llamada entrante</string>
+ <string name="DndMmi">Nun molestar</string>
+ <string name="CLIRDefaultOnNextCallOn">El ID d\'emisor presenta\'l valor predetermináu de restrinxíu. Siguiente llamada: Restrinxíu</string>
+ <string name="CLIRDefaultOnNextCallOff">El ID d\'emisor presenta\'l valor predetermináu de restrinxíu. Siguiente llamada: Non restrinxíu</string>
+ <string name="CLIRDefaultOffNextCallOn">El ID d\'emisor presenta\'l valor predetermináu de no restrinxíu. Siguiente llamada: Restrinxíu</string>
+ <string name="CLIRDefaultOffNextCallOff">El ID d\'emisor presenta\'l valor predetermináu de no restrinxíu. Siguiente llamada: Non restrinxíu</string>
+ <string name="serviceNotProvisioned">El serviciu nun se suministra.</string>
+ <string name="CLIRPermanent">Nun pues modificar el ID d\'emisor.</string>
+ <string name="RestrictedChangedTitle">Modificóse l\'accesu restrinxíu.</string>
+ <string name="RestrictedOnData">El serviciu de datos ta bloquiáu.</string>
+ <string name="RestrictedOnEmergency">El serviciu d\'emerxencia ta bloquiáu.</string>
+ <string name="RestrictedOnNormal">El serviciu de voz ta bloquiáu.</string>
+ <string name="RestrictedOnAllVoice">Tán bloquiaos tolos servicios de voz.</string>
+ <string name="RestrictedOnSms">El serviciu de SMS ta bloquiáu.</string>
+ <string name="RestrictedOnVoiceData">Los servicios de voz y de datos tán bloquiaos.</string>
+ <string name="RestrictedOnVoiceSms">Tán bloquiaos tolos servicios de voz y de SMS.</string>
+ <string name="RestrictedOnAll">Tán bloquiaos tolos servicios de voz, de datos y de SMS.</string>
+ <string name="serviceClassVoice">Voz</string>
+ <string name="serviceClassData">Datos</string>
+ <string name="serviceClassFAX">FAX</string>
+ <string name="serviceClassSMS">SMS</string>
+ <string name="serviceClassDataAsync">Asíncronos</string>
+ <string name="serviceClassDataSync">Sincronización</string>
+ <string name="serviceClassPacket">Paquete</string>
+ <string name="serviceClassPAD">PAD</string>
+ <string name="roamingText0">Indicador d\'itinerancia activáu</string>
+ <string name="roamingText1">Indicador d\'itinerancia desactiváu</string>
+ <string name="roamingText2">Indicador d\'itinerancia parpaguiante</string>
+ <string name="roamingText3">Fuera del vecindariu</string>
+ <string name="roamingText4">Fuera del edificiu</string>
+ <string name="roamingText5">Itinerancia: sistema preferíu</string>
+ <string name="roamingText6">Itinerancia: sistema disponible</string>
+ <string name="roamingText7">Itinerancia: partner d\'alianza</string>
+ <string name="roamingText8">Itinerancia: partner de gran calidá</string>
+ <string name="roamingText9">Itinerancia: funcionalidá de serviciu completa</string>
+ <string name="roamingText10">Itinerancia: funcionalidá de serviciu parcial</string>
+ <string name="roamingText11">Banner d\'itinerancia activáu</string>
+ <string name="roamingText12">Banner d\'itinerancia desactiváu</string>
+ <string name="roamingTextSearching">Guetando serviciu</string>
+ <string name="cfTemplateNotForwarded"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Non esviada</string>
+ <string name="cfTemplateForwarded"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g></string>
+ <string name="cfTemplateForwardedTime"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> trescurríos <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos</string>
+ <string name="cfTemplateRegistered"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Non esviada</string>
+ <string name="cfTemplateRegisteredTime"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Non esviada</string>
+ <string name="fcComplete">Códigu de función completu</string>
+ <string name="fcError">Hebo un fallu de conexón o\'l códigu de la función nun ye válidu.</string>
+ <string name="httpErrorOk">Aceutar</string>
+ <string name="httpError">Hebo un fallu de rede.</string>
+ <string name="httpErrorLookup">Nun pudo alcontrase la URL.</string>
+ <string name="httpErrorUnsupportedAuthScheme">Nun s\'almite l\'esquema d\'autenticación del sitiu.</string>
+ <string name="httpErrorAuth">Nun pudo autenticase.</string>
+ <string name="httpErrorProxyAuth">L\'autenticación per aciu del sirvidor proxy nun se fexo correutamente.</string>
+ <string name="httpErrorConnect">Nun pudo afitase conexón col sirvidor.</string>
+ <string name="httpErrorIO">Nun pudo afitase comunicación col sirvidor. Inténtalo de nueves.</string>
+ <string name="httpErrorTimeout">Escosó\'l tiempu d\'espera de conexón col sirvidor.</string>
+ <string name="httpErrorRedirectLoop">La páxina contién munchos redireicionamientos de sirvidor.</string>
+ <string name="httpErrorUnsupportedScheme">Protocolu non almitíu</string>
+ <string name="httpErrorFailedSslHandshake">Nun pudo afitase una conexón segura.</string>
+ <string name="httpErrorBadUrl">Nun pudo abrise la páxina porque la URL nun ye válida.</string>
+ <string name="httpErrorFile">Nun pudo accedese al ficheru.</string>
+ <string name="httpErrorFileNotFound">Nun pudo atopase\'l ficheru solicitáu.</string>
+ <string name="httpErrorTooManyRequests">Tán procesándose abondes solicitúes. Vuelvi a intentalo dempués.</string>
+ <string name="notification_title">Error d\'aniciu de sesión de <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g></string>
+ <string name="contentServiceSync">Sincronización</string>
+ <string name="contentServiceSyncNotificationTitle">Sincronización</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc">Abondes eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g></string>
+ <string name="low_memory" product="tablet">Escosó l\'espaciu d\'almacenamientu de la tablet. Desanicia dalgunos ficheros pa lliberar espaciu.</string>
+ <string name="low_memory" product="watch">Escosó l\'espaciu d\'almacenamientu de la tablet. Desanicia dalgunos ficheros pa lliberar espaciu.</string>
+ <string name="low_memory" product="default">Escosó l\'espaciu d\'almacenamientu del teléfonu. Desanicia dalgunos ficheros pa lliberar espaciu.</string>
+ <string name="ssl_ca_cert_warning">Ye dable que la rede tea supervisada</string>
+ <string name="ssl_ca_cert_noti_by_unknown">Por un terceru desconocíu</string>
+ <string name="ssl_ca_cert_noti_managed">Por <xliff:g id="MANAGING_DOMAIN">%s</xliff:g></string>
+ <string name="me">Yo</string>
+ <string name="power_dialog" product="tablet">Opciones de la tablet</string>
+ <string name="power_dialog" product="default">Opciones del teléfonu</string>
+ <string name="silent_mode">Mou silenciu</string>
+ <string name="turn_on_radio">Activar conexón inalámbrica</string>
+ <string name="turn_off_radio">Desactivar función inalámbrica</string>
+ <string name="screen_lock">Bloquéu de pantalla</string>
+ <string name="power_off">Apagar</string>
+ <string name="silent_mode_silent">Timbre desactiváu</string>
+ <string name="silent_mode_vibrate">Mou vibración</string>
+ <string name="silent_mode_ring">Timbre activáu</string>
+ <string name="shutdown_progress">Apagando\u2026</string>
+ <string name="shutdown_confirm" product="tablet">La tablet va apagase.</string>
+ <string name="shutdown_confirm" product="watch">El reló va apagase</string>
+ <string name="shutdown_confirm" product="default">El teléfonu va apagase.</string>
+ <string name="shutdown_confirm_question">¿De xuru que quies apagar el teléfonu?</string>
+ <string name="reboot_safemode_title">Reaniciar en mou seguru</string>
+ <string name="reboot_safemode_confirm">¿Quies reaniciar el sistema en mou seguru? Van inhabilitase toles aplicaciones esternas que tengas instalaes. Eses aplicaciones van restaurase la próxima vegada que reanicies del sistema.</string>
+ <string name="recent_tasks_title">Reciente</string>
+ <string name="no_recent_tasks">Nun hai aplicaciones recientes.</string>
+ <string name="global_actions" product="tablet">Opciones de la tablet</string>
+ <string name="global_actions" product="default">Opciones del teléfonu</string>
+ <string name="global_action_lock">Bloquéu de pantalla</string>
+ <string name="global_action_power_off">Apagar</string>
+ <string name="global_action_bug_report">Informe de fallu</string>
+ <string name="bugreport_title">Crear informe de fallos</string>
+ <string name="bugreport_message">Va atropase información tocante al estáu actual del preséu y va unviase per corréu-e. Van pasar unos minutos dende qu\'entame a xenerase l\'informe de fallos hasta que s\'unvie, polo qu\'encamentámoste que seyas paciente.</string>
+ <string name="global_action_toggle_silent_mode">Mou silenciu</string>
+ <string name="global_action_silent_mode_on_status">El soníu ta desactiváu. Activar</string>
+ <string name="global_action_silent_mode_off_status">El soníu ta activáu. Desactivar</string>
+ <string name="global_actions_toggle_airplane_mode">Mou avión</string>
+ <string name="global_actions_airplane_mode_on_status">Mou avión activáu</string>
+ <string name="global_actions_airplane_mode_off_status">Mou avión desactiváu</string>
+ <string name="global_action_settings">Axustes</string>
+ <string name="global_action_lockdown">Bloquiar agora</string>
+ <string name="status_bar_notification_info_overflow">999+</string>
+ <string name="safeMode">Mou seguru</string>
+ <string name="android_system_label">Sistema Android</string>
+ <string name="managed_profile_label">Trabayu</string>
+ <string name="permgrouplab_calendar">Calendariu</string>
+ <string name="permgrouplab_sms">SMS</string>
+ <string name="permgrouplab_storage">Almacenamientu</string>
+ <string name="permgrouplab_microphone">Micrófonu</string>
+ <string name="permgroupdesc_microphone">grabar soníu</string>
+ <string name="permgrouplab_camera">Cámara</string>
+ <string name="permgrouplab_phone">Teléfonu</string>
+ <string name="capability_title_canRetrieveWindowContent">Recuperar el conteníu de la ventana</string>
+ <string name="capability_desc_canRetrieveWindowContent">Inspeiciona\'l conteníu de la ventana cola que teas interactuando.</string>
+ <string name="capability_title_canRequestTouchExploration">Activar esploración táctil</string>
+ <string name="capability_desc_canRequestTouchExploration">Los elementos esbillaos van dicise en voz alta y vas poder esplorar la pantalla per duana de xestos.</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility">Activar accesibilidá web meyorada</string>
+ <string name="capability_desc_canRequestEnhancedWebAccessibility">Ye dable que s\'instalen secuencies de comandos pa que\'l conteníu de les aplicaciones seya más accesible.</string>
+ <string name="capability_title_canRequestFilterKeyEvents">Observar el testu qu\'escribes</string>
+ <string name="capability_desc_canRequestFilterKeyEvents">Inclúi datos personales como númberos de tarxetes de créitu y contraseñes.</string>
+ <string name="permlab_statusBar">inhabilitar o modificar la barra d\'estáu</string>
+ <string name="permdesc_statusBar">Permite que l\'aplicación inhabilite la barra d\'estáu o amieste y desanicie iconos del sistema.</string>
+ <string name="permlab_statusBarService">barra d\'estáu</string>
+ <string name="permdesc_statusBarService">Permite que l\'aplicación apaeza na barra d\'estáu.</string>
+ <string name="permlab_expandStatusBar">espander/contrayer la barra d\'estáu</string>
+ <string name="permdesc_expandStatusBar">Permite que l\'aplicación espanda o contraiga la barra d\'estáu.</string>
+ <string name="permlab_install_shortcut">instalar accesos direutos</string>
+ <string name="permdesc_install_shortcut">Permite qu\'una aplicación amieste accesos direutos a la pantalla d\'aniciu ensin intervención del usuariu.</string>
+ <string name="permlab_uninstall_shortcut">desinstalar accesos direutos</string>
+ <string name="permdesc_uninstall_shortcut">Permite que l\'aplicación desanicie accesos direutos de la pantalla d\'aniciu ensin la intervención del usuariu.</string>
+ <string name="permlab_processOutgoingCalls">redireicionar llamaes salientes</string>
+ <string name="permdesc_processOutgoingCalls">Permite que l\'aplicación vea\'l númberu que se ta marcando mientres una llamada saliente cola opción de redirixila a otro númberu o albortar dafechu la llamada.</string>
+ <string name="permlab_receiveSms">recibir mensaxes de testu (SMS)</string>
+ <string name="permdesc_receiveSms">Permite que l\'aplicación reciba y procese mensaxes MMS, lo que significa que podría usar esti permisu pa remanar o desaniciar mensaxes unviaos al preséu ensin amosá-ylos al usuariu.</string>
+ <string name="permlab_receiveMms">recibir mensaxes de testu (MMS)</string>
+ <string name="permdesc_receiveMms">Permite que l\'aplicación reciba y procese mensaxes MMS, lo que significa que podría usar esti permisu pa remanar o desaniciar mensaxes unviaos al preséu ensin amosá-ylos al usuariu.</string>
+ <string name="permlab_readCellBroadcasts">lleer mensaxes de difusión móvil</string>
+ <string name="permlab_subscribedFeedsRead">lleer feeds a los que ta soscritu l\'usuariu</string>
+ <string name="permdesc_subscribedFeedsRead">Permite que l\'aplicación obtenga detalles sobre los feeds sincronizaos anguaño.</string>
+ <string name="permdesc_sendSms">Permite que l\'aplicación unvie mensaxes SMS, lo que pue xenerar cargos inesperaos. Les aplicaciones malintencionaes puen causate gastos imprevistos al unviar mensaxes ensin la to confirmación.</string>
+ <string name="permlab_readSms">lleer los tos mensaxes de testu (SMS o MMS)</string>
+ <string name="permdesc_readSms" product="tablet">Permite que l\'aplicación llea mensaxes SMS almacenaos na tablet o na tarxeta SIM. L\'aplicación pue usar esti permisu pa lleer tolos mensaxes SMS, independientemente de cuál seya\'l so conteníu o\'l so nivel de confidencialidá.</string>
+ <string name="permdesc_readSms" product="default">Permite que l\'aplicación llea mensaxes SMS almacenaos nel teléfonu o na tarxeta SIM. L\'aplicación pue usar esti permisu pa lleer tolos mensaxes SMS, independientemente de cuál seya\'l so conteníu o\'l so nivel de confidencialidá.</string>
+ <string name="permlab_receiveWapPush">recibir mensaxes de testu (WAP)</string>
+ <string name="permdesc_receiveWapPush">Permite que l\'aplicación reciba y procese mensaxes WAP, lo que significa que podría usar esti permisu pa remanar o desaniciar mensaxes unviaos al usuariu ensin amosá-ylos.</string>
+ <string name="permlab_getTasks">recuperar aplicaciones n\'execución</string>
+ <string name="permdesc_getTasks">Permite que l\'aplicación recupere información sobre xeres que se tán executando nesi momentu o que s\'executaren de recién. L\'aplicación pue usar esti permisu pa descubrir cuáles son les aplicaciones que s\'usen nel preséu.</string>
+ <string name="permlab_reorderTasks">reorganizar aplicaciones n\'execución</string>
+ <string name="permdesc_reorderTasks">Permite que l\'aplicación mueva xeres a segundu o a primer planu. L\'aplicación pue usar esti permisu pa facer estos movimientos ensin que-y lo indique l\'usuariu.</string>
+ <string name="permlab_enableCarMode">habilitar mou coche</string>
+ <string name="permdesc_enableCarMode">Permite que l\'aplicación habilite\'l mou coche.</string>
+ <string name="permlab_killBackgroundProcesses">zarrar otres aplicaciones</string>
+ <string name="permdesc_killBackgroundProcesses">Esti permisu autoriza a l\'aplicación a torgar procesos en segundu planu d\'otres aplicaciones y pue facer, poro, qu\'eses aplicaciones dexen d\'executase.</string>
+ <string name="permlab_systemAlertWindow">amosar sobre otres aplicaciones</string>
+ <string name="permdesc_systemAlertWindow">Permite que l\'aplicación escriba sobre otres aplicaciones o en partes d\'interfaz d\'usuariu. Puen interferir col usu de la interfaz en cualquier aplicación o modificar lo que crees que s\'amuesa n\'otres aplicaciones.</string>
+ <string name="permlab_persistentActivity">facer que l\'aplicación s\'execute siempre</string>
+ <string name="permdesc_persistentActivity" product="tablet">Permite que l\'aplicación faiga que dalgunes de les sos partes se caltengan na memoria. Esto pue llendar la cantidá de memoria disponible pa otres aplicaciones y ralentizar la tablet.</string>
+ <string name="permdesc_persistentActivity" product="default">Permite que l\'aplicación faiga que dalgunes de les sos partes se caltengan na memoria. Esto pue llendar la cantidá de memoria disponible pa otres aplicaciones y ralentizar el teléfonu.</string>
+ <string name="permlab_getPackageSize">medir l\'espaciu d\'almacenamientu de l\'aplicación</string>
+ <string name="permdesc_getPackageSize">Permite que l\'aplicación recupere\'l so códigu, los datos y los tamaños de caché.</string>
+ <string name="permlab_writeSettings">modificar los axustes del sistema</string>
+ <string name="permdesc_writeSettings">Permite que l\'aplicación modifique los datos de configuración del sistema. Les aplicaciones malintencionaes puen dañar la configuración del sistema.</string>
+ <string name="permlab_receiveBootCompleted">executase al entamu</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet">Permite que l\'aplicación s\'execute automáticamente una vegada que\'l sistema s\'anicie completamente. Esto pue facer que la tablet tarde más n\'aniciase y permite que l\'aplicación ralentice\'l funcionamientu global del preséu.</string>
+ <string name="permdesc_receiveBootCompleted" product="default">Permite que l\'aplicación s\'execute automáticamente una vegada que\'l sistema s\'anicie completamente. Esto pue facer que\'l teléfonu tarde más n\'aniciase y pue permitir que l\'aplicación ralentice\'l funcionamientu global del preséu.</string>
+ <string name="permlab_broadcastSticky">unviar emisión persistente</string>
+ <string name="permdesc_broadcastSticky" product="tablet">Permite que l\'aplicación unvie emisiones que permanecen nel preséu una vegada que la emisión finó. Un usu escesivu podría ralentizar la tablet o tornala inestable al facer qu\'use muncha memoria.</string>
+ <string name="permdesc_broadcastSticky" product="default">Permite que l\'aplicación unvie emisiones que permanecen nel preséu una vegada que la emisión finó. Un usu escesivu podría ralentizar el teléfonu o tornalu inestable al facer qu\'use muncha memoria.</string>
+ <string name="permlab_readContacts">consultar los tos contautos</string>
+ <string name="permdesc_readContacts" product="tablet">Permite que l\'aplicación consulte información sobre contautos almacenaos na tablet, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Esti permisu permite guardar los datos de los contautos, y les aplicaciones malintencionaes puen usalu pa compartir datos de contautos del usuariu ensin el so consentimientu.</string>
+ <string name="permdesc_readContacts" product="default">Permite que l\'aplicación consulte información sobre contautos almacenaos nel teléfonu, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Esti permisu permite guardar los datos de los contautos, y les aplicaciones malintencionaes puen usalu pa compartir datos de contautos del usuariu ensin el so consentimientu.</string>
+ <string name="permlab_writeContacts">modificar los tos contautos</string>
+ <string name="permdesc_writeContacts" product="tablet">Permite que l\'aplicación modifique los datos de los contautos almacenaos na tablet, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Les aplicaciones puen usar esti permisu pa desaniciar datos de contautos.</string>
+ <string name="permdesc_writeContacts" product="default">Permite que l\'aplicación modifique los datos de los contautos almacenaos nel teléfonu, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Les aplicaciones puen usar esti permisu pa desaniciar datos de contautos.</string>
+ <string name="permlab_readCallLog">lleer el rexistru de llamaes</string>
+ <string name="permdesc_readCallLog" product="tablet">Permite que l\'aplicación consulte\'l rexistru de llamaes de la tablet, incluyíos datos sobre llamaes entrantes y salientes. Esti permisu permite guardar los datos del rexistru de llamaes, y les aplicaciones malintencionaes puen usalo pa compartir datos del rexistru de llamaes ensin el consentimientu del usuariu.</string>
+ <string name="permdesc_readCallLog" product="default">Permite que l\'aplicación consulte\'l rexistru de llamaes del teléfonu, incluyíos datos sobre llamaes entrantes y salientes. Esti permisu permite guardar los datos del rexistru de llamaes, y les aplicaciones malintencionaes puen usalo pa compartir datos del rexistru de llamaes ensin el consentimientu del usuariu.</string>
+ <string name="permlab_writeCallLog">escribir nel rexistru de llamaes</string>
+ <string name="permdesc_writeCallLog" product="tablet">Permite que l\'aplicación modifique\'l rexistru de llamaes de la tablet, incluyíos datos sobre llamaes entrantes y salientes. Les aplicaciones malintencionaes puen usar esti permisu pa desaniciar o modificar el rexistru de llamaes.</string>
+ <string name="permdesc_writeCallLog" product="default">Permite que l\'aplicación modifique\'l rexistru de llamaes del teléfonu, incluyíos datos sobre llamaes entrantes y salientes. Les aplicaciones malintencionaes puen usar esti permisu pa desaniciar o modificar el rexistru de llamaes.</string>
+ <string name="permlab_bodySensors">sens. corp. (mon. frec. card.)</string>
+ <string name="permlab_readCalendar">lleer eventos de calendariu ya información confidencial</string>
+ <string name="permdesc_readCalendar" product="tablet">Permite que l\'aplicación consulte tolos eventos de calendariu almacenaos na tablet, incluyíos los de collacios y compañeros de trabayu. L\'aplicación pue usar esti permisu pa compartir o guardar datos del calendariu del usuariu ensin tener en cuenta si son privaos o confidenciales.</string>
+ <string name="permdesc_readCalendar" product="default">Permite que l\'aplicación consulte tolos eventos de calendariu almacenaos nel teléfonu, incluyíos los de collacios y compañeros de trabayu. L\'aplicación pue usar esti permisu pa compartir o guardar datos del calendariu del usuariu ensin tener en cuenta si son privaos o confidenciales.</string>
+ <string name="permlab_writeCalendar">amestar o modificar eventos de calendariu y unviar mensaxes a los invitaos ensin el consentimientu de los propietarios</string>
+ <string name="permlab_accessLocationExtraCommands">acceder a comandos de fornidor de llocalización adicional</string>
+ <string name="permlab_accessFineLocation">llocalización precisa (basada en rede y GPS)</string>
+ <string name="permdesc_accessFineLocation">Permite que l\'aplicación obtenga la to llocalización precisa per duana del Sistema de posicionamientu global (GPS) o fontes de llocalización de rede, como torres de telefonía y redes Wi-Fi. Estos servicios de llocalización tienen de tar activaos y disponibles pa que l\'aplicación pueda usalos. Les aplicaciones puen usar esti permisu pa determinar la to llocalización y ye dable que\'l preséu consuma más batería.</string>
+ <string name="permlab_accessCoarseLocation">llocalización aproximada (basada en rede)</string>
+ <string name="permdesc_accessCoarseLocation">Permite que l\'aplicación obtenga la to llocalización aproximada. Esta llocalización remanez de los servicios de llocalización qu\'usen fontes de llocalización de rede, como torres de telefonía y redes Wi-Fi. Estos servicios de llocalización tienen de tar activaos y disponibles pa que l\'aplicación pueda usalos. Les aplicaciones puen usar esti permisu pa determinar la to llocalización de mou aproximáu.</string>
+ <string name="permlab_modifyAudioSettings">camudar la configuración d\'audiu</string>
+ <string name="permdesc_modifyAudioSettings">Permite que l\'aplicación modifique la configuración d\'audiu global (por exemplu, el volume y l\'altavoz de salida).</string>
+ <string name="permlab_recordAudio">grabar soníu</string>
+ <string name="permdesc_recordAudio">Permite que l\'aplicación grabe audiu col micrófonu. L\'aplicación pue usar esti permisu pa grabar audiu en cualquier momentu ensin tener la confirmación del usuariu.</string>
+ <string name="permlab_sim_communication">comunicación cola tarxeta SIM</string>
+ <string name="permdesc_sim_communication">Permite que l\'aplicación unvie comandos a la tarxeta SIM. Esti permisu YE MUI PELIGROSU.</string>
+ <string name="permlab_camera">facer semeyes y vídeos</string>
+ <string name="permdesc_camera">Permite que l\'aplicación faiga semeyes o grabe vídeos cola cámara. Esti permisu autoriza a l\'aplicación a usar la cámara en cualquier momentu ensin la to confirmación.</string>
+ <string name="permlab_vibrate">remanar la vibración</string>
+ <string name="permdesc_vibrate">Permite que l\'aplicación remane la función de vibración.</string>
+ <string name="permlab_flashlight">remanar llinterna</string>
+ <string name="permdesc_flashlight">Permite que l\'aplicación remane la función de llinterna.</string>
+ <string name="permlab_callPhone">llamar direutamente a númberos de teléfonu</string>
+ <string name="permdesc_callPhone">Permite que l\'aplicación faiga llamaes ensin intervención del usuariu, lo que pue dar llugar a llamaes o cargos inesperaos. Les aplicaciones nun puen usar este serviciu pa facer llamaes a númberos d\'emerxencia, pero les aplicaciones malintencionaes puen causate gastos imprevistos al facer llamaes ensin la to confirmación.</string>
+ <string name="permlab_readPhoneState">consultar la identidá y l\'estáu del teléfonu</string>
+ <string name="permdesc_readPhoneState">Permite que l\'aplicación acceda a les funciones de teléfonu del preséu. L\'aplicación pue usar esti permisu pa descubrir identificadores de preseos y númberos de teléfonu, pa saber si una llamada ta activa y pa conocer el númberu remotu col que s\'afitó conexón per aciu d\'una llamada.</string>
+ <string name="permlab_wakeLock" product="tablet">evitar que la tablet entre en mou de suspensión</string>
+ <string name="permlab_wakeLock" product="default">evitar que\'l teléfonu entre en mou de suspensión</string>
+ <string name="permdesc_wakeLock" product="tablet">Permite que l\'aplicación impida que la tablet entre en mou de suspensión.</string>
+ <string name="permdesc_wakeLock" product="default">Permite que l\'aplicación impida que\'l teléfonu entre en mou de suspensión.</string>
+ <string name="permlab_transmitIr">tresmitir infrabermeyos</string>
+ <string name="permdesc_transmitIr" product="tablet">Permite que l\'aplicación utilice\'l tresmisor d\'infrabermeyos de la tablet.</string>
+ <string name="permdesc_transmitIr" product="default">Permite que l\'aplicación utilice\'l tresmisor d\'infrabermeyos del teléfonu.</string>
+ <string name="permlab_setWallpaper">afitar fondu de pantalla</string>
+ <string name="permdesc_setWallpaper">Permite que l\'aplicación afite\'l fondu de pantalla del sistema.</string>
+ <string name="permlab_setWallpaperHints">axustar el tamañu del fondu de pantalla</string>
+ <string name="permdesc_setWallpaperHints">Permite que l\'aplicación afite\'l tamañu del fondu de pantalla del sistema.</string>
+ <string name="permlab_setTimeZone">afitar estaya horaria</string>
+ <string name="permdesc_setTimeZone" product="tablet">Permite que l\'aplicación camude la estaya horaria de la tablet.</string>
+ <string name="permdesc_setTimeZone" product="default">Permite que l\'aplicación camude la estaya horaria del teléfonu.</string>
+ <string name="permlab_getAccounts">guetar cuentes nel preséu</string>
+ <string name="permdesc_getAccounts" product="tablet">Permite que l\'aplicación obtenga una llista de cuentes reconocíes po la tablet, ente les que puen incluyise les cuentes creaes poles aplicaciones que tengas instalaes.</string>
+ <string name="permdesc_getAccounts" product="default">Permite que l\'aplicación obtenga una llista de cuentes reconocíes pol teléfonu, ente les que puen incluyise les cuentes creaes poles aplicaciones que tengas instalaes.</string>
+ <string name="permlab_accessNetworkState">ver conexones de rede</string>
+ <string name="permdesc_accessNetworkState">Permite que l\'aplicación vea información sobre conexones de rede (por exemplu, qué redes esisten y tán coneutaes).</string>
+ <string name="permlab_createNetworkSockets">accesu completu a rede</string>
+ <string name="permdesc_createNetworkSockets">Permite que l\'aplicación cree sockets de rede y use protocolos de rede personalizaos. El restolador web y otres aplicaciones proporcionen los medios necesarios pal unviu de datos a Internet, polo que nun fai falta usar esti permisu pa eso.</string>
+ <string name="permlab_changeNetworkState">cambiar la coneutividá de rede</string>
+ <string name="permdesc_changeNetworkState">Permite que l\'aplicación modifique l\'estáu de la coneutividá de rede.</string>
+ <string name="permlab_changeTetherState">cambiar coneutividá d\'anclaxe a rede</string>
+ <string name="permdesc_changeTetherState">Permite que l\'aplicación cambie l\'estáu de la coneutividá de rede d\'anclaxe.</string>
+ <string name="permlab_accessWifiState">ver conexones Wi-Fi</string>
+ <string name="permdesc_accessWifiState">Permite que l\'aplicación vea información sobre conexones a redes Wi-Fi (por exemplu, si ta habilitada la conexón Wi-Fi y el nome de los preseos Wi-Fi coneutaos).</string>
+ <string name="permlab_changeWifiState">coneutase a redes Wi-Fi y desconeutase</string>
+ <string name="permdesc_changeWifiState">Permite que l\'aplicación se coneute a puntos d\'accesu Wi-Fi y se desconeute d\'ellos y que faiga cambeos na configuración de redes Wi-Fi del preséu.</string>
+ <string name="permlab_changeWifiMulticastState">permitir receición multidifusión Wi-Fi</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet">Permite que l\'aplicación reciba paquetes unviaos a tolos preseos d\'una rede Wi-Fi qu\'usen direiciones de multidifusión, non sólo a la tablet. Utiliza más batería que\'l mou de non multidifusión.</string>
+ <string name="permdesc_changeWifiMulticastState" product="default">Permite que l\'aplicación reciba paquetes unviaos a tolos preseos d\'una rede Wi-Fi que utilicen direiciones de multidifusión, non sólo al teléfonu. Utiliza más batería que\'l mou de non multidifusión.</string>
+ <string name="permlab_bluetoothAdmin">acceder a los axustes de Bluetooth</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet">Permite que l\'aplicación configure la tablet Bluetooth llocal y que deteute preseos remotos y s\'emparexe con ellos.</string>
+ <string name="permdesc_bluetoothAdmin" product="default">Permite que l\'aplicación configure\'l teléfonu Bluetooth local y que deteute preseos remotos y s\'emparexe con ellos.</string>
+ <string name="permlab_accessWimaxState">coneutase a WiMAX y desconeutase d\'esta red</string>
+ <string name="permdesc_accessWimaxState">Permite que l\'aplicación determine si ta habilitada la conexón WiMAX y obtenga información sobre les redes WiMAX que tán coneutaes.</string>
+ <string name="permlab_changeWimaxState">Cambiar estáu de WiMAX</string>
+ <string name="permdesc_changeWimaxState" product="tablet">Permite que l\'aplicación coneute la tablet a redes WiMAX y la desconeute d\'elles.</string>
+ <string name="permdesc_changeWimaxState" product="default">Permite que l\'aplicación coneute\'l teléfonu a redes WiMAX y lu desconeute d\'elles.</string>
+ <string name="permlab_bluetooth">enllazar con preseos Bluetooth</string>
+ <string name="permdesc_bluetooth" product="tablet">Permite que l\'aplicación acceda a la configuración de Bluetooth de la tablet y qu\'afite y aceute conexones colos preseos sincronizaos.</string>
+ <string name="permdesc_bluetooth" product="default">Permite que l\'aplicación acceda a la configuración de Bluetooth del teléfonu y qu\'afite y aceute conexones colos preseos sincronizaos.</string>
+ <string name="permlab_nfc">remanar Comunicación de campu cercanu (NFC)</string>
+ <string name="permdesc_nfc">Permite que l\'aplicación se comunique con llectores, tarxetes y etiquetes de Comunicación de campu cercanu (NFC).</string>
+ <string name="permlab_disableKeyguard">inhabilitar el bloquéu de pantalla</string>
+ <string name="permdesc_disableKeyguard">Permite que l\'aplicación inhabilite\'l bloquéu del tecláu y cualquier proteición con contraseña asociada. Por exemplu, el teléfonu pue inhabilitar el bloquéu del tecláu cuando se recibe una llamada telefónica y volver a habilitalu cuando fina la llamada.</string>
+ <string name="permlab_readSyncSettings">lleer la configuración de sincronización</string>
+ <string name="permdesc_readSyncSettings">Permite que l\'aplicación consulte la configuración de sincronización d\'una cuenta. L\'aplicación pue usar esti permisu, por exemplu, pa determinar si l\'aplicación Contautos ta sincronizada con una cuenta.</string>
+ <string name="permlab_writeSyncSettings">activar y desactivar la sincronización</string>
+ <string name="permdesc_writeSyncSettings">Permite que l\'aplicación modifique la configuración de sincronización d\'una cuenta. Esti permisu pue usase, por exemplu, p\'habilitar la sincronización de l\'aplicación Contautos con una cuenta.</string>
+ <string name="permlab_readSyncStats">lleer estadístiques de sincronización</string>
+ <string name="permdesc_readSyncStats">Permite que l\'aplicación consulte les estadístiques de sincronización d\'una cuenta (por exemplu, l\'historial d\'eventos sincronizaos y la cantidá de datos sincronizaos).</string>
+ <string name="permlab_sdcardRead" product="nosdcard">consultar el conteníu del almacenamientu USB</string>
+ <string name="permlab_sdcardRead" product="default">consultar el conteníu de la tarxeta SD</string>
+ <string name="permdesc_sdcardRead" product="nosdcard">Permite que l\'aplicación llea\'l conteníu del almacenamientu USB.</string>
+ <string name="permdesc_sdcardRead" product="default">Permite que l\'aplicación llea\'l conteníu de la tarxeta SD.</string>
+ <string name="permlab_sdcardWrite" product="nosdcard">editar o desaniciar conteníu de USB</string>
+ <string name="permlab_sdcardWrite" product="default">modificar o desaniciar el conteníu de la tarxeta SD</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard">Permite escribir nel almacenamientu USB.</string>
+ <string name="permdesc_sdcardWrite" product="default">Permite que l\'aplicación escriba na tarxeta SD.</string>
+ <string name="permlab_use_sip">facer/recibir llamaes SIP</string>
+ <string name="permdesc_use_sip">Permite a la app facer y recibir llamaes SIP.</string>
+ <string name="permlab_bind_incall_service">interactuar cola pantalla de llamada</string>
+ <string name="permdesc_bind_incall_service">Permite que l\'aplicación remane cómo y cuándo apaez la pantalla de llamada.</string>
+ <string name="permlab_bind_connection_service">interactuar colos servicios de telefonía</string>
+ <string name="permdesc_bind_connection_service">Permite a la app interactuar colos servicios de telefonía pa facer/recibir llamaes.</string>
+ <string name="permlab_control_incall_experience">ufrir una esperiencia d\'usuariu de llamada</string>
+ <string name="permdesc_control_incall_experience">Permite a la app ufrir una esperiencia d\'usuariu de llamada</string>
+ <string name="permlab_readNetworkUsageHistory">lleer usu de rede históricu</string>
+ <string name="permdesc_readNetworkUsageHistory">Permite que l\'aplicación consulte l\'usu de rede históricu de redes y d\'aplicaciones específiques.</string>
+ <string name="permlab_manageNetworkPolicy">alministrar política de rede</string>
+ <string name="permdesc_manageNetworkPolicy">Permite que l\'aplicación alministre polítiques de rede y defina regles específiques de l\'aplicación.</string>
+ <string name="permlab_modifyNetworkAccounting">modificar cálculu d\'usu de rede</string>
+ <string name="permdesc_modifyNetworkAccounting">Permite que l\'aplicación modifique cómo se rexistra l\'usu de rede en rellación coles aplicaciones. Les aplicaciones normales nun tendríen d\'usar esti permisu.</string>
+ <string name="permlab_accessNotifications">acceder a les notificaciones</string>
+ <string name="permdesc_accessNotifications">Permite que l\'aplicación recupere, desamine y desanicie notificaciones, incluyíes les qu\'espublizaron otres aplicaciones.</string>
+ <string name="permlab_bindNotificationListenerService">enllazar con un serviciu de deteutor de notificaciones</string>
+ <string name="permdesc_bindNotificationListenerService">Permite enllazar cola interfaz de nivel superior d\'un serviciu de deteutor de notificaciones. Nun tendría de ser necesario pa les aplicaciones normales.</string>
+ <string name="permlab_bindConditionProviderService">enllazar con un serviciu de fornidor de condiciones</string>
+ <string name="permdesc_bindConditionProviderService">Permite enllazar cola interfaz de nivel superior d\'un serviciu de fornidor de condiciones. Nun tendría de ser necesario pa les aplicaciones normales.</string>
+ <string name="permlab_bindDreamService">enllazar con un serviciu de curiapantalles</string>
+ <string name="permdesc_bindDreamService">Permite enllazar cola interfaz de nivel superior d\'un serviciu de curiapantalles. Nun tendría de ser necesario pa les aplicaciones normales.</string>
+ <string name="permlab_invokeCarrierSetup">executar l\'aplicación de configuración proporcionada pol operador</string>
+ <string name="permdesc_invokeCarrierSetup">Permite executar l\'aplicación de configuración proporcionada pol operador. Nun tendría de ser necesario p\'aplicaciones normales.</string>
+ <string name="permlab_accessNetworkConditions">deteutar cambeos nel estáu de la rede</string>
+ <string name="permdesc_accessNetworkConditions">Permite qu\'una aplicación deteute cambeos nel estáu de la rede. Nun tendría de ser necesario p\'aplicaciones normales.</string>
+ <string name="permlab_setInputCalibration">camudar la calibración del preséu d\'entrada</string>
+ <string name="permdesc_setInputCalibration">Permite a la app camudar los parámetros de calibración de la pantalla táctil. Nun tendría de ser necesario pa les aplicaciones normales.</string>
+ <string name="permlab_accessDrmCertificates">acceder a certificaos DRM</string>
+ <string name="permdesc_accessDrmCertificates">Permite a la app dar y usar certificaos DRM. Nun tendría de ser necesario pa les aplicaciones normales.</string>
+ <string name="permlab_handoverStatus">Recibir estáu de tresferencies d\'Android Beam</string>
+ <string name="permdesc_handoverStatus">Permite qu\'esta app reciba información tocante a les tresferencies actuales d\'Android Beam</string>
+ <string name="permlab_removeDrmCertificates">desaniciar certificaos DRM</string>
+ <string name="permdesc_removeDrmCertificates">Permite a la app desaniciar certificaos DRM. Nun tendría de ser necesario pa les aplicaciones normales.</string>
+ <string name="policylab_limitPassword">Establecimientu de regles de contraseña</string>
+ <string name="policylab_watchLogin">Control d\'intentos de bloquéu de pantalla</string>
+ <string name="policydesc_watchLogin" product="tablet">Remana\'l númberu de contraseñes incorreutes introducíes al desbloquiar la pantalla y bloquia la tablet o desanicia tolos datos si s\'inxerten munches contraseñes incorreutes.</string>
+ <string name="policydesc_watchLogin" product="default">Remana\'l númberu de contraseñes incorreutes introducíes al desbloquiar la pantalla y bloquia\'l teléfonu o desanicia tolos datos si s\'inxerten munches contraseñes incorreutes.</string>
+ <string name="policylab_forceLock">Bloquéu de pantalla</string>
+ <string name="policydesc_forceLock">Remanar cómo y cuándo se bloquia la pantalla</string>
+ <string name="policylab_wipeData">Desaniciar tolos datos</string>
+ <string name="policydesc_wipeData" product="tablet">Desaniciar los datos de la tablet ensin avisar, reafitando los datos de fábrica</string>
+ <string name="policydesc_wipeData" product="default">Desaniciar los datos del teléfonu ensin avisar, reafitando los datos de fábrica</string>
+ <string name="policylab_setGlobalProxy">Definir el sirvidor proxy global</string>
+ <string name="policylab_encryptedStorage">Cifráu d\'almacenamientu</string>
+ <string name="policydesc_encryptedStorage">Desixe que se cifren los datos de l\'aplicación almacenaos.</string>
+ <string name="policylab_disableCamera">Inhabilitar cámares</string>
+ <string name="policydesc_disableCamera">Evitar l\'usu de les cámares del preséu</string>
+ <string-array name="phoneTypes">
+ <item>Casa</item>
+ <item>Móvil</item>
+ <item>Trabayu</item>
+ <item>Fax del trabayu</item>
+ <item>Fax de casa</item>
+ <item>Busca</item>
+ <item>Otru</item>
+ <item>Personalizar</item>
+ </string-array>
+ <string-array name="emailAddressTypes">
+ <item>Casa</item>
+ <item>Trabayu</item>
+ <item>Otra</item>
+ <item>Personalizar</item>
+ </string-array>
+ <string-array name="postalAddressTypes">
+ <item>Casa</item>
+ <item>Trabayu</item>
+ <item>Otra</item>
+ <item>Personalizar</item>
+ </string-array>
+ <string-array name="imAddressTypes">
+ <item>Casa</item>
+ <item>Trabayu</item>
+ <item>Otru</item>
+ <item>Personalizar</item>
+ </string-array>
+ <string-array name="organizationTypes">
+ <item>Trabayu</item>
+ <item>Otra</item>
+ <item>Personalizar</item>
+ </string-array>
+ <string-array name="imProtocols">
+ <item>AIM</item>
+ <item>Windows Live</item>
+ <item>Yahoo!</item>
+ <item>Skype</item>
+ <item>QQ</item>
+ <item>Google Talk</item>
+ <item>ICQ</item>
+ <item>Jabber</item>
+ </string-array>
+ <string name="phoneTypeCustom">Personalizáu</string>
+ <string name="phoneTypeHome">Casa</string>
+ <string name="phoneTypeMobile">Móvil</string>
+ <string name="phoneTypeWork">Trabayu</string>
+ <string name="phoneTypeFaxWork">Fax del trabayu</string>
+ <string name="phoneTypeFaxHome">Fax de casa</string>
+ <string name="phoneTypePager">Busca</string>
+ <string name="phoneTypeOther">Otru</string>
+ <string name="phoneTypeCallback">Devolución de llamada</string>
+ <string name="phoneTypeCar">Coche</string>
+ <string name="phoneTypeCompanyMain">Teléfonu principal de la empresa</string>
+ <string name="phoneTypeIsdn">RDSI</string>
+ <string name="phoneTypeMain">Principal</string>
+ <string name="phoneTypeOtherFax">Otru fax</string>
+ <string name="phoneTypeRadio">Señal móvil</string>
+ <string name="phoneTypeTelex">Télex</string>
+ <string name="phoneTypeTtyTdd">TTY TDD</string>
+ <string name="phoneTypeWorkMobile">Móvil del trabayu</string>
+ <string name="phoneTypeWorkPager">Busca del trabayu</string>
+ <string name="phoneTypeAssistant">Asistente</string>
+ <string name="phoneTypeMms">MMS</string>
+ <string name="eventTypeCustom">Personalizáu</string>
+ <string name="eventTypeBirthday">Cumpleaños</string>
+ <string name="eventTypeAnniversary">Aniversariu</string>
+ <string name="eventTypeOther">Otros</string>
+ <string name="emailTypeCustom">Personalizáu</string>
+ <string name="emailTypeHome">Casa</string>
+ <string name="emailTypeWork">Trabayu</string>
+ <string name="emailTypeOther">Otru</string>
+ <string name="emailTypeMobile">Móvil</string>
+ <string name="postalTypeCustom">Personalizada</string>
+ <string name="postalTypeHome">Casa</string>
+ <string name="postalTypeWork">Trabayu</string>
+ <string name="postalTypeOther">Otro</string>
+ <string name="imTypeCustom">Personalizáu</string>
+ <string name="imTypeHome">Casa</string>
+ <string name="imTypeWork">Trabayu</string>
+ <string name="imTypeOther">Otru</string>
+ <string name="imProtocolCustom">Personalizada</string>
+ <string name="imProtocolAim">AIM</string>
+ <string name="imProtocolMsn">Windows Live</string>
+ <string name="imProtocolYahoo">Yahoo!</string>
+ <string name="imProtocolSkype">Skype</string>
+ <string name="imProtocolQq">QQ</string>
+ <string name="imProtocolGoogleTalk">Hangouts</string>
+ <string name="imProtocolIcq">ICQ</string>
+ <string name="imProtocolJabber">Jabber</string>
+ <string name="imProtocolNetMeeting">NetMeeting</string>
+ <string name="orgTypeWork">Trabayu</string>
+ <string name="orgTypeOther">Otra</string>
+ <string name="orgTypeCustom">Personalizada</string>
+ <string name="relationTypeCustom">Personalizada</string>
+ <string name="relationTypeAssistant">Asistente</string>
+ <string name="relationTypeBrother">Hermanu</string>
+ <string name="relationTypeChild">Fíu/a</string>
+ <string name="relationTypeDomesticPartner">Pareya de fechu</string>
+ <string name="relationTypeFather">Padre</string>
+ <string name="relationTypeFriend">Collaciu/a</string>
+ <string name="relationTypeManager">Xefe</string>
+ <string name="relationTypeMother">Madre</string>
+ <string name="relationTypeParent">Padre/madre</string>
+ <string name="relationTypePartner">Pareya</string>
+ <string name="relationTypeReferredBy">Recomendáu por</string>
+ <string name="relationTypeRelative">Pariente</string>
+ <string name="relationTypeSister">Hermana</string>
+ <string name="relationTypeSpouse">Cónyugue</string>
+ <string name="sipAddressTypeCustom">Personalizada</string>
+ <string name="sipAddressTypeHome">Casa</string>
+ <string name="sipAddressTypeWork">Trabayu</string>
+ <string name="sipAddressTypeOther">Otru</string>
+ <string name="quick_contacts_not_available">Nun s\'atopó nenguna aplicación pa ver esti contautu.</string>
+ <string name="keyguard_password_enter_pin_code">Introduz el códigu PIN.</string>
+ <string name="keyguard_password_enter_puk_code">Introduz el códigu PUK y un nuevu códigu PIN.</string>
+ <string name="keyguard_password_enter_puk_prompt">Códigu PUK</string>
+ <string name="keyguard_password_enter_pin_prompt">Nuevu códigu PIN</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">Toca pa introducir contraseña</font></string>
+ <string name="keyguard_password_enter_password_code">Introduz la contraseña pa desbloquiar.</string>
+ <string name="keyguard_password_enter_pin_password_code">Inxerta\'l códigu PIN pa desbloquiar.</string>
+ <string name="keyguard_password_wrong_pin_code">Códigu PIN incorreutu</string>
+ <string name="keyguard_label_text">Pa desbloquiar el teléfonu, primi la tecla de menú y, a darréu, primi 0.</string>
+ <string name="emergency_call_dialog_number_for_display">Númberu d\'emerxencia</string>
+ <string name="lockscreen_carrier_default">Ensin serviciu</string>
+ <string name="lockscreen_screen_locked">Pantalla bloquiada</string>
+ <string name="lockscreen_instructions_when_pattern_enabled">Primi la tecla de menú pa desbloquiar el teléfonu o facer una llamada d\'emerxencia.</string>
+ <string name="lockscreen_instructions_when_pattern_disabled">Primi la tecla de menú pa desbloquiar la pantalla.</string>
+ <string name="lockscreen_pattern_instructions">Dibuxar patrón de desbloquéu</string>
+ <string name="lockscreen_return_to_call">Volver a llamada</string>
+ <string name="lockscreen_pattern_correct">Correutu</string>
+ <string name="lockscreen_pattern_wrong">Vuelvi a intentalo</string>
+ <string name="lockscreen_password_wrong">Vuelvi a intentalo</string>
+ <string name="faceunlock_multiple_failures">Perpasóse\'l númberu máximu d\'intentos de desbloquéu facial.</string>
+ <string name="lockscreen_missing_sim_message_short">Falta la tarxeta SIM.</string>
+ <string name="lockscreen_missing_sim_message" product="tablet">Nun s\'inxertó nenguna tarxeta SIM na tablet.</string>
+ <string name="lockscreen_missing_sim_message" product="default">Nun s\'inxertó nenguna tarxeta SIM nel teléfonu.</string>
+ <string name="lockscreen_missing_sim_instructions">Inxerta una tarxeta SIM.</string>
+ <string name="lockscreen_missing_sim_instructions_long">Falta la tarxeta SIM o nun pue lleese. Introduz una tarxeta SIM.</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short">Tarxeta SIM inutilizable</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions">La tarxeta SIM inhabilitóse permanentemente.\n Pa obtener otra tarxeta SIM, ponte en contautu col tu fornidor de servicios de telefonía.</string>
+ <string name="lockscreen_transport_prev_description">Pista anterior</string>
+ <string name="lockscreen_transport_next_description">Pista siguiente</string>
+ <string name="lockscreen_transport_pause_description">Posar</string>
+ <string name="lockscreen_transport_play_description">Reproducir</string>
+ <string name="lockscreen_transport_stop_description">Detener</string>
+ <string name="lockscreen_transport_rew_description">Rebobinar</string>
+ <string name="lockscreen_transport_ffw_description">Avance rápidu</string>
+ <string name="emergency_calls_only" msgid="2485604591272668370">Namái llamaes d\'emerxencia</string>
+ <string name="lockscreen_network_locked_message">Bloquiada pa la rede</string>
+ <string name="lockscreen_sim_puk_locked_message">La tarxeta SIM ta bloquiada col códigu PUK.</string>
+ <string name="lockscreen_sim_puk_locked_instructions">Ver la Guía d\'usuariu o contautar con atención al veceru.</string>
+ <string name="lockscreen_sim_locked_message">La tarxeta SIM ta bloquiada.</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message">Desbloquiando tarxeta SIM\u2026</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message">Fixisti <xliff:g id="number">%d</xliff:g> intentos fallíos de desbloquéu.
+\n\nVuelvi intentalo en <xliff:g id="number">%d</xliff:g> segundos.
+    </string>
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message">Introduxisti una contraseña incorreuta <xliff:g id="number">%d</xliff:g> vegaes.\n\nInténtalo otra vuelta en <xliff:g id="number">%d</xliff:g> segundos.
+    </string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message">Introduxisti un códigu PIN incorreutu <xliff:g id="NUMBER_0">%d</xliff:g> vegaes. \n\nInténtalo otra vuelta en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet">Fallasti <xliff:g id="number">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. Si falles otres <xliff:g id="number">%d</xliff:g> vegaes, vas tener d\'usar les tos credenciales d\'accesu de Google pa desbloquiar la tablet.\n\n Inténtalo otra vuelta en <xliff:g id="number">%d</xliff:g> segundos.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, vas tender d\'usar les tos credenciales d\'accesu de Google pa desbloquiar el teléfonu.\n\n Inténtalo otra vuelta en <xliff:g id="NUMBER_2">%d</xliff:g> segundos.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet">Intentasti desbloquiar la tablet <xliff:g id="NUMBER_0">%d</xliff:g> vegaes, pero nun pudisti. Si falles <xliff:g id="NUMBER_1">%d</xliff:g> vegaes más, van restablecese los datos de fábrica y van perdese tolos datos del usuariu.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default">Intentasti desbloquiar el teléfonu <xliff:g id="NUMBER_0">%d</xliff:g> vegaes, pero nun pudisti. Si falles <xliff:g id="NUMBER_1">%d</xliff:g> vegaes más, van restablecese los datos de fábrica y van perdese tolos datos del usuariu.</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tablet">Intentasti desbloquiar la tablet <xliff:g id="NUMBER">%d</xliff:g> vegaes, pero nun pudisti. Van restablecese los datos de fábrica del preséu.</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default">Intentasti desbloquiar el teléfonu <xliff:g id="NUMBER">%d</xliff:g> vegaes, pero nun pudisti. Van restablecese los datos de fábrica del preséu.</string>
+ <string name="lockscreen_too_many_failed_attempts_countdown">Espera <xliff:g id="NUMBER">%d</xliff:g> segundos y vuelvi a intentalo.</string>
+ <string name="lockscreen_forgot_pattern_button_text">¿Escaecisti\'l patrón?</string>
+ <string name="lockscreen_glogin_forgot_pattern">Desbloquéu de cuenta</string>
+ <string name="lockscreen_glogin_too_many_attempts">Demasiaos intentos incorreutos de creación del patrón</string>
+ <string name="lockscreen_glogin_instructions">Pa desbloquiar el teléfonu, anicia sesión cola to cuenta de Google.</string>
+ <string name="lockscreen_glogin_username_hint">Nome d\'usuariu (corréu electrónicu)</string>
+ <string name="lockscreen_glogin_password_hint">Contraseña</string>
+ <string name="lockscreen_glogin_submit_button">Aniciar sesión</string>
+ <string name="lockscreen_glogin_invalid_input">Nome d\'usuariu o contraseña non válidu</string>
+ <string name="lockscreen_glogin_account_recovery_hint">Si escaecisti\'l to nome d\'usuariu o contraseña,\nentra na páxina \"<b>google.com/accounts/recovery"</b>.</string>
+ <string name="lockscreen_glogin_checking_password">Comprobando\u2026</string>
+ <string name="lockscreen_unlock_label">Desbloquiar</string>
+ <string name="lockscreen_sound_on_label">Activar soníu</string>
+ <string name="lockscreen_sound_off_label">Desactivar soníu</string>
+ <string name="lockscreen_access_pattern_start">Patrón aniciáu</string>
+ <string name="lockscreen_access_pattern_cleared">Patrón desaniciáu</string>
+ <string name="lockscreen_access_pattern_cell_added">Amestóse una caxella.</string>
+ <string name="lockscreen_access_pattern_detected">Patrón completáu</string>
+ <string name="lockscreen_access_pattern_area" msgid="">Área de patrón</string>
+ <string name="keyguard_accessibility_widget_changed">%1$s. Widget %2$d de %3$d</string>
+ <string name="keyguard_accessibility_add_widget">Amestar widget</string>
+ <string name="keyguard_accessibility_widget_empty_slot">Baleru</string>
+ <string name="keyguard_accessibility_unlock_area_expanded">Área de desbloquéu ampliada</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed">Área de desbloquéu contrayida</string>
+ <string name="keyguard_accessibility_widget">Widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g></string>
+ <string name="keyguard_accessibility_user_selector">Seleutor d\'usuarios</string>
+ <string name="keyguard_accessibility_status">Estáu</string>
+ <string name="keyguard_accessibility_camera">Cámara</string>
+ <string name="keygaurd_accessibility_media_controls">Controles multimedia</string>
+ <string name="keyguard_accessibility_widget_reorder_start">Empezó a cambiase l\'orde de los widgets.</string>
+ <string name="keyguard_accessibility_widget_reorder_end">Finó de cambiase l\'orde de los widgets.</string>
+ <string name="keyguard_accessibility_widget_deleted">Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> desaniciáu</string>
+ <string name="keyguard_accessibility_expand_lock_area">Ampliar área de desbloquéu</string>
+ <string name="keyguard_accessibility_slide_unlock">Desbloquéu eslizando\'l deu</string>
+ <string name="keyguard_accessibility_pattern_unlock">Desbloquéu por patrón</string>
+ <string name="keyguard_accessibility_face_unlock">Desbloquéu facial</string>
+ <string name="keyguard_accessibility_pin_unlock">Desbloquéu por PIN</string>
+ <string name="keyguard_accessibility_password_unlock">Desbloquéu por contraseña</string>
+ <string name="keyguard_accessibility_pattern_area">Área de patrón</string>
+ <string name="keyguard_accessibility_slide_area">Área pa eslizar</string>
+ <string name="password_keyboard_label_symbol_key">\?123</string>
+ <string name="password_keyboard_label_alpha_key">ABC</string>
+ <string name="password_keyboard_label_alt_key">ALT</string>
+ <string name="granularity_label_character">caráuter</string>
+ <string name="granularity_label_word">pallabra</string>
+ <string name="granularity_label_link">enllaz</string>
+ <string name="granularity_label_line">llinia</string>
+ <string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
+ <string name="hour_cap_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="PM">%p</xliff:g>"</string>
+ <string name="factorytest_failed">Fallu na prueba de fábrica</string>
+ <string name="factorytest_not_system">L\'aición FACTORY_TEST namái ye compatible colos paquetes instalaos en /system/app.</string>
+ <string name="factorytest_no_action">Nun s\'atopó nengún paquete que proporcione l\'aición FACTORY_TEST.</string>
+ <string name="factorytest_reboot">Reaniciar</string>
+ <string name="js_dialog_title">La páxina \"<xliff:g id="TITLE">%s</xliff:g>\" diz:</string>
+ <string name="js_dialog_title_default">JavaScript</string>
+ <string name="js_dialog_before_unload_title">Confirmar navegación</string>
+ <string name="js_dialog_before_unload_positive_button">Colar d\'esta páxina</string>
+ <string name="js_dialog_before_unload_negative_button">Permanecer nesta páxina</string>
+ <string name="js_dialog_before_unload"><xliff:g id="MESSAGE">%s</xliff:g>\n\n¿De xuru que quies colar d\'esta páxina?</string>
+ <string name="save_password_label">Confirmar</string>
+ <string name="double_tap_toast">Suxerencia: toca dos vegaes p\'ampliar o amenorgar el conteníu.</string>
+ <string name="autofill_this_form">Autocompletar</string>
+ <string name="setup_autofill">Configurar Autocompletar</string>
+ <string name="autofill_address_name_separator">\u0020</string>
+ <string name="autofill_address_summary_name_format">$1$2$3</string>
+ <string name="autofill_address_summary_separator">, </string>
+ <string name="autofill_address_summary_format">$1$2$3</string>
+ <string name="autofill_attention_ignored_re">attention|attn</string>
+ <string name="autofill_region_ignored_re">province|region|other<!-- es -->|provincia<!-- pt-BR, pt-PT -->|bairro|suburb</string>
+ <string name="autofill_company_re">company|business|organization|organisation|department<!-- de-DE -->|firma|firmenname<!-- es -->|empresa<!-- fr-FR -->|societe|société<!-- it-IT -->|ragione.?sociale<!-- ja-JP -->|会社<!-- ru -->|название.?компании<!-- zh-CN -->|单位|公司</string>
+ <string name="autofill_address_line_1_re">address.?line|address1|addr1|street<!-- de-DE -->|strasse|straße|hausnummer|housenumber<!-- en-GB -->|house.?name<!-- es -->|direccion|dirección<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所1<!-- pt-BR, pt-PT -->|morada|endereço<!-- ru -->|Адрес<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_1_label_re">address<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_2_re">address.?line2|address2|addr2|street|suite|unit<!-- de-DE -->|adresszusatz|ergänzende.?angaben<!-- es -->|direccion2|colonia|adicional<!-- fr-FR -->|addresssuppl|complementnom|appartement<!-- it-IT -->|indirizzo2<!-- ja-JP -->|住所2</string>
+ <string name="autofill_address_line_3_re">address.?line3|address3|addr3|street|line3<!-- es -->|municipio<!-- fr-FR -->|batiment|residence<!-- it-IT -->|indirizzo3</string>
+ <string name="autofill_country_re">country|location<!-- ja-JP -->|国<!-- zh-CN -->|国家</string>
+ <string name="autofill_zip_code_re">zip|postal|post code|pcode|^1z$<!-- de-DE -->|postleitzahl<!-- es -->|cp<!-- fr-FR -->|cdp<!-- it-IT -->|cap<!-- ja-JP -->|郵便番号<!-- pt-BR, pt-PT -->|codigo|codpos|cep<!-- ru -->|Почтовый.?Индекс<!--zh-CN -->|邮政编码|邮编<!-- zh-TW -->|郵遞區號</string>
+ <string name="autofill_zip_4_re">zip|^-$|post2<!-- pt-BR, pt-PT -->|codpos2</string>
+ <string name="autofill_city_re">city|town<!-- de-DE -->|ort|stadt<!-- en-AU -->|suburb<!-- es -->|ciudad|provincia|localidad|poblacion<!-- fr-FR -->|ville|commune<!-- it-IT -->|localita<!-- ja-JP -->|市区町村<!-- pt-BR, pt-PT -->|cidade<!-- ru -->|Город<!-- zh-CN -->|市<!-- zh-TW -->|分區</string>
+ <string name="autofill_state_re">state|county|region|province<!-- de-DE -->|land<!-- en-UK -->|county|principality<!-- ja-JP -->|都道府県<!-- pt-BR, pt-PT -->|estado|provincia<!-- ru -->|область<!-- zh-CN -->|省<!-- zh-TW -->|地區</string>
+ <string name="autofill_address_type_same_as_re">same as</string>
+ <string name="autofill_address_type_use_my_re">use my</string>
+ <string name="autofill_billing_designator_re">bill</string>
+ <string name="autofill_shipping_designator_re">ship</string>
+ <string name="autofill_email_re">e.?mail<!-- ja-JP -->|メールアドレス<!-- ru -->|Электронной.?Почты<!-- zh-CN -->|邮件|邮箱<!-- zh-TW -->|電郵地址</string>
+ <string name="autofill_username_re">user.?name|user.?id<!-- de-DE -->|vollständiger.?name<!-- zh-CN -->|用户名</string>
+ <string name="autofill_name_re">^name|full.?name|your.?name|customer.?name|firstandlastname<!-- es -->|nombre.*y.*apellidos<!-- fr-FR -->|^nom<!-- ja-JP -->|お名前|氏名<!-- pt-BR, pt-PT -->|^nome<!-- zh-CN -->|姓名</string>
+ <string name="autofill_name_specific_re">^name<!-- fr-FR -->|^nom<!-- pt-BR, pt-PT -->|^nome</string>
+ <string name="autofill_first_name_re">irst.*name|initials|fname|first$<!-- de-DE -->|vorname<!-- es -->|nombre<!-- fr-FR -->|forename|prénom|prenom<!-- ja-JP -->|名<!-- pt-BR, pt-PT -->|nome<!-- ru -->|Имя</string>
+ <string name="autofill_middle_initial_re">middle.*initial|m\\.i\\.|mi$</string>
+ <string name="autofill_middle_name_re">middle.*name|mname|middle$<!-- es -->|apellido.?materno|lastlastname</string>
+ <string name="autofill_last_name_re">last.*name|lname|surname|last$<!-- de-DE -->|nachname<!-- es -->|apellidos<!-- fr-FR -->|famille|^nom<!-- it-IT -->|cognome<!-- ja-JP -->|姓<!-- pt-BR, pt-PT -->|morada|apelidos|surename|sobrenome<!-- ru -->|Фамилия</string>
+ <string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfonu<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string>
+ <string name="autofill_area_code_re">area.*code|acode|area</string>
+ <string name="autofill_phone_prefix_re">prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
+ <string name="autofill_phone_suffix_re">sufixu</string>
+ <string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string>
+ <string name="autofill_name_on_card_re">card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|karteninhaber<!-- es -->|nombre.*tarjeta<!-- fr-FR -->|nom.*carte<!-- it-IT -->|nome.*cart<!-- ja-JP -->|名前<!-- ru -->|Имя.*карты<!-- zh-CN -->|信用卡开户名|开户名|持卡人姓名<!-- zh-TW -->|持卡人姓名</string>
+ <string name="autofill_name_on_card_contextual_re">nome</string>
+ <string name="autofill_card_cvc_re">verification|card identification|cvn|security code|cvv code|cvc</string>
+ <string name="autofill_card_number_re">number|card.?#|card.?no|ccnum<!-- de-DE -->|nummer<!-- es -->|credito|numero|número<!-- fr-FR -->|numéro<!-- ja-JP -->|カード番号<!-- ru -->|Номер.*карты<!-- zh-CN -->|信用卡号|信用卡号码<!-- zh-TW -->|信用卡卡號</string>
+ <string name="autofill_expiration_month_re">expir|exp.*month|exp.*date|ccmonth<!-- de-DE -->|gueltig|gültig|monat<!-- es -->|fecha<!-- fr-FR -->|date.*exp<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|月</string>
+ <string name="autofill_expiration_date_re">exp|^/|year<!-- de-DE -->|ablaufdatum|gueltig|gültig|yahr<!-- es -->|fecha<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|年|有效期</string>
+ <string name="autofill_card_ignored_re">^card</string>
+ <string name="autofill_fax_re">fax<!-- fr-FR -->|télécopie|telecopie<!-- ja-JP -->|ファックス<!-- ru -->|факс<!-- zh-CN -->|传真<!-- zh-TW -->|傳真</string>
+ <string name="autofill_country_code_re">country.*code|ccode|_cc</string>
+ <string name="autofill_area_code_notext_re">^\\($</string>
+ <string name="autofill_phone_prefix_separator_re">^-$|^\\)$</string>
+ <string name="autofill_phone_suffix_separator_re">^-$</string>
+ <string name="autofill_province">Provincia</string>
+ <string name="autofill_postal_code">Códigu postal</string>
+ <string name="autofill_state">Estáu</string>
+ <string name="autofill_zip_code">Códigu postal</string>
+ <string name="autofill_county">Conceyu</string>
+ <string name="autofill_island">Islla</string>
+ <string name="autofill_district">Distritu</string>
+ <string name="autofill_department">Departamentu</string>
+ <string name="autofill_prefecture">Prefectura</string>
+ <string name="autofill_parish">Distritu</string>
+ <string name="autofill_area">Área</string>
+ <string name="autofill_emirate">Emiratu</string>
+ <string name="permlab_readHistoryBookmarks">consultar l\'historial y marcadores web</string>
+ <string name="permdesc_readHistoryBookmarks">Permite que l\'aplicación consulte l\'historial de toles URL visitaes pol restolador web y tolos sos marcadores. Nota: esti permisu nun puen usalu restoladores esternos nin otres aplicaciones que tengan funciones de navegación per Internet.</string>
+ <string name="permlab_writeHistoryBookmarks">escribir nel historial y nos marcadores web</string>
+ <string name="permlab_setAlarm">afitar una alarma</string>
+ <string name="permlab_addVoicemail">amestar buzón de voz</string>
+ <string name="permdesc_addVoicemail">Permite que l\'aplicación amieste mensaxes a la bandexa d\'entrada del buzón de voz.</string>
+ <string name="permlab_writeGeolocationPermissions">modificar los permisos de llocalización xeográfica del restolador web</string>
+ <string name="permdesc_writeGeolocationPermissions">Permite que l\'aplicación modifique los permisos de llocalización xeográfica del restolador web. Les aplicaciones malintencionaes puen usar esti permisu p\'autorizar l\'unviu d\'información sobre la llocalización a sitios web arbitrarios.</string>
+ <string name="save_password_message">¿Quies que\'l restolador web recuerde esta contraseña?</string>
+ <string name="save_password_notnow">Agora non</string>
+ <string name="save_password_remember">Recordar</string>
+ <string name="save_password_never">Enxamás</string>
+ <string name="open_permission_deny">Nun tienes permisu p\'abrir esta páxina.</string>
+ <string name="text_copied">Testu copiáu al cartafueyu.</string>
+ <string name="more_item_label">Más</string>
+ <string name="prepend_shortcut_label">MENU+</string>
+ <string name="menu_space_shortcut_label">espaciu</string>
+ <string name="menu_enter_shortcut_label">intro</string>
+ <string name="menu_delete_shortcut_label">desaniciar</string>
+ <string name="search_go">Guetar</string>
+ <string name="searchview_description_search">Guetar</string>
+ <string name="searchview_description_query">Consulta</string>
+ <string name="searchview_description_clear">Desaniciar consulta</string>
+ <string name="searchview_description_submit">Unviar consulta</string>
+ <string name="searchview_description_voice">Guetar por voz</string>
+ <string name="enable_explore_by_touch_warning_title">¿Habilitar esploración táctil?</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet"><xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quier habilitar la esploración táctil. Cuando esta función tea activada, vas poder escuchar o ver descripciones del conteníu esbilláu o usar xestos pa interactuar cola tablet.</string>
+ <string name="enable_explore_by_touch_warning_message" product="default"><xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quier habilitar la esploración táctil. Cuando esta función tea activada, vas poder escuchar o ver descripciones del conteníu esbilláu o usar xestos pa interactuar col teléfonu.</string>
+ <string name="oneMonthDurationPast">hai un mes</string>
+ <string name="beforeOneMonthDurationPast">hai más d\'un mes</string>
+ <string name="last_month">el mes pasáu</string>
+ <string name="older">anterior</string>
+ <string name="preposition_for_date">el <xliff:g id="DATE">%s</xliff:g></string>
+ <string name="preposition_for_time">a les <xliff:g id="TIME">%s</xliff:g></string>
+ <string name="preposition_for_year">en <xliff:g id="YEAR">%s</xliff:g></string>
+ <string name="day">día</string>
+ <string name="days">díes</string>
+ <string name="hour">hora</string>
+ <string name="hours">hores</string>
+ <string name="minute">min</string>
+ <string name="minutes">minutos</string>
+ <string name="second">segundu</string>
+ <string name="seconds">segundos</string>
+ <string name="week">selmana</string>
+ <string name="weeks">selmanes</string>
+ <string name="year">añu</string>
+ <string name="years">años</string>
+ <string name="VideoView_error_title">Incidencies col videu</string>
+ <string name="VideoView_error_text_invalid_progressive_playback">Esti videu nun pue tresmitise al preséu.</string>
+ <string name="VideoView_error_text_unknown">Nun pue reproducise\'l videu.</string>
+ <string name="VideoView_error_button">Aceutar</string>
+ <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="noon">"meudía"</string>
+ <string name="Noon">"Meudía"</string>
+ <string name="midnight">"medianueche"</string>
+ <string name="Midnight">"Medianueche"</string>
+ <string name="elapsed_time_short_format_mm_ss"><xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g></string>
+ <string name="elapsed_time_short_format_h_mm_ss"><xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g></string>
+ <string name="selectAll">Esbillar too</string>
+ <string name="cut">Cortar</string>
+ <string name="copy">Copiar</string>
+ <string name="paste">Apegar</string>
+ <string name="replace">Sustituyir\u2026</string>
+ <string name="delete">Desaniciar</string>
+ <string name="copyUrl">Copiar URL</string>
+ <string name="selectTextMode">Esbillar testu</string>
+ <string name="textSelectionCABTitle">Seleición de testu</string>
+ <string name="addToDictionary">Amestar al diccionariu</string>
+ <string name="deleteText">Desaniciar</string>
+ <string name="inputMethod">Métodu d\'introducción de testu</string>
+ <string name="editTextMenuTitle">Aiciones de testu</string>
+ <string name="low_internal_storage_view_title">Queda poco espaciu</string>
+ <string name="low_internal_storage_view_text">Ye dable que dalgunes funciones del sistema nun funcionen.</string>
+ <string name="low_internal_storage_view_text_no_boot">Nun hai espaciu bastante pal sistema. Comprueba qu\'heba 250 MB llibres y reanicia\'l preséu.</string>
+ <string name="app_running_notification_title"><xliff:g id="APP_NAME">%1$s</xliff:g> ta executándose</string>
+ <string name="app_running_notification_text">Toca pa obtener más información o pa detener l\'aplicación.</string>
+ <string name="ok">Aceutar</string>
+ <string name="cancel">Encaboxar</string>
+ <string name="yes">Aceutar</string>
+ <string name="no">Encaboxar</string>
+ <string name="dialog_alert_title">Atención</string>
+ <string name="loading">Cargando\u2026</string>
+ <string name="capital_on">SÍ</string>
+ <string name="capital_off">NON</string>
+ <string name="whichApplication">Completar aición usando</string>
+ <string name="whichApplicationNamed">Completar aición usando %1$s</string>
+ <string name="whichViewApplication">Abrir con</string>
+ <string name="whichViewApplicationNamed">Abrir con %1$s</string>
+ <string name="whichEditApplication">Editar con</string>
+ <string name="whichEditApplicationNamed">Editar con %1$s</string>
+ <string name="whichSendApplication">Compartir con</string>
+ <string name="whichSendApplicationNamed">Compartir con %1$s</string>
+ <string name="whichHomeApplication">Esbillar una aplicación na pantalla d\'aniciu</string>
+ <string name="whichHomeApplicationNamed">Usar %1$s como aplicación d\'aniciu</string>
+ <string name="alwaysUse">Usar siempre pa esta aición</string>
+ <string name="use_a_different_app">Usar una app distinta</string>
+ <string name="clearDefaultHintMsg">Pa desaniciar los valores predeterminaos, vete a Axustes del sistema &gt; Aplicaciones &gt; Descargaes.</string>
+ <string name="chooseActivity">Esbilla una aición</string>
+ <string name="chooseUsbActivity">Seleicionar una aplicación pal preséu USB</string>
+ <string name="noApplications">Nenguna aplicación pue facer esta aición.</string>
+ <string name="aerr_application">Detúvose l\'aplicación <xliff:g id="APPLICATION">%1$s</xliff:g>.</string>
+ <string name="aerr_process">Detúvose\'l procesu <xliff:g id="PROCESS">%1$s</xliff:g>.</string>
+ <string name="anr_activity_application">L\'aplicación <xliff:g id="APPLICATION">%2$s</xliff:g> nun respuende.\n\n¿Quies zarrala?</string>
+ <string name="anr_activity_process">L\'actividá <xliff:g id="ACTIVITY">%1$s</xliff:g> nun respuende.\n\n¿Quies zarrala?</string>
+ <string name="anr_application_process">L\'aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> nun respuende. ¿Quies zarrala?</string>
+ <string name="anr_process">El procesu <xliff:g id="PROCESS">%1$s</xliff:g> nun respuende.\n\n¿Quies zarralu?</string>
+ <string name="force_close">Aceutar</string>
+ <string name="report">Informar</string>
+ <string name="wait">Esperar</string>
+ <string name="webpage_unresponsive">La páxina nun respuende.\n\n¿Quies zarrala?</string>
+ <string name="launch_warning_title">Aplicación redireicionada</string>
+ <string name="launch_warning_replace"><xliff:g id="APP_NAME">%1$s</xliff:g> ta executándose.</string>
+ <string name="launch_warning_original">Primeramente, anicióse l\'aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>.</string>
+ <string name="screen_compat_mode_scale">Escala</string>
+ <string name="screen_compat_mode_show">Amosar siempre</string>
+ <string name="screen_compat_mode_hint">Pa volver a habilitar esta opción, vete a Axustes &gt; Aplicaciones &gt; Descargaes.</string>
+ <string name="smv_application">L\'aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (procesu <xliff:g id="PROCESS">%2$s</xliff:g>) infrinxó la política StrictMode autoaplicable.</string>
+ <string name="smv_process">El procesu <xliff:g id="PROCESS">%1$s</xliff:g> infrinxó la política StrictMode autoaplicable.</string>
+ <string name="android_upgrading_title">Anovando Android</string>
+ <string name="android_upgrading_fstrim">Optimizando almacenamientu.</string>
+ <string name="android_upgrading_apk">Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>\u2026</string>
+ <string name="android_upgrading_starting_apps">Aniciando aplicaciones</string>
+ <string name="android_upgrading_complete">Finando arranque\u2026</string>
+ <string name="heavy_weight_notification"><xliff:g id="APP">%1$s</xliff:g> n\'execución</string>
+ <string name="heavy_weight_notification_detail">Toca esta opción pa cambiar a l\'aplicación.</string>
+ <string name="heavy_weight_switcher_title">¿Cambiar aplicaciones?</string>
+ <string name="heavy_weight_switcher_text">Ta executándose otra aplicación. P\'aniciar una aplicación nueva, has detenela.</string>
+ <string name="old_app_action">Volver a <xliff:g id="OLD_APP">%1$s</xliff:g></string>
+ <string name="old_app_description">Nun aniciar la nueva aplicación</string>
+ <string name="new_app_action">Aniciar <xliff:g id="OLD_APP">%1$s</xliff:g></string>
+ <string name="new_app_description">Detener l\'aplicación anterior ensin guardar</string>
+ <string name="sendText">Seleiciona una aición pal testu</string>
+ <string name="volume_ringtone">Volume del timbre</string>
+ <string name="volume_music">Volume multimedia</string>
+ <string name="volume_music_hint_playing_through_bluetooth">Reproduciendo a traviés de Bluetooth</string>
+ <string name="volume_music_hint_silent_ringtone_selected">Tonu de silenciu afitáu</string>
+ <string name="volume_call">Volume de la llamada</string>
+ <string name="volume_bluetooth_call">Volume de la llamada de Bluetooth</string>
+ <string name="volume_alarm">Volume d\'alarma</string>
+ <string name="volume_notification">Volume de notificaciones</string>
+ <string name="volume_unknown">Volume</string>
+ <string name="volume_icon_description_bluetooth">Volume de Bluetooth</string>
+ <string name="volume_icon_description_ringer">Volume del tonu</string>
+ <string name="volume_icon_description_incall">Volume de llamada</string>
+ <string name="volume_icon_description_media">Volume multimedia</string>
+ <string name="volume_icon_description_notification">Volume de notificaciones</string>
+ <string name="ringtone_default">Tonu predetermináu</string>
+ <string name="ringtone_default_with_actual">Tonu predetermináu (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)</string>
+ <string name="ringtone_silent">Nengún</string>
+ <string name="ringtone_picker_title">Tonos</string>
+ <string name="ringtone_unknown">Tonu desconocíu</string>
+ <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
+ <string name="wifi_watchdog_network_disabled">Nun pudo afitase conexón cola rede Wi-Fi.</string>
+ <string name="wifi_watchdog_network_disabled_detailed"> tien una conexón inestable a Internet.</string>
+ <string name="wifi_p2p_dialog_title">Wi-Fi Direutu</string>
+ <string name="wifi_p2p_turnon_message">Aniciar Wi-Fi Direct. Va desactivase\'l funcionamientu de la zona o del cliente Wi-Fi.</string>
+ <string name="wifi_p2p_failed_message">Nun pudo aniciase Wi-Fi Direct.</string>
+ <string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct activáu</string>
+ <string name="wifi_p2p_enabled_notification_message">Toca p\'acceder a Axustes</string>
+ <string name="accept">Aceutar</string>
+ <string name="decline">Refugar</string>
+ <string name="wifi_p2p_invitation_sent_title">Invitación unviada</string>
+ <string name="wifi_p2p_invitation_to_connect_title">Invitación pa coneutase</string>
+ <string name="wifi_p2p_from_message">De:</string>
+ <string name="wifi_p2p_to_message">Pa:</string>
+ <string name="wifi_p2p_enter_pin_message">Escribi\'l PIN solicitáu:</string>
+ <string name="wifi_p2p_show_pin_message">PIN:</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet">La tablet va desconeutase temporalmente de la rede Wi-Fi mientres teas coneutáu a <xliff:g id="DEVICE_NAME">%1$s</xliff:g></string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default">El teléfonu va desconeutase temporalmente de la rede Wi-Fi mientres teas coneutáu a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>.</string>
+ <string name="select_character">Inxertar carácter</string>
+ <string name="sms_control_title">Unviando mensaxes SMS\u2026</string>
+ <string name="sms_control_message">&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta unviando un gran númberu de mensaxes SMS. ¿Quies permitir que l\'aplicación siga unviando mensaxes?</string>
+ <string name="sms_control_yes">Permitir</string>
+ <string name="sms_control_no">Refugar</string>
+ <string name="sms_short_code_confirm_message">&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quier unviar un mensaxe a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;.</string>
+ <string name="sms_short_code_details">Esto <b>pue ocasionar cargos</b> na to cuenta móvil.</string>
+ <string name="sms_premium_short_code_details"><b>Esto va ocasionar cargos na to cuenta móvil.</b></string>
+ <string name="sms_short_code_confirm_allow">Unviar</string>
+ <string name="sms_short_code_confirm_deny">Encaboxar</string>
+ <string name="sms_short_code_remember_choice">Recordar opción esbillada</string>
+ <string name="sms_short_code_remember_undo_instruction">Pues cambiar esta opción más tarde en Axustes &gt; Aplicaciones.</string>
+ <string name="sms_short_code_confirm_always_allow">Permitir siempre</string>
+ <string name="sms_short_code_confirm_never_allow">Nun permitir enxamás</string>
+ <string name="sim_removed_title">Tarxeta SIM desaniciada</string>
+ <string name="sim_removed_message">La rede móvil nun va tar disponible hasta que reanicies el preséu con una tarxeta SIM válida.</string>
+ <string name="sim_done_button">Fecho</string>
+ <string name="sim_added_title">Tarxeta SIM amestada</string>
+ <string name="sim_added_message">Reanicia\'l preséu p\'acceder a la rede móvil.</string>
+ <string name="sim_restart_button">Reaniciar</string>
+ <string name="time_picker_dialog_title">Afitar hora</string>
+ <string name="date_picker_dialog_title">Afitar data</string>
+ <string name="date_time_set">Afitar</string>
+ <string name="date_time_done">Fecho</string>
+ <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff33b5e5">NUEVU:</font></string>
+ <string name="perms_description_app">Proporcionáu por <xliff:g id="APP_NAME">%1$s</xliff:g></string>
+ <string name="no_permissions">Nun fai falta nengún permisu</string>
+ <string name="perm_costs_money">ye dable que se cobre por usar l\'aplicación.</string>
+ <string name="usb_storage_activity_title">Almacenamientu USB masivu</string>
+ <string name="usb_storage_title">Conexón per USB</string>
+ <string name="usb_storage_message" product="nosdcard">Coneutóse\'l preséu al ordenador per USB. Toca\'l siguiente botón si quies tresferir ficheros ente l\'ordenador y l\'almacenamientu USB del preséu.</string>
+ <string name="usb_storage_message" product="default">Coneutóse\'l preséu al ordenador per USB. Toca\'l siguiente botón si quies tresferir ficheros ente l\'ordenador y la tarxeta SD del preséu.</string>
+ <string name="usb_storage_button_mount">Activar almacenamientu USB</string>
+ <string name="usb_storage_error_message" product="nosdcard">Hebo un fallu al usar l\'almacenamientu USB como almacenamientu USB masivu.</string>
+ <string name="usb_storage_error_message" product="default">Hebo un fallu al usar la tarxeta SD pal almacenamientu USB masivu.</string>
+ <string name="usb_storage_notification_title">Conexón per USB</string>
+ <string name="usb_storage_notification_message">Toca pa tresferir ficheros</string>
+ <string name="usb_storage_stop_notification_title">Desactivar almacenamientu USB</string>
+ <string name="usb_storage_stop_notification_message">Toca pa desactivar l\'almacenamientu USB.</string>
+ <string name="usb_storage_stop_title">L\'almacenamientu USB ta n\'usu</string>
+ <string name="usb_storage_stop_message" product="nosdcard">Enantes de desactivar l\'almacenamientu USB, desactiva l\'almacenamientu USB del preséu Android del ordenador.</string>
+ <string name="usb_storage_stop_message" product="default">Enantes de desactivar l\'almacenamientu USB, desactiva la tarxeta SD del preséu Android del ordenador.</string>
+ <string name="usb_storage_stop_button_mount">Desactivar almacenamientu USB</string>
+ <string name="usb_storage_stop_error_message">Hebo un fallu al desactivar l\'almacenamientu USB. Comprueba que desactivasti\'l host USB, y darréu, vuelvi a intentalo.</string>
+ <string name="dlg_confirm_kill_storage_users_title">Activar almacenamientu USB</string>
+ <string name="dlg_confirm_kill_storage_users_text">Si actives l\'almacenamientu USB, van parase dalgunes aplicaciones que tas usando y ye dable que nun tean disponibles hasta que lu desactives.</string>
+ <string name="dlg_error_title">Fallu de funcionamientu de USB</string>
+ <string name="dlg_ok">Aceutar</string>
+ <string name="usb_accessory_notification_title">Coneutáu a un accesoriu USB</string>
+ <string name="adb_active_notification_title">Depuración USB coneutada</string>
+ <string name="adb_active_notification_message">Toca pa desactivar la depuración USB.</string>
+ <string name="select_input_method">Cambiar tecláu</string>
+ <string name="configure_input_methods">Esbillar teclaos</string>
+ <string name="show_ime">Amosar métodu d\'entrada</string>
+ <string name="hardware">Hardware</string>
+ <string name="select_keyboard_layout_notification_title">Seleiciona un diseñu de tecláu</string>
+ <string name="select_keyboard_layout_notification_message">Toca pa seleicionar un diseñu de tecláu.</string>
+ <string name="fast_scroll_alphabet"> ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="fast_scroll_numeric_alphabet"> 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="candidates_style"><u>candidatos</u></string>
+ <string name="ext_media_status_checking">Comprobando\u2026</string>
+ <string name="activity_list_empty">Nun s\'atopó nenguna actividá coincidente.</string>
+ <string name="permlab_route_media_output">Dirixir salida de mediu</string>
+ <string name="permdesc_route_media_output">Permite que l\'aplicación dirixa salides de medios a otros preseos esternos.</string>
+ <string name="permlab_readInstallSessions">Consultar sesiones d\'instalación</string>
+ <string name="permdesc_readInstallSessions">Permite qu\'una aplicación consulte sesiones d\'instalación pa ver detalles tocante a instalaciones de paquetes activos.</string>
+ <string name="tutorial_double_tap_to_zoom_message_short">Toca dos vegaes p\'acceder al control de zoom.</string>
+ <string name="gadget_host_error_inflating">Nun pudo amestase\'l widget.</string>
+ <string name="ime_action_go">Dir</string>
+ <string name="ime_action_search">Guetar</string>
+ <string name="ime_action_send">Unviar</string>
+ <string name="ime_action_next">Siguiente</string>
+ <string name="ime_action_done">Fecho</string>
+ <string name="ime_action_previous">Anterior</string>
+ <string name="ime_action_default">Executar</string>
+ <string name="dial_number_using">Marcar númberu\ncon <xliff:g id="NUMBER">%s</xliff:g></string>
+ <string name="create_contact_using">Crear un contautu\na partir de <xliff:g id="NUMBER">%s</xliff:g></string>
+ <string name="grant_credentials_permission_message_header">Les siguientes aplicaciones soliciten permisu p\'acceder a la to cuenta agora y nel futuru.</string>
+ <string name="grant_credentials_permission_message_footer">¿Quies permitir esta solicitú?</string>
+ <string name="grant_permissions_header_text">Solicitú d\'accesu</string>
+ <string name="allow">Permitir</string>
+ <string name="deny">Refugar</string>
+ <string name="permission_request_notification_title">Permisu solicitáu</string>
+ <string name="permission_request_notification_with_subtitle">Permisu solicitáu\npa la cuenta <xliff:g id="ACCOUNT">%s</xliff:g></string>
+ <string name="forward_intent_to_owner">Tas usando esta app fuera del perfil de trabayu</string>
+ <string name="forward_intent_to_work">Tas usando esta app nel to perfil de trabayu</string>
+ <string name="input_method_binding_label">Métodu d\'introducción de testu</string>
+ <string name="sync_binding_label">Sincronización</string>
+ <string name="accessibility_binding_label">Accesibilidá</string>
+ <string name="wallpaper_binding_label">Fondu de pantalla</string>
+ <string name="chooser_wallpaper">Camudar fondu de pantalla</string>
+ <string name="notification_listener_binding_label">Deteutor de notificaciones</string>
+ <string name="condition_provider_service_binding_label">Fornidor de condiciones</string>
+ <string name="vpn_title">VPN activada</string>
+ <string name="vpn_title_long">VPN activada por <xliff:g id="APP">%s</xliff:g></string>
+ <string name="vpn_text">Toca p\'alministrar la rede.</string>
+ <string name="vpn_text_long">Coneutáu a <xliff:g id="SESSION">%s</xliff:g>. Toca p\'alministrar la rede.</string>
+ <string name="vpn_lockdown_connecting">Coneutando VPN siempre activada…</string>
+ <string name="vpn_lockdown_connected">VPN siempre activada coneutada</string>
+ <string name="vpn_lockdown_error">Fallu de VPN siempre activada</string>
+ <string name="vpn_lockdown_config">Toca pa configurar</string>
+ <string name="upload_file">Esbillar ficheru</string>
+ <string name="no_file_chosen">Ficheru non esbilláu</string>
+ <string name="reset">Restablecer</string>
+ <string name="submit">Unviar</string>
+ <string name="car_mode_disable_notification_title">Habilitóse\'l mou coche.</string>
+ <string name="car_mode_disable_notification_message">Toca pa salir del mou coche.</string>
+ <string name="tethered_notification_title">Anclaxe a rede/Zona Wi-Fi activu</string>
+ <string name="tethered_notification_message">Toca pa configurar</string>
+ <string name="back_button_label">Atrás</string>
+ <string name="next_button_label">Siguiente</string>
+ <string name="skip_button_label">Saltar</string>
+ <string name="no_matches">Nun hai coincidencies.</string>
+ <string name="find_on_page">Guetar na páxina</string>
+ <string name="action_mode_done">Listo</string>
+ <string name="progress_erasing" product="nosdcard">Desaniciando almacenamientu USB\u2026</string>
+ <string name="progress_erasing" product="default">Desaniciando tarxeta SD\u2026</string>
+ <string name="share">Compartir</string>
+ <string name="find">Guetar</string>
+ <string name="websearch">Guetar na web</string>
+ <string name="find_next">Atopar siguiente</string>
+ <string name="find_previous">Atopar anterior</string>
+ <string name="gpsNotifTicker">Solicitú de llocalización de <xliff:g id="NAME">%s</xliff:g></string>
+ <string name="gpsNotifTitle">Solicitú de llocalización</string>
+ <string name="gpsNotifMessage">Solicitú unviada por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)</string>
+ <string name="gpsVerifYes">Sí</string>
+ <string name="gpsVerifNo">Non</string>
+ <string name="sync_too_many_deletes">Perpasóse la llende de desanicios.</string>
+ <string name="sync_too_many_deletes_desc">Hai <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> elementos desaniciaos pa <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> (cuenta <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>). ¿Qué quies facer?</string>
+ <string name="sync_really_delete">Desaniciar elementos</string>
+ <string name="sync_undo_deletes">Desfacer los desanicios</string>
+ <string name="sync_do_nothing">Nun facer un res agora</string>
+ <string name="choose_account_label">Esbilla una cuenta</string>
+ <string name="add_account_label">"Amestar una cuenta"</string>
+ <string name="add_account_button_label">Amestar cuenta</string>
+ <string name="number_picker_increment_button">Aumentar</string>
+ <string name="number_picker_decrement_button">Amenorgar</string>
+ <string name="number_picker_increment_scroll_mode">Caltén primíu <xliff:g id="VALUE">%s</xliff:g>.</string>
+ <string name="number_picker_increment_scroll_action">Esliza\'l deu hacia arriba p\'aumentar y hacia abaxo p\'amenorgar.</string>
+ <string name="time_picker_increment_minute_button">Aumentar minutos</string>
+ <string name="time_picker_decrement_minute_button">Amenorgar minutos</string>
+ <string name="time_picker_increment_hour_button">Aumentar hores</string>
+ <string name="time_picker_decrement_hour_button">Amenorgar hores</string>
+ <string name="time_picker_increment_set_pm_button">Afitar p.m.</string>
+ <string name="time_picker_decrement_set_am_button">Afitar a.m.</string>
+ <string name="date_picker_increment_month_button">Aumentar mes</string>
+ <string name="date_picker_decrement_month_button">Amenorgar mes</string>
+ <string name="date_picker_increment_day_button">Aumentar díes</string>
+ <string name="date_picker_decrement_day_button">Amenorgar díes</string>
+ <string name="date_picker_increment_year_button">Aumentar añu</string>
+ <string name="date_picker_decrement_year_button">Amenorgar año</string>
+ <string name="keyboardview_keycode_alt">Alt</string>
+ <string name="keyboardview_keycode_cancel">Encaboxar</string>
+ <string name="keyboardview_keycode_delete">Desaniciar</string>
+ <string name="keyboardview_keycode_done">Fecho</string>
+ <string name="keyboardview_keycode_mode_change">Cambéu de mou</string>
+ <string name="keyboardview_keycode_shift">Mayús</string>
+ <string name="keyboardview_keycode_enter">Intro</string>
+ <string name="activitychooserview_choose_application">Esbillar una aplicación</string>
+ <string name="activitychooserview_choose_application_error">Nun pudo abrise <xliff:g id="APPLICATION_NAME">%s</xliff:g></string>
+ <string name="shareactionprovider_share_with">Compartir con</string>
+ <string name="shareactionprovider_share_with_application">Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g></string>
+ <string name="content_description_sliding_handle">"Caltén primíu l'iconu de desbloquéu y eslízalu."</string>
+ <string name="description_target_unlock_tablet">Esliza\'l deu pa desbloquiar.</string>
+ <string name="keyboard_headset_required_to_hear_password">Coneuta un auricular pa escuchar les contraseñes.</string>
+ <string name="keyboard_password_character_no_headset">Puntu</string>
+ <string name="action_bar_home_description">Dir al escritoriu</string>
+ <string name="action_bar_up_description">Desplazase hacia arriba</string>
+ <string name="action_menu_overflow_description">Más opciones</string>
+ <string name="action_bar_home_description_format">%1$s, %2$s</string>
+ <string name="action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>
+ <string name="storage_internal">Almacenamientu internu</string>
+ <string name="storage_sd_card">Tarxeta SD</string>
+ <string name="storage_usb">Almacenamientu USB</string>
+ <string name="data_usage_warning_title">Avisu d\'usu de datos</string>
+ <string name="data_usage_warning_body">Toca pa ver l\'usu y axustes.</string>
+ <string name="data_usage_3g_limit_title">Algamóse la llende de datos 2G-3G</string>
+ <string name="data_usage_4g_limit_title">Algamóse la llende de datos 4G</string>
+ <string name="data_usage_mobile_limit_title">Algamóse la llende de datos móviles</string>
+ <string name="data_usage_wifi_limit_title">Llende de datos Wi-Fi algamada</string>
+ <string name="data_usage_limit_body">Datos posaos restu de ciclu</string>
+ <string name="data_usage_3g_limit_snoozed_title">Llende de datos 2G-3G perpasada</string>
+ <string name="data_usage_4g_limit_snoozed_title">Llende de datos 4G perpasada</string>
+ <string name="data_usage_mobile_limit_snoozed_title">Perpasóse llende datos móviles</string>
+ <string name="data_usage_wifi_limit_snoozed_title">Llende de datos Wi-Fi perpasada</string>
+ <string name="data_usage_limit_snoozed_body">Llende perpasada en <xliff:g id="SIZE">%s</xliff:g></string>
+ <string name="data_usage_restricted_title">Conexones automátiques restrinxíes</string>
+ <string name="data_usage_restricted_body">Toca pa desaniciar la restricción.</string>
+ <string name="ssl_certificate">Certificáu de seguranza</string>
+ <string name="ssl_certificate_is_valid">Esti certificáu ye válidu.</string>
+ <string name="issued_to">Emitíu pa:</string>
+ <string name="common_name">Nome común:</string>
+ <string name="org_name">Organización:</string>
+ <string name="org_unit">Departamentu:</string>
+ <string name="issued_by">Emitíu por:</string>
+ <string name="validity_period">Validez:</string>
+ <string name="issued_on">Data d\'emisión:</string>
+ <string name="expires_on">Data de caducidá:</string>
+ <string name="serial_number">Númberu de serie:</string>
+ <string name="fingerprints">Buelgues dixitales:</string>
+ <string name="sha256_fingerprint">Buelga dixital SHA-256:</string>
+ <string name="sha1_fingerprint">Buelga dixital SHA-1:</string>
+ <string name="activity_chooser_view_see_all">Ver too</string>
+ <string name="activity_chooser_view_dialog_title_default">Selecionar actividá</string>
+ <string name="share_action_provider_share_with">Compartir con</string>
+ <string name="list_delimeter">", "</string>
+ <string name="sending">Unviando\u2026</string>
+ <string name="launchBrowserDefault">¿Aniciar el restolador web?</string>
+ <string name="SetupCallDefault">¿Aceutar la llamada?</string>
+ <string name="activity_resolver_use_always">Siempre</string>
+ <string name="activity_resolver_use_once">Namái una vegada</string>
+ <string name="activity_resolver_work_profiles_support">%1$s nun almites perfiles de trabayu</string>
+ <string name="default_audio_route_name" product="tablet">Tablet</string>
+ <string name="default_audio_route_name" product="default">Teléfonu</string>
+ <string name="default_audio_route_name_headphones">Auriculares</string>
+ <string name="default_audio_route_name_dock_speakers">Altavoces de la base</string>
+ <string name="default_media_route_name_hdmi">HDMI</string>
+ <string name="default_audio_route_category_name">Sistema</string>
+ <string name="bluetooth_a2dp_audio_route_name">Audiu Bluetooth</string>
+ <string name="wireless_display_route_description">Pantalla inalámbrica</string>
+ <string name="media_route_button_content_description">Cast</string>
+ <string name="media_route_chooser_title">Coneutar a preséu</string>
+ <string name="media_route_chooser_title_for_remote_display">Unviar pantalla a preséu</string>
+ <string name="media_route_chooser_searching">Guetando por preseos…</string>
+ <string name="media_route_chooser_extended_settings">Axustes</string>
+ <string name="media_route_controller_disconnect">Desconeutar</string>
+ <string name="media_route_status_scanning">Analizando\u2026</string>
+ <string name="media_route_status_connecting">Coneutando\u2026</string>
+ <string name="media_route_status_available">Disponible</string>
+ <string name="media_route_status_not_available">Non disponible</string>
+ <string name="media_route_status_in_use">N\'usu</string>
+ <string name="display_manager_built_in_display_name">Pantalla integrada</string>
+ <string name="display_manager_hdmi_display_name">Pantalla HDMI</string>
+ <string name="display_manager_overlay_display_name">Superposición #<xliff:g id="ID">%1$d</xliff:g></string>
+ <string name="display_manager_overlay_display_title"><xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi</string>
+ <string name="display_manager_overlay_display_secure_suffix">, seguru</string>
+ <string name="kg_forgot_pattern_button_text">¿Escaecisti\'l patrón?</string>
+ <string name="kg_wrong_pattern">El patrón ye incorreutu</string>
+ <string name="kg_wrong_password">Contraseña incorreuta</string>
+ <string name="kg_wrong_pin">PIN incorreutu</string>
+ <string name="kg_too_many_failed_attempts_countdown">Inténtalo otra vuelta en <xliff:g id="NUMBER">%1$d</xliff:g> segundos.</string>
+ <string name="kg_pattern_instructions">Dibuxa\'l to patrón de desbloquéu.</string>
+ <string name="kg_sim_pin_instructions">Inxerta\'l PIN de la tarxeta SIM.</string>
+ <string name="kg_pin_instructions">Introduz el PIN.</string>
+ <string name="kg_password_instructions">Escribi la contraseña.</string>
+ <string name="kg_puk_enter_puk_hint">La tarxeta SIM ta inhabilitada. Pa continuar, inxerta\'l códigu PUK. Si quies obtener más información, ponte en contautu col operador</string>
+ <string name="kg_puk_enter_pin_hint">Introduz el códigu PIN deseáu</string>
+ <string name="kg_enter_confirm_pin_hint">Confirma\'l códigu PIN</string>
+ <string name="kg_sim_unlock_progress_dialog_message">Desbloquiando tarxeta SIM…</string>
+ <string name="kg_password_wrong_pin_code">Códigu PIN incorreutu</string>
+ <string name="kg_invalid_sim_pin_hint">Introduz un códigu PIN con una llonxitú comprendida ente cuatro y ocho díxitos.</string>
+ <string name="kg_invalid_sim_puk_hint">El códigu PUK tien de tener ocho númberos como mínimo.</string>
+ <string name="kg_invalid_puk">Vuelvi a introducir el códigu PUK correutu. Si introduces un códigu incorreutu delles vegaes, va inhabilitase la tarxeta SIM.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">Los códigos PIN nun concasen.</string>
+ <string name="kg_login_too_many_attempts">Abondos intentos incorreutos de crear el patrón</string>
+ <string name="kg_login_instructions">Pa desbloquiar el teléfonu, anicia sesión cola to cuenta de Google.</string>
+ <string name="kg_login_username_hint">Nome d\'usuariu (corréu-e)</string>
+ <string name="kg_login_password_hint">Contraseña</string>
+ <string name="kg_login_submit_button">Aniciar sesión</string>
+ <string name="kg_login_invalid_input">El nome d\'usuariu o la contraseña nun son válidos.</string>
+ <string name="kg_login_account_recovery_hint">Si escaecisti\'l nome d\'usuariu o la contraseña,\nvete a la páxina \"<b>google.com/accounts/recovery"</b>.</string>
+ <string name="kg_login_checking_password">Comprobando cuenta…</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">Punxisti un códigu PIN incorreutu <xliff:g id="NUMBER_0">%d</xliff:g> vegaes. \n\nVuelvi a intentalo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">Punxisti una contraseña incorreuta <xliff:g id="NUMBER_0">%d</xliff:g> vegaes. \n\nVuelvi a intentalo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. \n\nVuelvi a intentalo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet">Intentasti desbloquiar la tablet <xliff:g id="NUMBER_0">%d</xliff:g> vegaes, pero nun pudisti. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, van reafitase los datos de fábrica y van perdese tolos datos del usuariu.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default">Intentasti desbloquiar el teléfonu <xliff:g id="NUMBER_0">%d</xliff:g> vegaes, pero nun pudisti. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, van reafitase los datos de fábrica y van perdese tolos datos del usuariu.</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet">Intentasti desbloquiar la tablet <xliff:g id="NUMBER">%d</xliff:g> vegaes, pero nun pudisti. Van reafitase los datos de fábrica del preséu.</string>
+ <string name="kg_failed_attempts_now_wiping" product="default">Intentasti desbloquiar el teléfonu <xliff:g id="NUMBER">%d</xliff:g> vegaes, pero nun pudisti. Van reafitase los datos de fábrica del preséu.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, vas tener d\'usar una cuenta de corréu-e pa desbloquiar la tablet.\n\n Vuelvi a intentalo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, vas tener d\'usar una cuenta de corréu-e pa desbloquiar el teléfonu.\n\n Vuelvi a intentalo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos.</string>
+ <string name="kg_text_message_separator" product="default">" — "</string>
+ <string name="kg_reordering_delete_drop_target_text">Desaniciar</string>
+ <string name="safe_media_volume_warning" product="default">
+ ¿Quies xubir el volume penriba del nivel recomendáu?\n\nEscuchar soníos al altu la lleva mentanto llargos períodos de tiempu pue dañar los oyíos
+ </string>
+ <string name="continue_to_enable_accessibility">Caltén la pantalla primida con dos deos p\'habilitar les funciones d\'accesibilidá.</string>
+ <string name="accessibility_enabled">Accesibilidá habilitada</string>
+ <string name="enable_accessibility_canceled">Accesibilidá encaboxada</string>
+ <string name="user_switched">Usuariu actual: <xliff:g id="NAME">%1$s</xliff:g></string>
+ <string name="user_switching_message">Camudando a <xliff:g id="name" example="Bob">%1$s</xliff:g>\u2026</string>
+ <string name="owner_name" msgid="3879126011135546571">Propietariu</string>
+ <string name="error_message_title">Fallu</string>
+ <string name="error_message_change_not_allowed">Esti cambéu nun ta permitíu pol alministrador</string>
+ <string name="app_not_found">Nun s\'atopó nenguna aplicación que pueda facer esta aición.</string>
+ <string name="revoke">Revocar</string>
+ <string name="mediasize_iso_a0">ISO A0</string>
+ <string name="mediasize_iso_a1">ISO A1</string>
+ <string name="mediasize_iso_a2">ISO A2</string>
+ <string name="mediasize_iso_a3">ISO A3</string>
+ <string name="mediasize_iso_a4">ISO A4</string>
+ <string name="mediasize_iso_a5">ISO A5</string>
+ <string name="mediasize_iso_a6">ISO A6</string>
+ <string name="mediasize_iso_a7">ISO A7</string>
+ <string name="mediasize_iso_a8">ISO A8</string>
+ <string name="mediasize_iso_a9">ISO A9</string>
+ <string name="mediasize_iso_a10">ISO A10</string>
+ <string name="mediasize_iso_b0">ISO B0</string>
+ <string name="mediasize_iso_b1">ISO B1</string>
+ <string name="mediasize_iso_b2">ISO B2</string>
+ <string name="mediasize_iso_b3">ISO B3</string>
+ <string name="mediasize_iso_b4">ISO B4</string>
+ <string name="mediasize_iso_b5">ISO B5</string>
+ <string name="mediasize_iso_b6">ISO B6</string>
+ <string name="mediasize_iso_b7">ISO B7</string>
+ <string name="mediasize_iso_b8">ISO B8</string>
+ <string name="mediasize_iso_b9">ISO B9</string>
+ <string name="mediasize_iso_b10">ISO B10</string>
+ <string name="mediasize_iso_c0">ISO C0</string>
+ <string name="mediasize_iso_c1">ISO C1</string>
+ <string name="mediasize_iso_c2">ISO C2</string>
+ <string name="mediasize_iso_c3">ISO C3</string>
+ <string name="mediasize_iso_c4">ISO C4</string>
+ <string name="mediasize_iso_c5">ISO C5</string>
+ <string name="mediasize_iso_c6">ISO C6</string>
+ <string name="mediasize_iso_c7">ISO C7</string>
+ <string name="mediasize_iso_c8">ISO C8</string>
+ <string name="mediasize_iso_c9">ISO C9</string>
+ <string name="mediasize_iso_c10">ISO C10</string>
+ <string name="mediasize_na_letter">Carta</string>
+ <string name="mediasize_na_gvrnmt_letter">Carta del gobiernu</string>
+ <string name="mediasize_na_legal">Llegal</string>
+ <string name="mediasize_na_junior_legal">Junior legal</string>
+ <string name="mediasize_na_ledger">Doble carta</string>
+ <string name="mediasize_na_tabloid">Tabloide</string>
+ <string name="mediasize_na_index_3x5">Index Card 3x5</string>
+ <string name="mediasize_na_index_4x6">Index Card 4x6</string>
+ <string name="mediasize_na_index_5x8">Index Card 5x8</string>
+ <string name="mediasize_na_monarch">Monarch</string>
+ <string name="mediasize_na_quarto">Quarto</string>
+ <string name="mediasize_na_foolscap">Foolscap</string>
+ <string name="mediasize_chinese_roc_8k">ROC 8K</string>
+ <string name="mediasize_chinese_roc_16k">ROC 16K</string>
+ <string name="mediasize_chinese_prc_1">PRC 1</string>
+ <string name="mediasize_chinese_prc_2">PRC 2</string>
+ <string name="mediasize_chinese_prc_3">PRC 3</string>
+ <string name="mediasize_chinese_prc_4">PRC 4</string>
+ <string name="mediasize_chinese_prc_5">PRC 5</string>
+ <string name="mediasize_chinese_prc_6">PRC 6</string>
+ <string name="mediasize_chinese_prc_7">PRC 7</string>
+ <string name="mediasize_chinese_prc_8">PRC 8</string>
+ <string name="mediasize_chinese_prc_9">PRC 9</string>
+ <string name="mediasize_chinese_prc_10">PRC 10</string>
+ <string name="mediasize_chinese_prc_16k">PRC 16K</string>
+ <string name="mediasize_chinese_om_pa_kai">Pa Kai</string>
+ <string name="mediasize_chinese_om_dai_pa_kai">Dai Pa Ka</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai">Jurro Ku Kai</string>
+ <string name="mediasize_japanese_jis_b10">JIS B10</string>
+ <string name="mediasize_japanese_jis_b9">JIS B9</string>
+ <string name="mediasize_japanese_jis_b8">JIS B8</string>
+ <string name="mediasize_japanese_jis_b7">JIS B7</string>
+ <string name="mediasize_japanese_jis_b6">JIS B6</string>
+ <string name="mediasize_japanese_jis_b5">JIS B5</string>
+ <string name="mediasize_japanese_jis_b4">JIS B4</string>
+ <string name="mediasize_japanese_jis_b3">JIS B3</string>
+ <string name="mediasize_japanese_jis_b2">JIS B2</string>
+ <string name="mediasize_japanese_jis_b1">JIS B1</string>
+ <string name="mediasize_japanese_jis_b0">JIS B0</string>
+ <string name="mediasize_japanese_jis_exec">JIS Exec</string>
+ <string name="mediasize_japanese_chou4">Chou4</string>
+ <string name="mediasize_japanese_chou3">Chou3</string>
+ <string name="mediasize_japanese_chou2">Chou2</string>
+ <string name="mediasize_japanese_hagaki">Hagaki</string>
+ <string name="mediasize_japanese_oufuku">Oufuku</string>
+ <string name="mediasize_japanese_kahu">Kahu</string>
+ <string name="mediasize_japanese_kaku2">Kaku2</string>
+ <string name="mediasize_japanese_you4">You4</string>
+ <string name="mediasize_unknown_portrait">Cualquier tamañu vertical</string>
+ <string name="mediasize_unknown_landscape">Cualquier tamañu horizontal</string>
+ <string name="write_fail_reason_cancelled">Encaboxáu</string>
+ <string name="write_fail_reason_cannot_write">Fallu al escribir conteníu</string>
+ <string name="reason_unknown">desconocíu</string>
+ <string name="reason_service_unavailable">Serviciu d\'impresión non habilitáu</string>
+ <string name="print_service_installed_title">Instalóse\'l serviciu <xliff:g id="NAME">%s</xliff:g></string>
+ <string name="print_service_installed_message">Tocar p\'habilitar</string>
+ <string name="restr_pin_enter_admin_pin">Introduz el PIN del alministrador</string>
+ <string name="restr_pin_enter_pin">Inxertar PIN</string>
+ <string name="restr_pin_incorrect">Incorreutu</string>
+ <string name="restr_pin_enter_old_pin">PIN actual</string>
+ <string name="restr_pin_enter_new_pin">PIN nuevu</string>
+ <string name="restr_pin_confirm_pin">Confirma\'l PIN nuevu</string>
+ <string name="restr_pin_create_pin">Crear PIN pa modificar restricciones</string>
+ <string name="restr_pin_error_doesnt_match">Los númberos PIN nun concasen. Vuelvi a intentalo.</string>
+ <string name="restr_pin_error_too_short">El PIN ye enforma curtiu. Tien de tener al menos 4 díxitos.</string>
+ <string name="restr_pin_try_later">Volver a intentalo dempués</string>
+ <string name="done_label">Fecho</string>
+ <string name="hour_picker_description">Control eslizante circular d\'hores</string>
+ <string name="minute_picker_description">Control eslizante circular de minutos</string>
+ <string name="select_hours">Seleicionar hores</string>
+ <string name="select_minutes">Seleicionar minutos</string>
+ <string name="select_day">Seleicionar mes y día</string>
+ <string name="select_year">Seleicionar añu</string>
+ <string name="deleted_key"><xliff:g id="key" example="4">%1$s</xliff:g> desaniciáu</string>
+ <string name="managed_profile_label_badge"><xliff:g id="label" example="Email">%1$s</xliff:g> de trabayu</string>
+ <string name="time_placeholder">--</string>
+ <string name="lock_to_app_toast">Pa desactivar esta pantalla, caltén primíos al empar los botones de retrocesu y Visión xeneral.</string>
+ <string name="lock_to_app_toast_accessible">Pa desactivar esta pantalla, caltén primíu\'l botón Visión xeneral.</string>
+ <string name="lock_to_app_start">Pantalla fixada</string>
+ <string name="lock_to_app_exit">Pantalla desfixada</string>
+ <string name="lock_to_app_unlock_pin">Solicitar PIN pa desactivar</string>
+ <string name="lock_to_app_unlock_pattern">Solicitar patrón de desbloquéu pa desactivar</string>
+ <string name="lock_to_app_unlock_password">Solicitar contraseña pa desactivar</string>
+ <string name="zen_mode_feature_name">Nun molestar</string>
+ <string name="floating_toolbar_open_overflow_description">Más opciones</string>
+</resources>
diff --git a/core/res/res/values-az-rAZ/cm_strings.xml b/core/res/res/values-az-rAZ/cm_strings.xml
new file mode 100644
index 0000000..cde10dc
--- /dev/null
+++ b/core/res/res/values-az-rAZ/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ekran şəkli</string>
+ <string name="permlab_receiveProtectedSms">qorunan SMS qəbul et</string>
+ <string name="permdesc_receiveProtectedSms">Tətbiqetməyə qorunan bir SMS qəbul etmə icazəsi verər.</string>
+ <string name="permlab_modifyProtectedSmsList">qorunan SMS siyahısını dəyişdir</string>
+ <string name="permdesc_modifyProtectedSmsList">Tətbiqetməyə qorunan SMS ünvan siyahısını dəyişdirmə icazəsi verər.</string>
+ <string name="permgrouplab_security">Təhlükəsizlik</string>
+ <string name="permgroupdesc_security">Cihaz təhlükəsizlik məlumatı ilə bağlı icazələr.</string>
+ <string name="permlab_readPhoneBlacklist">telefon qara siyahısını oxu</string>
+ <string name="permdesc_readPhoneBlacklist">Tətbiqetmənin gələn zəngləri və ya mesajları əngəllənmiş telefon nömrələri haqqında məlumat oxumasına icazə verər.</string>
+ <string name="permlab_changePhoneBlacklist">telefon qara siyahısını dəyişdir</string>
+ <string name="permdesc_changePhoneBlacklist">Tətbiqetmənin gələn zəngləri və ya mesajları əngəllənmiş telefon nömrələrini dəyişdirməsinə icazə verər.</string>
+ <string name="permlab_setKeyguardWallpaper">klaviatura divar kağızını tənzimlə</string>
+ <string name="permdesc_setKeyguardWallpaper">Tətbiqetmənin kilit ekranı divar kağızını dəyişdirməsinə icazə verər.</string>
+ <string name="global_action_reboot">Yenidən başlat</string>
+ <string name="global_action_current_user">Hazırki</string>
+ <string name="reboot_reboot">Yenidən başlat</string>
+ <string name="reboot_recovery">Bərpa rejimi (Recovery)</string>
+ <string name="reboot_bootloader">Önyükləyici (Bootloader)</string>
+ <string name="reboot_download">Endirmə rejimi</string>
+ <string name="reboot_soft">Proqram təminatını yenidən başlatma</string>
+ <string name="reboot_title">Yenidən başlat</string>
+ <string name="reboot_confirm" product="tablet">Planşetiniz yenidən başladılacaq.</string>
+ <string name="reboot_confirm" product="default">Telefonunuz yenidən başlayacaq.</string>
+ <string name="reboot_progress">Yenidən başladılır\u2026</string>
+ <string name="app_killed_message">Tətbiq sonlandırıldı</string>
+ <string name="adb_net_active_notification_title">Şəbəkə üzərindən ADB fəaldır</string>
+ <string name="adb_both_active_notification_title">USB &amp; şəbəkə üzərindən ADB fəaldır</string>
+ <string name="adb_active_generic_notification_message">Xəta ayırdetməni ləğv etmək üçün toxunun.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; şəbəkə</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Şəbəkə</string>
+ <string name="permlab_interceptPackageLaunch">tətbiqetmə başlatmanın qarşısını al</string>
+ <string name="stylus_app_not_installed">%s quraşdırılmayıb</string>
+ <string name="silent_mode_priority">Üstünlük</string>
+ <string name="silent_mode_none">Yoxdur</string>
+ <string name="subscription_change_disabled_wifi_ap">SIM abunəliyini dəyişmə ilə əlaqədar Wi-Fi internet paylaşma ləğv edildi</string>
+ <string name="notify_turn_wifi_off_title">Wi-Fi\'ı bağla</string>
+ <string name="permlab_changePrivacyGuardState">Gizlilik Qorumasını fəallaşdır ya da ləğv et</string>
+ <string name="permdesc_changePrivacyGuardState">Tətbiqetməyə başqa bir tətbiqetmənin Gizlilik Qorumasını işlədib işlədə bilməyəcəyini müəyyənləşdirmə imkanı verər. Əgər tətbiqetmə Gizlilik Qoruması ilə işləyərsə şəxslər, zəng qeydləri və ya mesajlar kimi şəxsi verilənlərə müraciət edə bilməyəcək.</string>
+ <string name="privacy_guard_notification">Gizlilik Qoruması fəaldır</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> şəxsi verilənlərə müraciət edə bilməyəcək</string>
+ <string name="privacy_guard_dialog_title">Gizlilik Qoruması</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> <xliff:g id="op">%2$s</xliff:g> icazəsindən istifadə etmək istəyir.</string>
+ <string name="permission_remember_choice">Seçimimi yadda saxla</string>
+ <string name="app_ops_access_camera">kameraya müraciət</string>
+ <string name="app_ops_access_location">olduğunuz yerə müraciət</string>
+ <string name="app_ops_access_notifications">bildirişləri oxu</string>
+ <string name="app_ops_activate_vpn">VPN aktivetmə</string>
+ <string name="app_ops_auto_start">açılanda başla</string>
+ <string name="app_ops_delete_call_log">zəng qeydini sil</string>
+ <string name="app_ops_delete_contacts">şəxsləri sil</string>
+ <string name="app_ops_delete_mms">MMS mesajlarını sil</string>
+ <string name="app_ops_delete_sms">SMS mesajlarını sil</string>
+ <string name="app_ops_draw_on_top">pəncərələri yuxarıda göstər</string>
+ <string name="app_ops_get_usage_stats">tətbiq istifadə statistikalarını al</string>
+ <string name="app_ops_keep_device_awake">cihazı oyanıq saxla</string>
+ <string name="app_ops_make_phone_call">telefon zəngi edin</string>
+ <string name="app_ops_modify_calendar">təqvimi yenilə</string>
+ <string name="app_ops_modify_call_log">zəng qeydini yenilə</string>
+ <string name="app_ops_modify_clipboard">lövhəni dəyiş</string>
+ <string name="app_ops_modify_contacts">şəxsləri yenilə</string>
+ <string name="app_ops_modify_settings">sistem tənzimləmələrini yenilə</string>
+ <string name="app_ops_mute_unmute_microphone">mikrofonu aç/bağla</string>
+ <string name="app_ops_play_audio">səs çal</string>
+ <string name="app_ops_post_notification">bildiriş göndər</string>
+ <string name="app_ops_project_media">medianı əks etdir</string>
+ <string name="app_ops_read_calendar">təqvimi oxu</string>
+ <string name="app_ops_read_call_log">zəng qeydini oxu</string>
+ <string name="app_ops_read_clipboard">lövhəni</string>
+ <string name="app_ops_read_contacts">şəxsləri oxu</string>
+ <string name="app_ops_read_mms">MMS mesajlarını oxu</string>
+ <string name="app_ops_read_sms">SMS mesajlarını oxu</string>
+ <string name="app_ops_receive_sms">SMS mesajı qəbul et</string>
+ <string name="app_ops_record_audio">səs yaz</string>
+ <string name="app_ops_send_mms">MMS mesajı göndər</string>
+ <string name="app_ops_send_sms">SMS mesajı göndər</string>
+ <string name="app_ops_start_at_bootup">açılanda başla</string>
+ <string name="app_ops_toast_window">bildiriş mesajlarını göstər</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth açıb bağla</string>
+ <string name="app_ops_toggle_nfc">NFC aç bağla</string>
+ <string name="app_ops_use_alarm_volume">zəngli saat səsinin idarəsi</string>
+ <string name="app_ops_use_audio_focus">səs fokunusuna nəzarət</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetooth səsinə nəzarət</string>
+ <string name="app_ops_use_master_volume">əsas səs səviyyəsinə nəzarət</string>
+ <string name="app_ops_use_media_buttons">media düymələrindən istifadə et</string>
+ <string name="app_ops_use_media_volume">media səsinə nəzarət</string>
+ <string name="app_ops_use_notification_volume">bildiriş səsinə nəzarət</string>
+ <string name="app_ops_use_ring_volume">zəng səsini idarə et</string>
+ <string name="app_ops_use_vibrate">sensor geri bildirişdən istifadə et</string>
+ <string name="app_ops_use_voice_volume">səsli zəng səviyyəsinə nəzarət</string>
+ <string name="app_ops_write_mms">MMS mesajı yazın</string>
+ <string name="app_ops_write_sms">SMS mesajı yazın</string>
+ <string name="app_ops_su">root müraciəti əldə et</string>
+ <string name="lock_to_app_toast_no_navbar">Bu ekranı çıxarmaq üçün Geri düyməsinə toxunub basılı tutun.</string>
+ <string name="live_display_auto">Avtomatik</string>
+ <string name="live_display_auto_summary">Gün çıxandan və batandan sonra ekranın rəng hərarətini avtomatik tənzimləyər</string>
+ <string name="live_display_off">Bağlı</string>
+ <string name="live_display_off_summary">Bütün tənzimləmələri ləğv et</string>
+ <string name="live_display_day">Gündüz</string>
+ <string name="live_display_day_summary">Yalnız gündüz tənziml. istifadə et</string>
+ <string name="live_display_night">Gecə</string>
+ <string name="live_display_night_summary">Yalnız gecə tənziml. istifadə et</string>
+ <string name="live_display_outdoor">Açıq hava (parlaq günəş)</string>
+ <string name="live_display_outdoor_summary">Yalnız açıq hava tənziml. istifadə et</string>
+ <string name="live_display_hint">LiveDisplay göz yorğunluğunuzu azaldıb gecələri yuxulamağınıza kömək edə bilər. Yoxlamaq üçün bura klikləyin!</string>
+ <string name="tethered_notification_no_device_message">Bağlı cihaz yoxdur</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> cihaz bağlıdır</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> cihaz bağlıdır</string>
+</resources>
diff --git a/core/res/res/values-be/cm_strings.xml b/core/res/res/values-be/cm_strings.xml
new file mode 100644
index 0000000..0c83b38
--- /dev/null
+++ b/core/res/res/values-be/cm_strings.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Здымак экрану</string>
+ <string name="permlab_receiveProtectedSms">атрыманне абароненых SMS</string>
+ <string name="permdesc_receiveProtectedSms">Дазваляе праграме атрымліваць абароненыя SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">мадыфікацыя спісу абароненых SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Дадатак зможа змяняць спіс адрасатаў абароненых SMS-паведамленняў.</string>
+ <string name="permgrouplab_security">Бяспека</string>
+ <string name="permgroupdesc_security">Дазволы, што адносяцца да бяспекі дадзеных на прыладзе.</string>
+ <string name="permlab_readPhoneBlacklist">прагляд чорнага спісу</string>
+ <string name="permdesc_readPhoneBlacklist">Дазваляе праграме праглядаць звесткі пра нумары тэлефонаў, ад якіх заблакаваны тэлефанаванні ці паведамленні.</string>
+ <string name="permlab_changePhoneBlacklist">мадыфікацыя чорнага спісу</string>
+ <string name="permdesc_changePhoneBlacklist">Дазваляе праграме ўносіць змены ў спіс нумароў тэлефонаў, ад якіх заблакаваны тэлефанаванні ці паведамленні.</string>
+ <string name="permlab_setKeyguardWallpaper">усталёўка шпалераў экрану блакавання</string>
+ <string name="permdesc_setKeyguardWallpaper">Дазваляе праграме змяняць шпалеры экрану блакавання.</string>
+ <string name="global_action_reboot">Перазагрузіць</string>
+ <string name="global_action_current_user">Бягучы</string>
+ <string name="reboot_reboot">Перазагрузіць</string>
+ <string name="reboot_recovery">Рэжым аднаўлення</string>
+ <string name="reboot_bootloader">Загрузчык</string>
+ <string name="reboot_download">Спампоўкі</string>
+ <string name="reboot_soft">Перазапуск інтэрфейсу</string>
+ <string name="reboot_title">Перазагрузіць</string>
+ <string name="reboot_confirm" product="tablet">Ваш планшэт будзе перазапушчаны.</string>
+ <string name="reboot_confirm" product="default">Ваш тэлефон будзе перазапушчаны.</string>
+ <string name="reboot_progress">Перазапуск\u2026</string>
+ <string name="app_killed_message">Дадатак зачынены</string>
+ <string name="adb_net_active_notification_title">ADB праз сетку ўключана</string>
+ <string name="adb_both_active_notification_title">ADB праз USB &amp; сетку ўключана</string>
+ <string name="adb_active_generic_notification_message">Націснуць для выключэння наладкі.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">па сетцы &amp; USB</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Па сетцы</string>
+ <string name="permlab_interceptPackageLaunch">Перахоп запуску дадаткаў</string>
+ <string name="stylus_app_not_installed">%s не ўсталявана</string>
+ <string name="silent_mode_priority">Важныя</string>
+ <string name="silent_mode_none">Не</string>
+ <string name="subscription_change_disabled_wifi_ap">Выключаныя Wi-Fi кропкі доступу ў сувязі са зменай падпіскі SIM</string>
+ <string name="notify_turn_wifi_off_title">Вымкнуць Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">уключэнне ці выключэнне рэжыму абароны прыватнасці</string>
+ <string name="permdesc_changePrivacyGuardState">Дазваляе праграме выбіраць, ці будзе іншая праграма працаваць у рэжыме абароны прыватнасці. Калі праграма запушчана ў рэжыме абароны прыватнасці, яна не будзе мець доступу да асабістых дадзеных, такіх як кантакты, паведамленні ці гісторыя тэлефанаванняў.</string>
+ <string name="privacy_guard_notification">Рэжым абароны прыватнасці актыўны</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> не будзе мець доступу да асабістых дадзеных</string>
+ <string name="privacy_guard_dialog_title">Рэжым абароны</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> жадае <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Запамятаць вырашэнне</string>
+ <string name="app_ops_access_camera">атрымаць доступ да камеры</string>
+ <string name="app_ops_access_location">атрымаць доступ да месцазнаходжання прылады</string>
+ <string name="app_ops_access_notifications">атрымаць доступ да апавяшчэнняў</string>
+ <string name="app_ops_activate_vpn">актываваць VPN</string>
+ <string name="app_ops_auto_start">прызначыць запуск пры ўлучэнні прылады</string>
+ <string name="app_ops_delete_call_log">выдаліць часопіс званкоў</string>
+ <string name="app_ops_delete_contacts">выдаліць кантакты</string>
+ <string name="app_ops_delete_mms">выдаліць MMS-паведамленні</string>
+ <string name="app_ops_delete_sms">выдаліць SMS-паведамленні</string>
+ <string name="app_ops_draw_on_top">адлюстроўваць элементы інтэрфейсу па-над іншымі вокнамі</string>
+ <string name="app_ops_get_usage_stats">атрымаць статыстыку выкарыстання дадаткаў</string>
+ <string name="app_ops_keep_device_awake">забараніць прыладзе пераходзіць да рэжыму сну</string>
+ <string name="app_ops_make_phone_call">выканаць тэлефонны званок</string>
+ <string name="app_ops_modify_calendar">змяніць дадзеныя каляндара</string>
+ <string name="app_ops_modify_call_log">змяніць дадзеныя часопіса званкоў</string>
+ <string name="app_ops_modify_clipboard">змяніць змесціва буфера абмену</string>
+ <string name="app_ops_modify_contacts">змяніць дадзеныя кантактаў</string>
+ <string name="app_ops_modify_settings">змяніць сістэмныя параметры</string>
+ <string name="app_ops_mute_unmute_microphone">выключыць ці ўключыць мікрафон</string>
+ <string name="app_ops_play_audio">прайграванне аўдыя</string>
+ <string name="app_ops_post_notification">вывесці паведамленне</string>
+ <string name="app_ops_project_media">выканаць трансляцыю кантэнту</string>
+ <string name="app_ops_read_calendar">прачытаць дадзеныя каляндара</string>
+ <string name="app_ops_read_call_log">прачытаць дадзеныя спіса выклікаў</string>
+ <string name="app_ops_read_clipboard">прачытаць змесціва буфера абмену</string>
+ <string name="app_ops_read_contacts">прачытаць дадзеныя кантактаў</string>
+ <string name="app_ops_read_mms">прачытаць MMS-паведамленні</string>
+ <string name="app_ops_read_sms">прачытаць SMS-паведамленні</string>
+ <string name="app_ops_receive_sms">атрымаць SMS-паведамленне</string>
+ <string name="app_ops_record_audio">запіс аўдыя</string>
+ <string name="app_ops_send_mms">даслать MMS-паведамленне</string>
+ <string name="app_ops_send_sms">даслать SMS-паведамленне</string>
+ <string name="app_ops_start_at_bootup">прызначыць запуск пры ўлучэнні прылады</string>
+ <string name="app_ops_toast_window">адлюстроўваць усплывальныя паведамленні</string>
+ <string name="app_ops_toggle_bluetooth">пераключыць стан Bluetooth</string>
+ <string name="app_ops_toggle_nfc">пераключыць стан модуля NFC</string>
+ <string name="app_ops_toggle_wifi">пераключыць стан Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">атрымаць кіраванне гучнасцю будзільніка</string>
+ <string name="app_ops_use_audio_focus">атрымаць кіраванне аўдыя фокусам</string>
+ <string name="app_ops_use_bluetooth_volume">атрымаць кіраванне гучнасцю Bluetooth-прылад</string>
+ <string name="app_ops_use_master_volume">атрымаць кіраванне агульнай гучнасцю</string>
+ <string name="app_ops_use_media_buttons">выкарыстоўваць кнопкі мультымедыя</string>
+ <string name="app_ops_use_media_volume">атрымаць кіраванне гучнасцю мультымедыя</string>
+ <string name="app_ops_use_notification_volume">кіраванне гучнасцю паведамленняў</string>
+ <string name="app_ops_use_ring_volume">кіраванне гучнасцю званка</string>
+ <string name="app_ops_use_vibrate">выкарыстоўваць вібраводгук</string>
+ <string name="app_ops_use_voice_volume">атрымаць кіраванне гучнасцю пры гутарцы</string>
+ <string name="app_ops_write_mms">стварыць MMS-паведамленне</string>
+ <string name="app_ops_write_sms">стварыць SMS-паведамленне</string>
+ <string name="app_ops_use_fingerprint">Выкарыстанне адбіткаў пальцаў</string>
+ <string name="app_ops_add_voicemail">Дадаць галасавое паведамленне</string>
+ <string name="app_ops_read_phone_state">атрыманне стану тэлефона</string>
+ <string name="app_ops_scan_wifi">Сканаваць сеткі Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">змена шпалер</string>
+ <string name="app_ops_assist_structure">Выкарыстоўваць структуру падтрымкі</string>
+ <string name="app_ops_assist_screenshot">зрабіць скрыншот</string>
+ <string name="app_ops_use_body_sensors">Выкарыстоўваць датчыкі</string>
+ <string name="app_ops_read_cell_broadcasts">Шырокаапавяшчальныя паведамленні</string>
+ <string name="app_ops_mock_location">Фіктыўнае месцазнаходжанне</string>
+ <string name="app_ops_read_external_storage">чытанне дадзеных</string>
+ <string name="app_ops_write_external_storage">захоўваць дадзеныя на картку памяці</string>
+ <string name="app_ops_turn_on_screen">улучэнне экрану</string>
+ <string name="app_ops_get_accounts">атрымаць інфармацыю карыстальнікаў</string>
+ <string name="app_ops_wifi_change">Змяніць стан Wi-Fi</string>
+ <string name="app_ops_su">атрымаць правы суперкарыстальніка</string>
+ <string name="lock_to_app_toast_no_navbar">Каб адмацаваць экран, націсніце і ўтрымвайце кнопку \"Назад\".</string>
+ <string name="live_display_auto">Аўтаматычна</string>
+ <string name="live_display_auto_summary">Аўтаматычная падладка колеравай тэмпературы экрана пасля заходу і ўзыходу сонца</string>
+ <string name="live_display_off">Адключыць</string>
+ <string name="live_display_off_summary">Адключыць аўтападладку</string>
+ <string name="live_display_day">Дзень</string>
+ <string name="live_display_day_summary">Толькі дзённыя налады</string>
+ <string name="live_display_night">Ноч</string>
+ <string name="live_display_night_summary">Толькі начныя налады</string>
+ <string name="live_display_outdoor">На вуліцы (яскравае сонца)</string>
+ <string name="live_display_outdoor_summary">Толькі вулічны рэжым</string>
+ <string name="live_display_hint">LiveDisplay дапаможа зменшыць глядзельную напругу і палепшыць сон. Націсніце тут, каб паспрабаваць!</string>
+ <string name="tethered_notification_no_device_message">Няма падлучаных прылад</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> падлучаная прылада</string>
+ <string name="tethered_notification_multi_device_message">Падлучана прылад: <xliff:g id="count">%1$s</xliff:g></string>
+ <string name="notify_package_component_protected_title">Запуск дадатку забаронены</string>
+ <string name="notify_package_component_protected_text">Дадатак <xliff:g id="app_name">%1$s</xliff:g> заблакаваны на запуск. Націсні, каб увесці паролль і запусціць дадатак.</string>
+</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
new file mode 100644
index 0000000..4bbe54a
--- /dev/null
+++ b/core/res/res/values-be/strings.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="byteShort">Б</string>
+ <string name="kilobyteShort">КБ</string>
+ <string name="megabyteShort">МБ</string>
+ <string name="gigabyteShort">ГБ</string>
+ <string name="terabyteShort">TБ</string>
+ <string name="petabyteShort">ПБ</string>
+ <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g><xliff:g id="unit" example="KB">%2$s</xliff:g></string>
+ <string name="passwordIncorrect">Памылковы пароль.</string>
+ <string name="mmiComplete">Запыт MMI завершаны.</string>
+ <string name="badPuk">Уведзены памылковы PUK-код.</string>
+ <string name="invalidPin">Увядзіце PIN-код (ад 4 да 8 лічбаў).</string>
+ <string name="invalidPuk">Увядзіце PUK-код з 8 лічбаў ці больш.</string>
+ <string name="needPuk2">Для разблакавання SIM-карткі увядзіце код PUK2.</string>
+ <plurals name="pinpuk_attempts">
+ <item quantity="one">У вас засталася <xliff:g id="number">%d</xliff:g> спроба перад тым, як SIM-картка будзе заблакавана.</item>
+ <item quantity="few">У вас засталася <xliff:g id="number">%d</xliff:g> спробы перад тым, як SIM-картка будзе заблакавана.</item>
+ <item quantity="other">У вас засталася <xliff:g id="number">%d</xliff:g> спробы перад тым, як SIM-картка будзе заблакавана.</item>
+ </plurals>
+ <string name="BaMmi">Забарона выклікаў</string>
+ <string name="wfcRegErrorTitle">Wi-Fi выклік</string>
+ <string name="wfcSpnFormat">%s</string>
+ <string name="wfcDataSpnFormat">%s</string>
+ <string name="wifi_calling_off_summary">Адключана</string>
+ <string name="wfc_mode_wifi_preferred_summary">Wi-Fi пераважна</string>
+ <string name="wfc_mode_cellular_preferred_summary">Сотавы пераважна</string>
+ <string name="wfc_mode_wifi_only_summary">толькі Wi-Fi</string>
+ <string name="global_action_lockdown">Блакаваць зараз</string>
+ <string name="permdesc_sim_communication">Дазваляе праграме дасылаць каманды да SIM-карткі. Гэта вельмі небяспечна.</string>
+ <string name="permlab_transmitIr">выкарыстанне інфрачырвонай перадачы</string>
+ <string name="permdesc_transmitIr" product="tablet">Дазваляе праграме выкарыстоўваць інфрачырвоны перадатчык планшэту.</string>
+ <string name="permdesc_transmitIr" product="default">Дазваляе праграме выкарыстоўваць інфрачырвоны перадатчык тэлефону.</string>
+ <string name="cancel">Скасаваць</string>
+ <string name="no">Скасаваць</string>
+ <string name="capital_on">УКЛ</string>
+ <string name="capital_off">ВЫКЛ</string>
+ <string name="sms_short_code_confirm_deny">Скасаваць</string>
+ <string name="keyboardview_keycode_cancel">Скасаваць</string>
+ <string name="error_message_change_not_allowed">Гэтае дзеянне забаронена адміністратарам</string>
+ <string name="mediasize_iso_a0">ISO A0 (841х1189 мм)</string>
+ <string name="mediasize_iso_a1">ISO A1 (594х841 мм)</string>
+ <string name="mediasize_iso_a2">ISO A2 (420х594 мм)</string>
+ <string name="mediasize_iso_a3">ISO A3 (297х420 мм)</string>
+ <string name="mediasize_iso_a4">ISO A4 (210x297 мм)</string>
+ <string name="mediasize_iso_a5">ISO A5 (148x210 мм)</string>
+ <string name="mediasize_iso_a6">ISO A6 (105x148 мм)</string>
+ <string name="mediasize_iso_a7">ISO A7 (74x105 мм)</string>
+ <string name="mediasize_iso_a8">ISO A8 (52x74 мм)</string>
+ <string name="mediasize_iso_a9">ISO A9 (37x52 мм)</string>
+ <string name="mediasize_iso_a10">ISO A10 (26x37 мм)</string>
+ <string name="mediasize_iso_b0">ISO B0 (1000x1414 мм)</string>
+ <string name="mediasize_iso_b1">ISO B1 (707x1000 мм)</string>
+ <string name="mediasize_iso_b2">ISO B2 (500x707 мм)</string>
+ <string name="mediasize_iso_b3">ISO B3 (353x500 мм)</string>
+ <string name="mediasize_iso_b4">ISO B4 (250x353 мм)</string>
+ <string name="mediasize_iso_b5">ISO B5 (176x250 мм)</string>
+ <string name="mediasize_iso_b6">ISO B6 (125x176 мм)</string>
+ <string name="mediasize_iso_b7">ISO B7 (88x125 мм)</string>
+ <string name="mediasize_iso_b8">ISO B8 (62x88 мм)</string>
+ <string name="mediasize_iso_b9">ISO B9 (44x62 мм)</string>
+ <string name="mediasize_iso_b10">ISO B10 (31x44 мм)</string>
+ <string name="mediasize_iso_c0">ISO C0 (917x1297 мм)</string>
+ <string name="mediasize_iso_c1">ISO C1 (648x917 мм)</string>
+ <string name="mediasize_iso_c2">ISO C2 (458x648 мм)</string>
+ <string name="mediasize_iso_c3">ISO C3 (324x458 мм)</string>
+ <string name="mediasize_iso_c4">ISO C4 (229x324 мм)</string>
+ <string name="mediasize_iso_c5">ISO C5 (162x229 мм)</string>
+ <string name="mediasize_iso_c6">ISO C6 (114x162 мм)</string>
+ <string name="mediasize_iso_c7">ISO C7 (81x114 мм)</string>
+ <string name="mediasize_iso_c8">ISO C8 (57x81 мм)</string>
+ <string name="mediasize_iso_c9">ISO C9 (40x57 мм)</string>
+ <string name="mediasize_iso_c10">ISO C10 (28x40 мм)</string>
+ <string name="mediasize_na_letter">Letter (216x279 мм)</string>
+ <string name="mediasize_na_gvrnmt_letter">Government Letter (203x267 мм)</string>
+ <string name="mediasize_na_legal">Legal (216x356 мм)</string>
+ <string name="mediasize_na_junior_legal">Junior Legal (203x127 мм)</string>
+ <string name="mediasize_na_ledger">Ledger (432x279 мм)</string>
+ <string name="mediasize_na_tabloid">Tabloid (279x432 мм)</string>
+ <string name="mediasize_na_index_3x5">Index Card 3x5 (76x127 мм)</string>
+ <string name="mediasize_na_index_4x6">Index Card 4x6 (102x152 мм)</string>
+ <string name="mediasize_na_index_5x8">Index Card 5x8 (127x203 мм)</string>
+ <string name="mediasize_na_monarch">Monarch (184x267 мм)</string>
+ <string name="mediasize_na_quarto">Quarto (203x254 мм)</string>
+ <string name="mediasize_na_foolscap">Foolscap (203x330 мм)</string>
+ <string name="mediasize_chinese_roc_8k">ROC 8K (270x390 мм)</string>
+ <string name="mediasize_chinese_roc_16k">ROC 16K (195x270 мм)</string>
+ <string name="mediasize_chinese_prc_1">PRC 1 (102x165 мм)</string>
+ <string name="mediasize_chinese_prc_2">PRC 2 (102x176 мм)</string>
+ <string name="mediasize_chinese_prc_3">PRC 3 (125x176 мм)</string>
+ <string name="mediasize_chinese_prc_4">PRC 4 (110x208 мм)</string>
+ <string name="mediasize_chinese_prc_5">PRC 5 (110x220 мм)</string>
+ <string name="mediasize_chinese_prc_6">PRC 6 (120x320 мм)</string>
+ <string name="mediasize_chinese_prc_7">PRC 7 (160x230 мм)</string>
+ <string name="mediasize_chinese_prc_8">PRC 8 (120x309 мм)</string>
+ <string name="mediasize_chinese_prc_9">PRC 9 (229x324 мм)</string>
+ <string name="mediasize_chinese_prc_10">PRC 10 (324x458 мм)</string>
+ <string name="mediasize_chinese_prc_16k">PRC 16K (146x215 мм)</string>
+ <string name="mediasize_chinese_om_pa_kai">Pa Kai (146x215 мм)</string>
+ <string name="mediasize_chinese_om_dai_pa_kai">Dai Pa Kai (275x395 мм)</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai">Jurro Ku Kai (275x395 мм)</string>
+ <string name="mediasize_japanese_jis_b10">JIS B10 (32x45 мм)</string>
+ <string name="mediasize_japanese_jis_b9">JIS B9 (45x64 мм)</string>
+ <string name="mediasize_japanese_jis_b8">JIS B8 (64x91 мм)</string>
+ <string name="mediasize_japanese_jis_b7">JIS B7 (91x128 мм)</string>
+ <string name="mediasize_japanese_jis_b6">JIS B6 (128x182 мм)</string>
+ <string name="mediasize_japanese_jis_b5">JIS B5 (182x257 мм)</string>
+ <string name="mediasize_japanese_jis_b4">JIS B4 (257x364 мм)</string>
+ <string name="mediasize_japanese_jis_b3">JIS B3 (364x515 мм)</string>
+ <string name="mediasize_japanese_jis_b2">JIS B2 (515x728 мм)</string>
+ <string name="mediasize_japanese_jis_b1">JIS B1 (728x1030 мм)</string>
+ <string name="mediasize_japanese_jis_b0">JIS B0 (1030x1456 мм)</string>
+ <string name="mediasize_japanese_jis_exec">JIS Exec (216x330 мм)</string>
+ <string name="mediasize_japanese_chou4">Chou4 (90x205 мм)</string>
+ <string name="mediasize_japanese_chou3">Chou3 (120x235 мм)</string>
+ <string name="mediasize_japanese_chou2">Chou2 (111,1x146 мм)</string>
+ <string name="mediasize_japanese_hagaki">Hagaki (100x148 мм)</string>
+ <string name="mediasize_japanese_oufuku">Oufuku (148x200 мм)</string>
+ <string name="mediasize_japanese_kahu">Kaku (240x322,1 мм)</string>
+ <string name="mediasize_japanese_kaku2">Kaku2 (240x332 мм)</string>
+ <string name="mediasize_japanese_you4">You4 (105x235 мм)</string>
+ <string name="write_fail_reason_cancelled">Скасавана</string>
+</resources>
diff --git a/core/res/res/values-bg/cm_strings.xml b/core/res/res/values-bg/cm_strings.xml
new file mode 100644
index 0000000..384826d
--- /dev/null
+++ b/core/res/res/values-bg/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Снимка на екрана</string>
+ <string name="permlab_receiveProtectedSms">приемай защитени SMS</string>
+ <string name="permdesc_receiveProtectedSms">Разрешава на приложението да приема входящи защитени SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">Модифициране на списъка със защитени SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Разрешава на приложението да модифицира списъка с контакти на защитените SMS.</string>
+ <string name="permgrouplab_security">Сигурност</string>
+ <string name="permgroupdesc_security">Разрешения, свързани с информацията за защита на устройството.</string>
+ <string name="permlab_readPhoneBlacklist">Прочетете списъка с блокирани контакти</string>
+ <string name="permdesc_readPhoneBlacklist">Разрешава на приложението да прочетете информацията за телефонни номера, които са блокирани за входящи повиквания или съобщения.</string>
+ <string name="permlab_changePhoneBlacklist">Промяна на списъка с блокирани контакти</string>
+ <string name="permdesc_changePhoneBlacklist">Разрешава на приложението да промени телефонните номера, които са блокирани за входящи повиквания или съобщения.</string>
+ <string name="permlab_setKeyguardWallpaper">Задаване на тапет за заключен екран</string>
+ <string name="permdesc_setKeyguardWallpaper">Разрешава на едно приложение да променя тапета на заключения екран.</string>
+ <string name="global_action_reboot">Рестартиране</string>
+ <string name="global_action_current_user">Текущ</string>
+ <string name="reboot_reboot">Рестартиране</string>
+ <string name="reboot_recovery">Възстановяване</string>
+ <string name="reboot_bootloader">Буутлоудър</string>
+ <string name="reboot_download">Изтегляне</string>
+ <string name="reboot_soft">Бързо рестартиране</string>
+ <string name="reboot_title">Рестартиране</string>
+ <string name="reboot_confirm" product="tablet">Таблетът ще се рестартира.</string>
+ <string name="reboot_confirm" product="default">Телефонът ще се рестартира.</string>
+ <string name="reboot_progress">Рестартиране\u2026</string>
+ <string name="app_killed_message">Затворено приложение</string>
+ <string name="adb_net_active_notification_title">ADB над мрежата е активиран</string>
+ <string name="adb_both_active_notification_title">ADB над USB &amp; мрежата е активирана</string>
+ <string name="adb_active_generic_notification_message">Докоснете за да деактивирате отстраняване на грешки.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s </xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; мрежа</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Мрежа</string>
+ <string name="permlab_interceptPackageLaunch">Прихвани стартиращите приложения</string>
+ <string name="stylus_app_not_installed">%s не е инсталиран</string>
+ <string name="silent_mode_priority">Приоритет</string>
+ <string name="silent_mode_none">Без</string>
+ <string name="subscription_change_disabled_wifi_ap">Изключена Wi-Fi точка за достъп, поради промяна в абонаментна на СИМ</string>
+ <string name="notify_turn_wifi_off_title">Изключете Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">Активира или деактивира Защитен режим</string>
+ <string name="permdesc_changePrivacyGuardState">Разрешава на приложението да променя статута на поверителност на друго приложение. Когато едно приложение се използва с защита на поверителността, не може да има достъп до персонални данни, като контакти, регистри с повиквания или съобщения.</string>
+ <string name="privacy_guard_notification">Защитен режим e активен</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s </xliff:g> няма да можете да получите достъп до лични данни</string>
+ <string name="privacy_guard_dialog_title">Защитен режим</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s </xliff:g> бих искал да <xliff:g id="op">%2$s </xliff:g>.</string>
+ <string name="permission_remember_choice">Запомни избора ми</string>
+ <string name="app_ops_access_camera">достъп до камерата</string>
+ <string name="app_ops_access_location">достъп до вашето местоположение</string>
+ <string name="app_ops_access_notifications">прочети своите известия</string>
+ <string name="app_ops_activate_vpn">активиране на VPN</string>
+ <string name="app_ops_auto_start">изпълнение при включване</string>
+ <string name="app_ops_delete_call_log">изтриване на дневника за повиквания</string>
+ <string name="app_ops_delete_contacts">Изтриване на контакти</string>
+ <string name="app_ops_delete_mms">Изтриване на MMS съобщенията</string>
+ <string name="app_ops_delete_sms">Изтриване на SMS съобщенията</string>
+ <string name="app_ops_draw_on_top">Издърпай прозореца на най-отгоре</string>
+ <string name="app_ops_get_usage_stats">Вземи статистика за използването на приложението</string>
+ <string name="app_ops_keep_device_awake">Задръж устройството будно</string>
+ <string name="app_ops_make_phone_call">осъществете телефонно повикване</string>
+ <string name="app_ops_modify_calendar">актуализиране на вашият календар</string>
+ <string name="app_ops_modify_call_log">актуализация на дневника за повиквания</string>
+ <string name="app_ops_modify_clipboard">промяна на клипборда</string>
+ <string name="app_ops_modify_contacts">актуализиране на вашите контакти</string>
+ <string name="app_ops_modify_settings">актуализиране на системните настройки</string>
+ <string name="app_ops_mute_unmute_microphone">изключи/включи микрофона</string>
+ <string name="app_ops_play_audio">изпълнение на аудио</string>
+ <string name="app_ops_post_notification">публикувай уведомление</string>
+ <string name="app_ops_project_media">медиен проект</string>
+ <string name="app_ops_read_calendar">прегледай календара</string>
+ <string name="app_ops_read_call_log">прегледай повикванията</string>
+ <string name="app_ops_read_clipboard">прегледай клипборда</string>
+ <string name="app_ops_read_contacts">прегледай контактите</string>
+ <string name="app_ops_read_mms">прегледай MMS съобщенията</string>
+ <string name="app_ops_read_sms">прегледай SMS съобщенията</string>
+ <string name="app_ops_receive_sms">получихте SMS съобщение</string>
+ <string name="app_ops_record_audio">записване на звук</string>
+ <string name="app_ops_send_mms">Изпращане на MMS съобщение</string>
+ <string name="app_ops_send_sms">Изпращане на SMS съобщение</string>
+ <string name="app_ops_start_at_bootup">изпълнение при включване</string>
+ <string name="app_ops_toast_window">показвай изкачащи уведомления</string>
+ <string name="app_ops_toggle_bluetooth">активиране/деактивиране Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">Превключване клетъчен данни</string>
+ <string name="app_ops_toggle_nfc">активиране/деактивиране NFC</string>
+ <string name="app_ops_toggle_wifi">активирай/деактивирай Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">контрол на силата на алармата</string>
+ <string name="app_ops_use_audio_focus">контрол на силата на звука</string>
+ <string name="app_ops_use_bluetooth_volume">контрол на силата на Bluetooth</string>
+ <string name="app_ops_use_master_volume">главен контрол на звука</string>
+ <string name="app_ops_use_media_buttons">Използвайте мултимедийните бутони</string>
+ <string name="app_ops_use_media_volume">контрол на звука за мултимедия</string>
+ <string name="app_ops_use_notification_volume">контрол на звука за уведомления</string>
+ <string name="app_ops_use_ring_volume">контрол на звука при повикване</string>
+ <string name="app_ops_use_vibrate">Използвайте haptic feedback</string>
+ <string name="app_ops_use_voice_volume">контрол на звука при разговор</string>
+ <string name="app_ops_write_mms">Напишете MMS съобщение</string>
+ <string name="app_ops_write_sms">Напишете SMS съобщение</string>
+ <string name="app_ops_use_fingerprint">използвай пръстов отпечатък</string>
+ <string name="app_ops_add_voicemail">добави гласова поща</string>
+ <string name="app_ops_read_phone_state">достъп до състоянието на телефона</string>
+ <string name="app_ops_scan_wifi">сканирай за Wi-Fi мрежи</string>
+ <string name="app_ops_change_wallpaper">Смяна на тапета</string>
+ <string name="app_ops_assist_structure">Използвайте структура за подпомагане</string>
+ <string name="app_ops_assist_screenshot">снимай екрана</string>
+ <string name="app_ops_use_body_sensors">използвай сензорите за тяло</string>
+ <string name="app_ops_read_cell_broadcasts">регистрирай излъчването на антенна клетка</string>
+ <string name="app_ops_mock_location">симулиране на местоположение</string>
+ <string name="app_ops_read_external_storage">прочети външната памет</string>
+ <string name="app_ops_write_external_storage">пиши върху външната памет</string>
+ <string name="app_ops_turn_on_screen">включи екрана</string>
+ <string name="app_ops_get_accounts">изведи акаунти на устройството</string>
+ <string name="app_ops_wifi_change">променете състоянието на Wi-Fi</string>
+ <string name="app_ops_su">получете root достъп</string>
+ <string name="lock_to_app_toast_no_navbar">За да освободите този екран, докоснете и задръжте бутона назад.</string>
+ <string name="live_display_auto">Автоматичен</string>
+ <string name="live_display_auto_summary">Настройва автоматично температурата на цветовете на екрана след залез и изгрев</string>
+ <string name="live_display_off">Изключен</string>
+ <string name="live_display_off_summary">Деактивира всички корекции</string>
+ <string name="live_display_day">Дневен</string>
+ <string name="live_display_day_summary">Използва само дневните настройки</string>
+ <string name="live_display_night">Нощен</string>
+ <string name="live_display_night_summary">Използва само нощните настройки</string>
+ <string name="live_display_outdoor">На открито (ярко слънце)</string>
+ <string name="live_display_outdoor_summary">Използвай само настройките за открито</string>
+ <string name="live_display_hint">Използването на Адаптивен екран може да помогне за намаляване умората в очите през нощта. Докоснете тук, за да го изпробвате!</string>
+ <string name="tethered_notification_no_device_message">Няма свързано устройство</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> устройството е свързано</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s </xliff:g> устройствата са свързани</string>
+ <string name="notify_package_component_protected_title">Старта на приложението блокиран</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> е блокиран. Докосни за да потвърдиш старта на приложението.</string>
+ <string name="notify_battery_fully_charged_title">Батерията е напълно заредена</string>
+ <string name="notify_battery_fully_charged_text">Изключете зарядното устройството за да удължите живота на батерията.</string>
+</resources>
diff --git a/core/res/res/values-bn-rBD/cm_strings.xml b/core/res/res/values-bn-rBD/cm_strings.xml
new file mode 100644
index 0000000..dd7686b
--- /dev/null
+++ b/core/res/res/values-bn-rBD/cm_strings.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">স্ক্রীনসর্ট</string>
+ <string name="permlab_receiveProtectedSms">সুরক্ষিত এসএমএস গৃহীত হবে</string>
+ <string name="permdesc_receiveProtectedSms">একটি আগত সুরক্ষিত এসএমএস গ্রহণ করতে অ্যাপটিকে অনুমতি দিন।</string>
+ <string name="permlab_modifyProtectedSmsList">সংরক্ষিত এসএমএস তালিকা পরিবর্তন করতে সক্ষম</string>
+ <string name="permgrouplab_security">নিরাপত্তা</string>
+ <string name="permgroupdesc_security">ডিভাইসের নিরাপত্তা তথ্য সংক্রান্ত অনুমতি।</string>
+ <string name="permlab_readPhoneBlacklist">ফোনের নিষিদ্ধ তালিকা পড়ুন</string>
+ <string name="permdesc_readPhoneBlacklist">একটি অ্যাপকে অভিমুখী কল বা বার্তার জন্য অবরুদ্ধ ফোন নাম্বারের তথ্য পাঠের অনুমতি দিন।</string>
+ <string name="permlab_changePhoneBlacklist">ফোনের নিষিদ্ধ তালিকা পরিবর্তন করুন</string>
+ <string name="permdesc_changePhoneBlacklist">একটি অ্যাপকে অভিমুখী কল বা বার্তার জন্য অবরুদ্ধ ফোন নাম্বার পরিবর্তনের অনুমতি দিন।</string>
+ <string name="permlab_setKeyguardWallpaper">কীগার্ড ওয়ালপেপার নির্ধারণ</string>
+ <string name="permdesc_setKeyguardWallpaper">অ্যাপটিকে লক স্ক্রীন ওয়ালপেপার পরিবর্তনের অনুমতি দিন।</string>
+ <string name="global_action_reboot">পুনরায় চালু</string>
+ <string name="reboot_reboot">পুনরায় চালু</string>
+ <string name="reboot_recovery">পুনরুদ্ধার</string>
+ <string name="reboot_bootloader">বুটলোডার</string>
+ <string name="reboot_download">ডাউনলোড</string>
+ <string name="reboot_soft">দ্রুত পুনরায় চালু</string>
+ <string name="reboot_confirm" product="tablet">আপনার ট্যাবলেট পুনরায় চালু হবে।</string>
+ <string name="reboot_confirm" product="default">আপনার ফোন পুনরায় চালু হবে।</string>
+ <string name="reboot_progress">পুনরায় চালু হচ্ছে\u2026</string>
+ <string name="adb_net_active_notification_title">নেটওয়ার্কের উপর এডিবি সক্রিয়</string>
+ <string name="adb_both_active_notification_title">এডিবির উপর ইউএসবি &amp; নেটওয়ার্ক সক্রিয়</string>
+ <string name="adb_active_generic_notification_message">ডিবাগ নিষ্ক্রিয় করতে স্পর্শ করুন।</string>
+ <string name="silent_mode_priority">অগ্রাধিকার</string>
+ <string name="notify_turn_wifi_off_title">ওয়াইফাই বন্ধ করুন</string>
+ <string name="permlab_changePrivacyGuardState">গোপনীয়তা রক্ষাকারী সক্রিয় বা নিস্ক্রিয় করুন</string>
+ <string name="permdesc_changePrivacyGuardState">অ্যাপটি কে অন্য অ্যাপ পরিবর্তন করার অনুমতি দিন যা গোপনীয়তা রক্ষাকারী সঙ্গে চলমান। যখন একটি অ্যাপ গোপনীয়তা রক্ষাকারী সঙ্গে চলমান থাকে তখন এটি ব্যক্তিগত তথ্য ব্যাবহার করতে পারবে না, যেমন যোগাযোগ, কল লগ, বা বার্তা।</string>
+ <string name="privacy_guard_notification">গোপনীয়তা রক্ষাকারী সক্রিয়</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> ব্যাক্তিগত তথ্য ব্যাবহার করতে পারবেন না</string>
+ <string name="privacy_guard_dialog_title">গোপনীয়তা রক্ষাকারী</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> করতে চায় <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="app_ops_access_camera">ক্যামেরায় প্রবেশাধিকার</string>
+ <string name="app_ops_access_location">আপনার অবস্থানে প্রবেশাধিকার</string>
+ <string name="app_ops_access_notifications">আপনার নোটিফিকেশানস প্রবেশাধিকার</string>
+ <string name="app_ops_get_usage_stats">অ্যাপের সংস্থান তথ্যাদি পান</string>
+ <string name="app_ops_keep_device_awake">আপনার ডিভাইস জাগ্রত রাখা</string>
+ <string name="app_ops_make_phone_call">একটি ফোন কল করুন</string>
+ <string name="app_ops_modify_calendar">আপনার পঞ্জিকা হালনাগাদ করুন</string>
+ <string name="app_ops_modify_call_log">কল লগ হালনাগাদ করুন</string>
+ <string name="app_ops_modify_clipboard">ক্লিপবোর্ড রূপান্তর করুন</string>
+ <string name="app_ops_modify_contacts">আপনার যোগাযোগসমূহে হালনাগাদ করুন</string>
+ <string name="app_ops_modify_settings">সিস্টেম রুপান্তর নির্ধারণ হালনাগাদ করুন</string>
+ <string name="app_ops_play_audio">অডিও প্লে করুন</string>
+ <string name="app_ops_post_notification">একটি নোটিফিকেশান পোস্ট</string>
+ <string name="app_ops_read_calendar">আপনার পঞ্জিকায় প্রবেশাধিকার</string>
+ <string name="app_ops_read_call_log">কল লগ এ প্রবেশাধিকার</string>
+ <string name="app_ops_read_clipboard">ক্লিপবোর্ড এ প্রবেশাধিকার</string>
+ <string name="app_ops_read_contacts">যোগাযোগসমূহে প্রবেশাধিকার</string>
+ <string name="app_ops_read_mms">এমএমএস বার্তায় প্রবেশাধিকার</string>
+ <string name="app_ops_read_sms">এমএমএস বার্তায় প্রবেশাধিকার</string>
+ <string name="app_ops_receive_sms">একটি এসএমএস বার্তা গ্রহণ</string>
+ <string name="app_ops_record_audio">অডিও রেকর্ড</string>
+ <string name="app_ops_send_mms">এমএমএস বার্তা প্রেরণ</string>
+ <string name="app_ops_send_sms">এসএমএস বার্তা প্রেরণ</string>
+ <string name="app_ops_start_at_bootup">শক্তি প্রাপ্তি থেকে আরম্ভ</string>
+ <string name="app_ops_toggle_bluetooth">ব্লু-টুথ টগল</string>
+ <string name="app_ops_toggle_nfc">এনএফসি টগল</string>
+ <string name="app_ops_use_alarm_volume">এলার্ম ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_audio_focus">অডিও ফোকাস নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_bluetooth_volume">ব্লু-টুথ ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_master_volume">মাস্টার ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_media_buttons">মিডিয়া বোতামগুলোর ব্যবহার</string>
+ <string name="app_ops_use_media_volume">মিডিয়া ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_notification_volume">নোটিফিকেশান ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_ring_volume">রিংটোন ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_use_vibrate">কাম্পা প্রতিক্রিয়ার ব্যবহার</string>
+ <string name="app_ops_use_voice_volume">ভয়েস কলের ভলিউম নিয়ন্ত্রণ</string>
+ <string name="app_ops_write_mms">এমএমএস বার্তা লিখুন</string>
+ <string name="app_ops_write_sms">এসএমএস বার্তা লিখুন</string>
+ <string name="live_display_auto">স্বয়ংক্রিয়</string>
+ <string name="live_display_off">বন্ধ</string>
+ <string name="live_display_off_summary">সব সামঞ্জস্যগুলি অক্ষম করুন</string>
+ <string name="live_display_day_summary">শুধু দিবা রূপান্তর নির্ধারণ ব্যবহার করুন</string>
+ <string name="live_display_night_summary">কেবল রাতের রূপান্তর নির্ধারণ ব্যবহার করুন</string>
+ <string name="live_display_outdoor">বহিরঙ্গন (উজ্জ্বল সূর্যালোক)</string>
+ <string name="live_display_outdoor_summary">শুধুমাত্র বহিরঙ্গন রূপান্তর নির্ধারণ ব্যবহার করুন</string>
+</resources>
diff --git a/core/res/res/values-ca/cm_strings.xml b/core/res/res/values-ca/cm_strings.xml
new file mode 100644
index 0000000..a229976
--- /dev/null
+++ b/core/res/res/values-ca/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Captura de pantalla</string>
+ <string name="permlab_receiveProtectedSms">rebre SMS protegits</string>
+ <string name="permdesc_receiveProtectedSms">Permet a l\'aplicació rebre un SMS entrant protegit.</string>
+ <string name="permlab_modifyProtectedSmsList">modifica la llista d\'SMS protegits</string>
+ <string name="permdesc_modifyProtectedSmsList">Permet a l\'aplicació modificar la llista d\'adreces d\'SMS protegits.</string>
+ <string name="permgrouplab_security">Seguretat</string>
+ <string name="permgroupdesc_security">Permisos relacionats amb la informació de seguretat del dispositiu.</string>
+ <string name="permlab_readPhoneBlacklist">llegeix la llista negra del telèfon</string>
+ <string name="permdesc_readPhoneBlacklist">Permet a una aplicació llegir informació sobre números de telèfon que estan bloquejats per a trucades entrants o missatges.</string>
+ <string name="permlab_changePhoneBlacklist">canvia la llista negra del telèfon</string>
+ <string name="permdesc_changePhoneBlacklist">Permet a una aplicació canviar els números de telèfon que estan bloquejats per a trucades entrants o missatges.</string>
+ <string name="permlab_setKeyguardWallpaper">estableix el fons de la pantalla de bloqueig</string>
+ <string name="permdesc_setKeyguardWallpaper">Permet que una aplicació estableixi el fons de la pantalla de bloqueig.</string>
+ <string name="global_action_reboot">Reinicia</string>
+ <string name="global_action_current_user">Actual</string>
+ <string name="reboot_reboot">Reinicia</string>
+ <string name="reboot_recovery">Recuperació</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Descàrrega</string>
+ <string name="reboot_soft">Reinici ràpid</string>
+ <string name="reboot_title">Reinicia</string>
+ <string name="reboot_confirm" product="tablet">La teva tauleta es reiniciarà.</string>
+ <string name="reboot_confirm" product="default">El teu telèfon es reiniciarà.</string>
+ <string name="reboot_progress">S\'està reiniciant\u2026</string>
+ <string name="app_killed_message">Aplicació matada</string>
+ <string name="adb_net_active_notification_title">ADB sobre xarxa habilitat</string>
+ <string name="adb_both_active_notification_title">ADB sobre USB i xarxa habilitat</string>
+ <string name="adb_active_generic_notification_message">Toca per deshabilitar la depuració.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; xarxa</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Xarxa</string>
+ <string name="permlab_interceptPackageLaunch">interceptar el llançament d\'una aplicació</string>
+ <string name="stylus_app_not_installed">%s no està instal·lat</string>
+ <string name="silent_mode_priority">Prioritat</string>
+ <string name="silent_mode_none">Cap</string>
+ <string name="subscription_change_disabled_wifi_ap">S\'ha deshabilitat el punt d\'accés Wi-Fi degut a un canvi en la subscripció de la SIM</string>
+ <string name="notify_turn_wifi_off_title">Apaga el Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">activa o desactiva el guarda de privacitat</string>
+ <string name="permdesc_changePrivacyGuardState">Permet a l\'aplicació fer el canvi d\'estat de privacitat d\'una altra aplicació. Quan una aplicació s\'executa amb el guarda de privacitat, no tindrà accés a les dades personals com els contactes, registres de trucades, o missatges.</string>
+ <string name="privacy_guard_notification">Guarda de privacitat actiu</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> no tindrà accés a dades personals</string>
+ <string name="privacy_guard_dialog_title">Guarda de privacitat</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> voldria <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Recorda la meva elecció</string>
+ <string name="app_ops_access_camera">accedir a la càmera</string>
+ <string name="app_ops_access_location">accedir a la teva ubicació</string>
+ <string name="app_ops_access_notifications">llegir les teves notificacions</string>
+ <string name="app_ops_activate_vpn">activa una VPN</string>
+ <string name="app_ops_auto_start">iniciar-se a l\'engegar</string>
+ <string name="app_ops_delete_call_log">esborrar el teu registre de trucades</string>
+ <string name="app_ops_delete_contacts">esborrar els teus contactes</string>
+ <string name="app_ops_delete_mms">esborrar els teus missatges MMS</string>
+ <string name="app_ops_delete_sms">esborrar els teus missatges SMS</string>
+ <string name="app_ops_draw_on_top">dibuixar finestres en primer pla</string>
+ <string name="app_ops_get_usage_stats">obtenir estadístiques d\'ús d\'aplicacions</string>
+ <string name="app_ops_keep_device_awake">mantenir el teu dispositiu encès</string>
+ <string name="app_ops_make_phone_call">fer una trucada</string>
+ <string name="app_ops_modify_calendar">actualitzar el teu calendari</string>
+ <string name="app_ops_modify_call_log">actualitzar el registre de trucades</string>
+ <string name="app_ops_modify_clipboard">modificar el portapapers</string>
+ <string name="app_ops_modify_contacts">actualitzar els teus contactes</string>
+ <string name="app_ops_modify_settings">actualitza la configuració del sistema</string>
+ <string name="app_ops_mute_unmute_microphone">silencia/encen el micròfon</string>
+ <string name="app_ops_play_audio">reproduir so</string>
+ <string name="app_ops_post_notification">publicar una notificació</string>
+ <string name="app_ops_project_media">projectar contingut multimèdia</string>
+ <string name="app_ops_read_calendar">llegir el teu calendari</string>
+ <string name="app_ops_read_call_log">llegir el registre de trucades</string>
+ <string name="app_ops_read_clipboard">llegir el portapapers</string>
+ <string name="app_ops_read_contacts">llegir els teus contactes</string>
+ <string name="app_ops_read_mms">llegir els teus missatges MMS</string>
+ <string name="app_ops_read_sms">llegir els teus missatges SMS</string>
+ <string name="app_ops_receive_sms">rebre un missatge SMS</string>
+ <string name="app_ops_record_audio">enregistrar so</string>
+ <string name="app_ops_send_mms">enviar un missatge MMS</string>
+ <string name="app_ops_send_sms">enviar un missatge SMS</string>
+ <string name="app_ops_start_at_bootup">iniciar-se a l\'engegar</string>
+ <string name="app_ops_toast_window">mostra missatges emergents</string>
+ <string name="app_ops_toggle_bluetooth">canviar el Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">commuta les dades mòbils</string>
+ <string name="app_ops_toggle_nfc">canviar NFC</string>
+ <string name="app_ops_toggle_wifi">canviar Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">controlar el volum de l\'alarma</string>
+ <string name="app_ops_use_audio_focus">controlar el focus del so</string>
+ <string name="app_ops_use_bluetooth_volume">controlar el volum del Bluetooth</string>
+ <string name="app_ops_use_master_volume">controlar el volum principal</string>
+ <string name="app_ops_use_media_buttons">utilitzar els botons multimèdia</string>
+ <string name="app_ops_use_media_volume">controlar el volum multimèdia</string>
+ <string name="app_ops_use_notification_volume">controlar el volum de les notificacions</string>
+ <string name="app_ops_use_ring_volume">controlar el volum del to de trucada</string>
+ <string name="app_ops_use_vibrate">utilitzar resposta hàptica</string>
+ <string name="app_ops_use_voice_volume">controlar el volum de la veu de la trucada</string>
+ <string name="app_ops_write_mms">escriure un missatge MMS</string>
+ <string name="app_ops_write_sms">escriure un missatge SMS</string>
+ <string name="app_ops_use_fingerprint">utilitzar l\'empremta digital</string>
+ <string name="app_ops_add_voicemail">afegir un missatge de veu</string>
+ <string name="app_ops_read_phone_state">accedir a l\'estat del telèfon</string>
+ <string name="app_ops_scan_wifi">escannejar xarxes Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">canviar el fons de pantalla</string>
+ <string name="app_ops_assist_structure">utilitzar estructures d\'assistència</string>
+ <string name="app_ops_assist_screenshot">prendre una captura de pantalla</string>
+ <string name="app_ops_use_body_sensors">utilitzar sensors pel cos</string>
+ <string name="app_ops_read_cell_broadcasts">llegir radio difusions</string>
+ <string name="app_ops_mock_location">simular l\'ubicació</string>
+ <string name="app_ops_read_external_storage">llegir d\'un emmagatzematge extern</string>
+ <string name="app_ops_write_external_storage">escriure en un emmagatzematge extern</string>
+ <string name="app_ops_turn_on_screen">encendre la pantalla</string>
+ <string name="app_ops_get_accounts">obtenir els comptes del dispositiu</string>
+ <string name="app_ops_wifi_change">canviar l\'estat del Wi-Fi</string>
+ <string name="app_ops_su">obtenir accés de superusuari</string>
+ <string name="lock_to_app_toast_no_navbar">Per desancorar aquesta pantalla, toca i aguanta el botó Enrera.</string>
+ <string name="live_display_auto">Automàtic</string>
+ <string name="live_display_auto_summary">Ajusta automàticament la temperatura de color de la pantalla després de la posta de sol i de l\'alba</string>
+ <string name="live_display_off">No</string>
+ <string name="live_display_off_summary">Deshabilita tots els ajustaments</string>
+ <string name="live_display_day">Dia</string>
+ <string name="live_display_day_summary">Utilitza només la configuració de dia</string>
+ <string name="live_display_night">Nit</string>
+ <string name="live_display_night_summary">Utilitza només la configuració de nit</string>
+ <string name="live_display_outdoor">Exterior (sol intens)</string>
+ <string name="live_display_outdoor_summary">Utilitza només la configuració d\'exterior</string>
+ <string name="live_display_hint">LiveDisplay pot ajudar-te a reduir la fatiga ocular i ajudar-te a dormir a la nit. Fes clic aquí per provar-ho!</string>
+ <string name="tethered_notification_no_device_message">Cap dispositiu connectat</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> dispositiu connectat</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> dispositius connectats</string>
+ <string name="notify_package_component_protected_title">Execució de l\'activitat bloquejada</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> està protegit de ser executada. Clica per autentificar i executar l\'aplicació.</string>
+ <string name="notify_battery_fully_charged_title">Bateria completament carregada</string>
+ <string name="notify_battery_fully_charged_text">Desconnecta el teu dispositiu del carregador per millorar la longevitat de la bateria.</string>
+</resources>
diff --git a/core/res/res/values-cs/cm_strings.xml b/core/res/res/values-cs/cm_strings.xml
new file mode 100644
index 0000000..9395ff9
--- /dev/null
+++ b/core/res/res/values-cs/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Snímek obrazovky</string>
+ <string name="permlab_receiveProtectedSms">přijímat chráněné SMS</string>
+ <string name="permdesc_receiveProtectedSms">Umožňuje přijímat příchozí chráněné SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">upravit seznam chráněných SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Umožňuje aplikaci upravit seznam adres chráněných SMS.</string>
+ <string name="permgrouplab_security">Zabezpečení</string>
+ <string name="permgroupdesc_security">Oprávnění vztahující se k informacím o zabezpečení zařízení.</string>
+ <string name="permlab_readPhoneBlacklist">čtení černé listiny telefonu</string>
+ <string name="permdesc_readPhoneBlacklist">Umožňuje čtení informací o telefonních číslech, která jsou blokována pro příjem hovorů nebo zpráv.</string>
+ <string name="permlab_changePhoneBlacklist">změnit černou listinu telefonu</string>
+ <string name="permdesc_changePhoneBlacklist">Umožňuje změnit telefonní čísla, která jsou blokována pro příjem hovorů nebo zpráv.</string>
+ <string name="permlab_setKeyguardWallpaper">nastavit tapetu zámku kláves</string>
+ <string name="permdesc_setKeyguardWallpaper">Umožní změnit tapetu zámku obrazovky.</string>
+ <string name="global_action_reboot">Restartovat</string>
+ <string name="global_action_current_user">Aktuální</string>
+ <string name="reboot_reboot">Reboot</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Soft reboot</string>
+ <string name="reboot_title">Restartovat</string>
+ <string name="reboot_confirm" product="tablet">Tablet bude restartován.</string>
+ <string name="reboot_confirm" product="default">Telefon bude restartován.</string>
+ <string name="reboot_progress">Restart\u2026</string>
+ <string name="app_killed_message">Aplikace byla ukončena</string>
+ <string name="adb_net_active_notification_title">ADB po síti povoleno</string>
+ <string name="adb_both_active_notification_title">ADB přes USB a po síti povoleno</string>
+ <string name="adb_active_generic_notification_message">Dotykem zakázat ladění.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB a síť</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Síť</string>
+ <string name="permlab_interceptPackageLaunch">zachytit spuštění aplikace</string>
+ <string name="stylus_app_not_installed">Aplikace %s není nainstalována</string>
+ <string name="silent_mode_priority">Priorita</string>
+ <string name="silent_mode_none">Žádný</string>
+ <string name="subscription_change_disabled_wifi_ap">Hotspot Wi\u2011Fi byl kvůli změně připojení SIM vypnut</string>
+ <string name="notify_turn_wifi_off_title">Vypnout Wi\u2011Fi</string>
+ <string name="permlab_changePrivacyGuardState">povolit či zakázat Ochranu soukromí</string>
+ <string name="permdesc_changePrivacyGuardState">Umožní změnit pravidla, zda bude některá aplikace spuštěna v režimu Ochrany soukromí. Pokud je aplikace spuštěna v režimu Ochrany soukromí, tato aplikace nemá umožněn přístup k osobním datům jako jsou kontakty, historie volání nebo zprávy.</string>
+ <string name="privacy_guard_notification">Ochrana soukromí aktivní</string>
+ <string name="privacy_guard_notification_detail">Aplikaci <xliff:g id="app">%1$s</xliff:g> nebude umožněn přístup k osobním údajům</string>
+ <string name="privacy_guard_dialog_title">Ochrana soukromí</string>
+ <string name="privacy_guard_dialog_summary">Aplikace <xliff:g id="app">%1$s</xliff:g> se pokouší <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Zapamatovat si volbu</string>
+ <string name="app_ops_access_camera">používat fotoaparát</string>
+ <string name="app_ops_access_location">zjišťovat polohu</string>
+ <string name="app_ops_access_notifications">číst upozornění</string>
+ <string name="app_ops_activate_vpn">aktivovat VPN</string>
+ <string name="app_ops_auto_start">spustit při startu</string>
+ <string name="app_ops_delete_call_log">smazat historii hovorů</string>
+ <string name="app_ops_delete_contacts">smazat kontakty</string>
+ <string name="app_ops_delete_mms">smazat MMS zprávy</string>
+ <string name="app_ops_delete_sms">smazat SMS zprávy</string>
+ <string name="app_ops_draw_on_top">vykreslit okna navrchu</string>
+ <string name="app_ops_get_usage_stats">získat statistiky využití aplikace</string>
+ <string name="app_ops_keep_device_awake">udržovat zařízení probuzené</string>
+ <string name="app_ops_make_phone_call">vytvářet telefonní hovory</string>
+ <string name="app_ops_modify_calendar">měnit kalendář</string>
+ <string name="app_ops_modify_call_log">měnit výpisy hovorů</string>
+ <string name="app_ops_modify_clipboard">měnit schránku</string>
+ <string name="app_ops_modify_contacts">měnit kontakty</string>
+ <string name="app_ops_modify_settings">aktualizovat systémové nastavení</string>
+ <string name="app_ops_mute_unmute_microphone">vypnout/zapnout mikrofon</string>
+ <string name="app_ops_play_audio">přehrávat zvuk</string>
+ <string name="app_ops_post_notification">posílat upozornění</string>
+ <string name="app_ops_project_media">promítání médií</string>
+ <string name="app_ops_read_calendar">číst kalendář</string>
+ <string name="app_ops_read_call_log">číst výpisy hovorů</string>
+ <string name="app_ops_read_clipboard">číst schránku</string>
+ <string name="app_ops_read_contacts">číst kontakty</string>
+ <string name="app_ops_read_mms">číst zprávy MMS</string>
+ <string name="app_ops_read_sms">číst zprávy SMS</string>
+ <string name="app_ops_receive_sms">přijímat zprávy SMS</string>
+ <string name="app_ops_record_audio">nahrávat zvuk</string>
+ <string name="app_ops_send_mms">zaslat zprávu MMS</string>
+ <string name="app_ops_send_sms">zaslat zprávu SMS</string>
+ <string name="app_ops_start_at_bootup">spustit při startu</string>
+ <string name="app_ops_toast_window">zobrazovat vyskakovací upozornění</string>
+ <string name="app_ops_toggle_bluetooth">přepnout Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">vypnout/zapnout mobilní data</string>
+ <string name="app_ops_toggle_nfc">přepnout NFC</string>
+ <string name="app_ops_toggle_wifi">přepnout Wi\u2011Fi</string>
+ <string name="app_ops_use_alarm_volume">ovládat hlasitost budíku</string>
+ <string name="app_ops_use_audio_focus">ovládat zvukové zdroje</string>
+ <string name="app_ops_use_bluetooth_volume">ovládat hlasitost Bluetooth</string>
+ <string name="app_ops_use_master_volume">ovládat hlavní hlasitost</string>
+ <string name="app_ops_use_media_buttons">použít mediální tlačítka</string>
+ <string name="app_ops_use_media_volume">ovládat hlasitost médií</string>
+ <string name="app_ops_use_notification_volume">ovládat hlasitost upozornění</string>
+ <string name="app_ops_use_ring_volume">ovládat hlasitost vyzvánění</string>
+ <string name="app_ops_use_vibrate">použít hmatovou odezvu</string>
+ <string name="app_ops_use_voice_volume">ovládat hlasitost hovoru</string>
+ <string name="app_ops_write_mms">zapsat zprávu MMS</string>
+ <string name="app_ops_write_sms">zapsat zprávu SMS</string>
+ <string name="app_ops_use_fingerprint">použít otisk prstu</string>
+ <string name="app_ops_add_voicemail">přidat hlasovou zprávu</string>
+ <string name="app_ops_read_phone_state">přístup ke stavu telefonu</string>
+ <string name="app_ops_scan_wifi">prohledávání Wi\u2011Fi sítí</string>
+ <string name="app_ops_change_wallpaper">změnit tapetu</string>
+ <string name="app_ops_assist_structure">použít asistenční strukturu</string>
+ <string name="app_ops_assist_screenshot">sejmout obrazovku</string>
+ <string name="app_ops_use_body_sensors">použít senzory těla</string>
+ <string name="app_ops_read_cell_broadcasts">přečíst zprávy buněk GSM</string>
+ <string name="app_ops_mock_location">zfalšovat polohu</string>
+ <string name="app_ops_read_external_storage">přečíst externí úložiště</string>
+ <string name="app_ops_write_external_storage">zapsat na externí úložiště</string>
+ <string name="app_ops_turn_on_screen">zapnout obrazovku</string>
+ <string name="app_ops_get_accounts">získat účty zařízení</string>
+ <string name="app_ops_wifi_change">změna stavu Wi\u2011Fi</string>
+ <string name="app_ops_su">získat root přístup</string>
+ <string name="lock_to_app_toast_no_navbar">Chcete-li odebrat tuto obrazovku, podržte tlačítko Zpět.</string>
+ <string name="live_display_auto">Automaticky</string>
+ <string name="live_display_auto_summary">Automaticky upravit teplotu barev obrazovky po západu a východu slunce</string>
+ <string name="live_display_off">Vypnuto</string>
+ <string name="live_display_off_summary">Zakázat všechny úpravy</string>
+ <string name="live_display_day">Den</string>
+ <string name="live_display_day_summary">Nastavení pouze pro den</string>
+ <string name="live_display_night">Noc</string>
+ <string name="live_display_night_summary">Nastavení pouze pro noc</string>
+ <string name="live_display_outdoor">Venku (slunečno)</string>
+ <string name="live_display_outdoor_summary">Nastavení pouze pro venkovní</string>
+ <string name="live_display_hint">LiveDisplay může pomoci proti namáhání očí a také spánku v noci. Dotykem zde tuto funkci můžete vyzkoušet!</string>
+ <string name="tethered_notification_no_device_message">Žádné připojené zařízení</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> připojené zařízení</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> připojená zařízení</string>
+ <string name="notify_package_component_protected_title">Spuštění aktivity zablokováno</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> je chráněna před spuštěním. Dotykem autorizovat spuštění aplikace.</string>
+ <string name="notify_battery_fully_charged_title">Baterie je nabitá</string>
+ <string name="notify_battery_fully_charged_text">Pro zlepšení životnosti baterie odpojte zařízení od nabíječky.</string>
+</resources>
diff --git a/core/res/res/values-da/cm_strings.xml b/core/res/res/values-da/cm_strings.xml
new file mode 100644
index 0000000..f901c9d
--- /dev/null
+++ b/core/res/res/values-da/cm_strings.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Skærmbillede</string>
+ <string name="permlab_receiveProtectedSms">modtag beskyttet SMS</string>
+ <string name="permdesc_receiveProtectedSms">Tillader at app\'en kan modtage en indgående beskyttet SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">rediger beskyttet SMS liste</string>
+ <string name="permdesc_modifyProtectedSmsList">Tillader at app\'en kan ændre den beskyttede SMS adresseliste.</string>
+ <string name="permgrouplab_security">Sikkerhed</string>
+ <string name="permgroupdesc_security">Tilladelser vedr. enhedens sikkerhedsinformation.</string>
+ <string name="permlab_readPhoneBlacklist">læs telefonens sortliste</string>
+ <string name="permdesc_readPhoneBlacklist">Tillader en app at læse informationer om telefonnumre, som er blokerede for indgående opkald eller beskeder.</string>
+ <string name="permlab_changePhoneBlacklist">ændre telefonens sortliste</string>
+ <string name="permdesc_changePhoneBlacklist">Tillader en app at ændre telefonnumre, som er blokerede for indgående opkald eller beskeder.</string>
+ <string name="permlab_setKeyguardWallpaper">angive baggrund til keyguard</string>
+ <string name="permdesc_setKeyguardWallpaper">Tillader en app at ændre baggrund for skærmlåsen.</string>
+ <string name="global_action_reboot">Genstart</string>
+ <string name="global_action_current_user">Aktuel</string>
+ <string name="reboot_reboot">Genstart</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Blød genstart</string>
+ <string name="reboot_title">Genstart</string>
+ <string name="reboot_confirm" product="tablet">Din tablet vil genstarte.</string>
+ <string name="reboot_confirm" product="default">Din telefon vil genstarte.</string>
+ <string name="reboot_progress">Genstarter\u2026</string>
+ <string name="app_killed_message">App lukket</string>
+ <string name="adb_net_active_notification_title">ADB via netværk aktiveret</string>
+ <string name="adb_both_active_notification_title">ADB via USB &amp; netværk aktiveret</string>
+ <string name="adb_active_generic_notification_message">Tryk for at deaktivere fejlretning.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; netværk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Netværk</string>
+ <string name="permlab_interceptPackageLaunch">afbryd app-opstart</string>
+ <string name="stylus_app_not_installed">%s er ikke installeret</string>
+ <string name="silent_mode_priority">Prioritet</string>
+ <string name="silent_mode_none">Ingen</string>
+ <string name="subscription_change_disabled_wifi_ap">Deaktiverede Wi-Fi hotspot på grund af en ændring af dit SIM abonnement</string>
+ <string name="notify_turn_wifi_off_title">Slå Wi-Fi fra</string>
+ <string name="permlab_changePrivacyGuardState">aktivér eller deaktivér privatlivsvagt</string>
+ <string name="permdesc_changePrivacyGuardState">Tillader app\'en at ændre, om en anden app kører med Privatlivsvagt. Når en app kører med Privatlivsvagt, vil den ikke have adgang til personlige data såsom kontakter, opkaldslister eller beskeder.</string>
+ <string name="privacy_guard_notification">Privatlivsvagt aktiv</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> vil ikke kunne tilgå personlige data</string>
+ <string name="privacy_guard_dialog_title">Privatlivsvagt</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> ønsker at <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Husk mit valg</string>
+ <string name="app_ops_access_camera">tilgå kameraet</string>
+ <string name="app_ops_access_location">tilgå din placering</string>
+ <string name="app_ops_access_notifications">læse dine meddelelser</string>
+ <string name="app_ops_activate_vpn">aktivér en VPN</string>
+ <string name="app_ops_auto_start">starte ved opstart</string>
+ <string name="app_ops_delete_call_log">slet din opkaldsliste</string>
+ <string name="app_ops_delete_contacts">slet dine kontakter</string>
+ <string name="app_ops_delete_mms">slet dine MMS beskeder</string>
+ <string name="app_ops_delete_sms">slet dine SMS beskeder</string>
+ <string name="app_ops_draw_on_top">tegn vinduer øverst</string>
+ <string name="app_ops_get_usage_stats">få brugsstatistik for app</string>
+ <string name="app_ops_keep_device_awake">holde din enhed vågen</string>
+ <string name="app_ops_make_phone_call">foretage opkald</string>
+ <string name="app_ops_modify_calendar">opdatere din kalender</string>
+ <string name="app_ops_modify_call_log">opdatere opkaldslisten</string>
+ <string name="app_ops_modify_clipboard">ændre udklipsholderen</string>
+ <string name="app_ops_modify_contacts">opdatere dine kontakter</string>
+ <string name="app_ops_modify_settings">opdatere systemindstillinger</string>
+ <string name="app_ops_mute_unmute_microphone">Slå mikrofon til/fra</string>
+ <string name="app_ops_play_audio">afspille lyd</string>
+ <string name="app_ops_post_notification">vise en meddelelse</string>
+ <string name="app_ops_project_media">projekt medie</string>
+ <string name="app_ops_read_calendar">læse din kalender</string>
+ <string name="app_ops_read_call_log">læse opkaldsliste</string>
+ <string name="app_ops_read_clipboard">læse udklipsholderen</string>
+ <string name="app_ops_read_contacts">læse dine kontakter</string>
+ <string name="app_ops_read_mms">læse dine MMS-beskeder</string>
+ <string name="app_ops_read_sms">læse dine SMS-beskeder</string>
+ <string name="app_ops_receive_sms">modtage en SMS-besked</string>
+ <string name="app_ops_record_audio">optage lyd</string>
+ <string name="app_ops_send_mms">sende en MMS-besked</string>
+ <string name="app_ops_send_sms">sende en SMS-besked</string>
+ <string name="app_ops_start_at_bootup">starte ved opstart</string>
+ <string name="app_ops_toast_window">vis toast beskeder</string>
+ <string name="app_ops_toggle_bluetooth">tænde/slukke Bluetooth</string>
+ <string name="app_ops_toggle_nfc">NFC til/fra</string>
+ <string name="app_ops_toggle_wifi">Wi-Fi til/fra</string>
+ <string name="app_ops_use_alarm_volume">kontrollere lydstyrken for alarmer</string>
+ <string name="app_ops_use_audio_focus">kontrollere lydfokus</string>
+ <string name="app_ops_use_bluetooth_volume">kontrollere lydstyrken for Bluetooth</string>
+ <string name="app_ops_use_master_volume">kontrollere systemlydstyrken</string>
+ <string name="app_ops_use_media_buttons">bruge medieknapperne</string>
+ <string name="app_ops_use_media_volume">kontrollere lydstyrken for medier</string>
+ <string name="app_ops_use_notification_volume">kontrollere lydstyrken for meddelelser</string>
+ <string name="app_ops_use_ring_volume">kontrollere lydstyrken for ringetonen</string>
+ <string name="app_ops_use_vibrate">bruge haptisk feedback</string>
+ <string name="app_ops_use_voice_volume">styre lydstyrken for stemmeopkald</string>
+ <string name="app_ops_write_mms">skrive en MMS-besked</string>
+ <string name="app_ops_write_sms">skrive en SMS-besked</string>
+ <string name="app_ops_use_fingerprint">brug fingeraftryk</string>
+ <string name="app_ops_add_voicemail">tilføj en voicemail</string>
+ <string name="app_ops_scan_wifi">skan Wi-Fi-netværk</string>
+ <string name="app_ops_change_wallpaper">skift baggrund</string>
+ <string name="app_ops_su">få root-adgang</string>
+ <string name="lock_to_app_toast_no_navbar">For at frigøre denne skærm, tryk og hold Tilbage-knappen nede.</string>
+ <string name="live_display_auto">Automatisk</string>
+ <string name="live_display_auto_summary">Justerer automatisk farvetemperaturen på skærmen efter solnedgang og solopgang</string>
+ <string name="live_display_off">Fra</string>
+ <string name="live_display_off_summary">Deaktivere alle justeringer</string>
+ <string name="live_display_day">Dag</string>
+ <string name="live_display_day_summary">Brug kun dag-indstillinger</string>
+ <string name="live_display_night">Nat</string>
+ <string name="live_display_night_summary">Brug kun nat-indstillinger</string>
+ <string name="live_display_outdoor">Udendørs (stærk sol)</string>
+ <string name="live_display_outdoor_summary">Brug kun udendørsindstillinger</string>
+ <string name="live_display_hint">LiveDisplay kan hjælpe med at reducere overanstrengelse af øjnene og hjælpe dig med at sove om natten. Klik her for at prøve det!</string>
+ <string name="tethered_notification_no_device_message">Ingen tilsluttet enhed</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> tilsluttet enhed</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> tilsluttede enheder</string>
+</resources>
diff --git a/core/res/res/values-de/cm_strings.xml b/core/res/res/values-de/cm_strings.xml
new file mode 100644
index 0000000..6854614
--- /dev/null
+++ b/core/res/res/values-de/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Bildschirmfoto</string>
+ <string name="permlab_receiveProtectedSms">geschützte SMS empfangen</string>
+ <string name="permdesc_receiveProtectedSms">Ermöglicht der App, eine eingehende geschützte SMS zu empfangen.</string>
+ <string name="permlab_modifyProtectedSmsList">Liste der geschützten SMS ändern</string>
+ <string name="permdesc_modifyProtectedSmsList">Ermöglicht der App, die Adressliste der geschützten SMS zu ändern.</string>
+ <string name="permgrouplab_security">Sicherheit</string>
+ <string name="permgroupdesc_security">Berechtigungen im Zusammenhang mit der Gerätesicherheit.</string>
+ <string name="permlab_readPhoneBlacklist">Sperrliste lesen</string>
+ <string name="permdesc_readPhoneBlacklist">Ermöglicht der App, gesperrte Telefonnummern für eingehende Anrufe oder Nachrichten zu lesen.</string>
+ <string name="permlab_changePhoneBlacklist">Sperrliste ändern</string>
+ <string name="permdesc_changePhoneBlacklist">Ermöglicht der App, gesperrte Telefonnummern für eingehende Anrufe oder Nachrichten zu ändern.</string>
+ <string name="permlab_setKeyguardWallpaper">Sperrbildschirm-Hintergrund ändern</string>
+ <string name="permdesc_setKeyguardWallpaper">Ermöglicht der App, den Sperrbildschirm-Hintergrund zu ändern.</string>
+ <string name="global_action_reboot">Neu starten</string>
+ <string name="global_action_current_user">Aktuell</string>
+ <string name="reboot_reboot">Neu starten</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Warmstart</string>
+ <string name="reboot_title">Neu starten</string>
+ <string name="reboot_confirm" product="tablet">Ihr Tablet wird neu gestartet.</string>
+ <string name="reboot_confirm" product="default">Ihr Telefon wird neu gestartet.</string>
+ <string name="reboot_progress">Neustart wird durchgeführt\u2026</string>
+ <string name="app_killed_message">Anwendung beendet</string>
+ <string name="adb_net_active_notification_title">ADB über Netzwerk aktiviert</string>
+ <string name="adb_both_active_notification_title">ADB über USB &amp; Netzwerk aktiviert</string>
+ <string name="adb_active_generic_notification_message">Berühren, um Debugging zu deaktivieren.</string>
+ <string name="adb_active_custom_tile">ADB: <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB und Netzwerk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Netzwerk</string>
+ <string name="permlab_interceptPackageLaunch">App-Start verhindern</string>
+ <string name="stylus_app_not_installed">%s ist nicht installiert</string>
+ <string name="silent_mode_priority">Wichtig</string>
+ <string name="silent_mode_none">Keine</string>
+ <string name="subscription_change_disabled_wifi_ap">Der WLAN-Hotspot wurde aufgrund einer SIM-Abonnementänderung deaktiviert.</string>
+ <string name="notify_turn_wifi_off_title">WLAN ausschalten</string>
+ <string name="permlab_changePrivacyGuardState">Datenschutz aktivieren oder deaktivieren</string>
+ <string name="permdesc_changePrivacyGuardState">Ermöglicht der App, den Datenschutz für andere Apps zu aktivieren oder deaktivieren. Eine App mit aktiviertem Datenschutz hat keinen Zugriff auf persönliche Daten wie Kontakte, Nachrichten oder das Anrufprotokoll.</string>
+ <string name="privacy_guard_notification">Datenschutz aktiv</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> hat keinen Zugriff auf persönliche Daten</string>
+ <string name="privacy_guard_dialog_title">Datenschutz</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> versucht, <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Meine Auswahl merken</string>
+ <string name="app_ops_access_camera">auf die Kamera zuzugreifen</string>
+ <string name="app_ops_access_location">den Standort abzurufen</string>
+ <string name="app_ops_access_notifications">auf Benachrichtigungen zuzugreifen</string>
+ <string name="app_ops_activate_vpn">ein VPN zu aktivieren</string>
+ <string name="app_ops_auto_start">automatisch zu starten</string>
+ <string name="app_ops_delete_call_log">Ihre Anrufliste zu löschen</string>
+ <string name="app_ops_delete_contacts">Ihre Kontakte zu löschen</string>
+ <string name="app_ops_delete_mms">Ihre MMS-Nachrichten zu löschen</string>
+ <string name="app_ops_delete_sms">Ihre SMS zu löschen</string>
+ <string name="app_ops_draw_on_top">sich im Vordergrund einzublenden</string>
+ <string name="app_ops_get_usage_stats">Nutzungsstatistiken von Apps abrufen</string>
+ <string name="app_ops_keep_device_awake">den Ruhezustand zu deaktivieren</string>
+ <string name="app_ops_make_phone_call">Anrufe zu tätigen</string>
+ <string name="app_ops_modify_calendar">Ihren Kalender zu aktualisieren</string>
+ <string name="app_ops_modify_call_log">die Anrufliste zu ändern</string>
+ <string name="app_ops_modify_clipboard">die Zwischenablage zu ändern</string>
+ <string name="app_ops_modify_contacts">Kontakte zu ändern</string>
+ <string name="app_ops_modify_settings">Einstellungen zu ändern</string>
+ <string name="app_ops_mute_unmute_microphone">das Mikrofon zu aktivieren/deaktivieren</string>
+ <string name="app_ops_play_audio">Audio wiederzugeben</string>
+ <string name="app_ops_post_notification">eine Benachrichtigung zu erstellen</string>
+ <string name="app_ops_project_media">Medien zu projizieren</string>
+ <string name="app_ops_read_calendar">Kalendereinträge zu lesen</string>
+ <string name="app_ops_read_call_log">die Anrufliste zu lesen</string>
+ <string name="app_ops_read_clipboard">die Zwischenablage zu lesen</string>
+ <string name="app_ops_read_contacts">Kontakte zu lesen</string>
+ <string name="app_ops_read_mms">MMS zu lesen</string>
+ <string name="app_ops_read_sms">Ihre SMS zu lesen</string>
+ <string name="app_ops_receive_sms">eine SMS zu empfangen</string>
+ <string name="app_ops_record_audio">Audio aufzuzeichnen</string>
+ <string name="app_ops_send_mms">eine MMS zu senden</string>
+ <string name="app_ops_send_sms">eine SMS zu senden</string>
+ <string name="app_ops_start_at_bootup">beim Einschalten zu starten</string>
+ <string name="app_ops_toast_window">Toast-Nachrichten anzuzeigen</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth ein-/auszuschalten</string>
+ <string name="app_ops_toggle_mobile_data">Mobile Daten ein-/ausschalten</string>
+ <string name="app_ops_toggle_nfc">NFC ein-/auszuschalten</string>
+ <string name="app_ops_toggle_wifi">WLAN ein-/auszuschalten</string>
+ <string name="app_ops_use_alarm_volume">die Weckerlautstärke zu ändern</string>
+ <string name="app_ops_use_audio_focus">den Audiofokus zu ändern</string>
+ <string name="app_ops_use_bluetooth_volume">die Bluetooth-Laustärke zu ändern</string>
+ <string name="app_ops_use_master_volume">die Gesamtlautstärke zu ändern</string>
+ <string name="app_ops_use_media_buttons">die Medienschaltflächen zu nutzen</string>
+ <string name="app_ops_use_media_volume">die Medienlautstärke zu ändern</string>
+ <string name="app_ops_use_notification_volume">die Benachrichtigungslautstärke zu ändern</string>
+ <string name="app_ops_use_ring_volume">die Klingeltonlautstärke zu ändern</string>
+ <string name="app_ops_use_vibrate">den Vibrationsalarm zu steuern</string>
+ <string name="app_ops_use_voice_volume">die Sprachlautstärke zu ändern</string>
+ <string name="app_ops_write_mms">eine MMS zu schreiben</string>
+ <string name="app_ops_write_sms">eine SMS zu schreiben</string>
+ <string name="app_ops_use_fingerprint">den Fingerabdruck zu nutzen</string>
+ <string name="app_ops_add_voicemail">eine Sprachnachricht hinzuzufügen</string>
+ <string name="app_ops_read_phone_state">auf Telefon-Status zuzugreifen</string>
+ <string name="app_ops_scan_wifi">WLAN-Netzwerke zu scannen</string>
+ <string name="app_ops_change_wallpaper">Hintergrundbild zu ändern</string>
+ <string name="app_ops_assist_structure">Unterstützungsstruktur zu verwenden</string>
+ <string name="app_ops_assist_screenshot">Bildschirmfoto aufzunehmen</string>
+ <string name="app_ops_use_body_sensors">Körpersensoren zu verwenden</string>
+ <string name="app_ops_read_cell_broadcasts">Cell-Broadcasts zu lesen</string>
+ <string name="app_ops_mock_location">Ihren Standort zu simulieren</string>
+ <string name="app_ops_read_external_storage">externen Speicher zu lesen</string>
+ <string name="app_ops_write_external_storage">externen Speicher zu beschreiben</string>
+ <string name="app_ops_turn_on_screen">den Bildschirm einzuschalten</string>
+ <string name="app_ops_get_accounts">Geräte-Konten abzurufen</string>
+ <string name="app_ops_wifi_change">WLAN-Status zu ändern</string>
+ <string name="app_ops_su">Root-Zugriff zu erhalten</string>
+ <string name="lock_to_app_toast_no_navbar">Zum Lösen dieser Ansicht drücken und halten Sie die Zurück-Taste.</string>
+ <string name="live_display_auto">Automatisch</string>
+ <string name="live_display_auto_summary">Farbtemperatur des Bildschirms nach Sonnenaufgang und Sonnenuntergang automatisch anpassen</string>
+ <string name="live_display_off">Aus</string>
+ <string name="live_display_off_summary">Alle Anpassungen deaktivieren</string>
+ <string name="live_display_day">Tag</string>
+ <string name="live_display_day_summary">Nur Tag-Modus verwenden</string>
+ <string name="live_display_night">Nacht</string>
+ <string name="live_display_night_summary">Nur Nacht-Modus verwenden</string>
+ <string name="live_display_outdoor">Außen (helle Sonne)</string>
+ <string name="live_display_outdoor_summary">Nur Außen-Modus verwenden</string>
+ <string name="live_display_hint">LiveDisplay kann gegen eine Überanstrengung der Augen und beim Schlafen in der Nacht helfen. Klicken Sie hier, um es auszuprobieren!</string>
+ <string name="tethered_notification_no_device_message">Kein verbundenes Gerät</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> verbundenes Gerät</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> verbundene Geräte</string>
+ <string name="notify_package_component_protected_title">Start der Aktivität blockiert</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> ist vom Starten abgehalten worden. Tippen Sie, um sich zu authentifizieren und die App zu starten.</string>
+ <string name="notify_battery_fully_charged_title">Akku vollständig aufgeladen</string>
+ <string name="notify_battery_fully_charged_text">Trennen Sie Ihr Gerät jetzt vom Ladegerät, um die Lebensdauer des Akkus nicht zu beeinträchtigen.</string>
+</resources>
diff --git a/core/res/res/values-el/cm_strings.xml b/core/res/res/values-el/cm_strings.xml
new file mode 100644
index 0000000..931c58a
--- /dev/null
+++ b/core/res/res/values-el/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Στιγμιότυπο οθόνης</string>
+ <string name="permlab_receiveProtectedSms">λήψη προστατευμένων SMS</string>
+ <string name="permdesc_receiveProtectedSms">Επιτρέπει στην εφαρμογή να λαμβάνει εισερχόμενα προστατευμένα SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">τροποποίηση λίστας προστατευμένων SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Επιτρέπει στην εφαρμογή την τροποποίηση της λίστας προστατευμένων SMS.</string>
+ <string name="permgrouplab_security">Ασφάλεια</string>
+ <string name="permgroupdesc_security">Δικαιώματα που σχετίζονται με την ασφάλεια των πληροφοριών της συσκευής.</string>
+ <string name="permlab_readPhoneBlacklist">ανάγνωση της μαύρης λίστας τηλεφώνου</string>
+ <string name="permdesc_readPhoneBlacklist">Επιτρέπει σε μια εφαρμογή την ανάγνωση πληροφοριών σχετικά με τους αριθμούς τηλεφώνου που έχουν αποκλειστεί για εισερχόμενες κλήσεις ή μηνύματα.</string>
+ <string name="permlab_changePhoneBlacklist">αλλαγή της μαύρης λίστας τηλεφώνου</string>
+ <string name="permdesc_changePhoneBlacklist">Επιτρέπει σε μια εφαρμογή την αλλαγή των αριθμών τηλεφώνου που έχουν αποκλειστεί για εισερχόμενες κλήσεις ή μηνύματα.</string>
+ <string name="permlab_setKeyguardWallpaper">ορισμός ταπετσαρίας οθόνης κλειδώματος</string>
+ <string name="permdesc_setKeyguardWallpaper">Επιτρέπει σε μια εφαρμογή την αλλαγή της ταπετσαρίας της οθόνης κλειδώματος.</string>
+ <string name="global_action_reboot">Επανεκκίνηση</string>
+ <string name="global_action_current_user">Τρέχων</string>
+ <string name="reboot_reboot">Επανεκκίνηση</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Γρήγορη επανεκκίνηση</string>
+ <string name="reboot_title">Επανεκκίνηση</string>
+ <string name="reboot_confirm" product="tablet">Το tablet σας θα κάνει επανεκκίνηση.</string>
+ <string name="reboot_confirm" product="default">Το τηλέφωνό σας θα κάνει επανεκκίνηση.</string>
+ <string name="reboot_progress">Επανεκκίνηση\u2026</string>
+ <string name="app_killed_message">Η εφαρμογή τερματίστηκε</string>
+ <string name="adb_net_active_notification_title">ADB μέσω δικτύου ενεργοποιημένο</string>
+ <string name="adb_both_active_notification_title">ADB μέσω USB &amp; δικτύου ενεργοποιημένο</string>
+ <string name="adb_active_generic_notification_message">Αγγίξτε για απενεργοποίηση του εντοπισμού σφαλμάτων.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; δίκτυο</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Δίκτυο</string>
+ <string name="permlab_interceptPackageLaunch">παρεμπόδιση έναρξης εφαρμογών</string>
+ <string name="stylus_app_not_installed">Το %s δεν είναι εγκατεστημένο</string>
+ <string name="silent_mode_priority">Προτεραιότητα</string>
+ <string name="silent_mode_none">Κανένα</string>
+ <string name="subscription_change_disabled_wifi_ap">Το Wi-Fi hotspot απενεργοποιήθηκε λόγω αλλαγής συνδρομής SIM</string>
+ <string name="notify_turn_wifi_off_title">Απενεργοποίηση Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">ενεργοποίηση ή απενεργοποίηση της Προστασίας Απορρήτου</string>
+ <string name="permdesc_changePrivacyGuardState">Επιτρέπει στην εφαρμογή τον χειρισμό άλλων εφαρμογών με την Προστασία Απορρήτου. Όταν μια εφαρμογή τρέχει με την Προστασία Απορρήτου, δεν θα έχει πρόσβαση στα προσωπικά σας δεδομένα όπως επαφές, μηνύματα ή το αρχείο κλήσεων.</string>
+ <string name="privacy_guard_notification">Προστασία Απορρήτου ενεργή</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> δεν θα μπορεί να έχει πρόσβαση στα προσωπικά σας δεδομένα</string>
+ <string name="privacy_guard_dialog_title">Προστασία Απορρήτου</string>
+ <string name="privacy_guard_dialog_summary">Το <xliff:g id="app">%1$s</xliff:g> ζητά: <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Απομνημόνευση της επιλογής μου</string>
+ <string name="app_ops_access_camera">πρόσβαση στην φωτογρ. μηχανή</string>
+ <string name="app_ops_access_location">πρόσβαση στην τοποθεσία σας</string>
+ <string name="app_ops_access_notifications">ανάγνωση των ειδοποιήσεών σας</string>
+ <string name="app_ops_activate_vpn">ενεργοποίηση ενός VPN</string>
+ <string name="app_ops_auto_start">άνοιγμα κατά την εκκίνηση</string>
+ <string name="app_ops_delete_call_log">διαγραφή του ιστορικού κλήσεων σας</string>
+ <string name="app_ops_delete_contacts">διαγραφή των επαφών σας</string>
+ <string name="app_ops_delete_mms">διαγραφή των μηνυμάτων MMS σας</string>
+ <string name="app_ops_delete_sms">διαγραφή των μηνυμάτων SMS σας</string>
+ <string name="app_ops_draw_on_top">εμφάνιση παραθύρων στην κορυφή</string>
+ <string name="app_ops_get_usage_stats">λήψη στατιστικών χρήσης εφαρμογών</string>
+ <string name="app_ops_keep_device_awake">διατήρηση της συσκευής σας σε αφύπνιση</string>
+ <string name="app_ops_make_phone_call">πραγματοποίηση μιας τηλεφωνικής κλήσης</string>
+ <string name="app_ops_modify_calendar">ενημέρωση του ημερολογίου σας</string>
+ <string name="app_ops_modify_call_log">ενημέρωση του αρχείου κλήσεων</string>
+ <string name="app_ops_modify_clipboard">τροποποίηση του προχείρου</string>
+ <string name="app_ops_modify_contacts">ενημέρωση των επαφών σας</string>
+ <string name="app_ops_modify_settings">ενημέρωση των ρυθμίσεων συστήματος</string>
+ <string name="app_ops_mute_unmute_microphone">σίγαση/κατάργηση σίγασης του μικροφώνου</string>
+ <string name="app_ops_play_audio">αναπαραγωγή ήχου</string>
+ <string name="app_ops_post_notification">εμφάνιση μιας ειδοποίησης</string>
+ <string name="app_ops_project_media">εμφάνιση πολυμέσων</string>
+ <string name="app_ops_read_calendar">ανάγνωση του ημερολογίου σας</string>
+ <string name="app_ops_read_call_log">ανάγνωση του αρχείου κλήσεων</string>
+ <string name="app_ops_read_clipboard">ανάγνωση του προχείρου</string>
+ <string name="app_ops_read_contacts">ανάγνωση των επαφών σας</string>
+ <string name="app_ops_read_mms">ανάγνωση των μηνυμάτων MMS σας</string>
+ <string name="app_ops_read_sms">ανάγνωση των μηνυμάτων SMS σας</string>
+ <string name="app_ops_receive_sms">λήψη ενός μηνύματος SMS</string>
+ <string name="app_ops_record_audio">εγγραφή ήχου</string>
+ <string name="app_ops_send_mms">αποστολή ενός μηνύματος MMS</string>
+ <string name="app_ops_send_sms">αποστολή ενός μηνύματος SMS</string>
+ <string name="app_ops_start_at_bootup">άνοιγμα κατά την εκκίνηση</string>
+ <string name="app_ops_toast_window">εμφάνιση αναδυόμενων μηνυμάτων</string>
+ <string name="app_ops_toggle_bluetooth">εναλλαγή Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">εναλλαγή δεδομένων κινητής τηλεφωνίας</string>
+ <string name="app_ops_toggle_nfc">εναλλαγή NFC</string>
+ <string name="app_ops_toggle_wifi">εναλλαγή Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">έλεγχο έντασης ξυπνητηριού</string>
+ <string name="app_ops_use_audio_focus">έλεγχο της εστίασης ήχου</string>
+ <string name="app_ops_use_bluetooth_volume">έλεγχο της έντασης Bluetooth</string>
+ <string name="app_ops_use_master_volume">έλεγχο της κύριας έντασης</string>
+ <string name="app_ops_use_media_buttons">χρήση των πλήκτρων μέσων</string>
+ <string name="app_ops_use_media_volume">έλεγχο της έντασης μέσων</string>
+ <string name="app_ops_use_notification_volume">έλεγχο της έντασης ειδοποιήσεων</string>
+ <string name="app_ops_use_ring_volume">έλεγχο της έντασης ήχου κλήσης</string>
+ <string name="app_ops_use_vibrate">χρήση απτικής ανάδρασης</string>
+ <string name="app_ops_use_voice_volume">έλεγχο της έντασης φωνητικής κλήσης</string>
+ <string name="app_ops_write_mms">εγγραφή ενός μηνύματος MMS</string>
+ <string name="app_ops_write_sms">εγγραφή ενός μηνύματος SMS</string>
+ <string name="app_ops_use_fingerprint">χρήση δακτυλικού αποτυπώματος</string>
+ <string name="app_ops_add_voicemail">προσθήκη φωνητικού μηνύματος</string>
+ <string name="app_ops_read_phone_state">πρόσβαση στην κατάσταση τηλεφώνου</string>
+ <string name="app_ops_scan_wifi">σάρωση δίκτυων Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">αλλαγή της ταπετσαρίας</string>
+ <string name="app_ops_assist_structure">χρήση της βοηθητικής εφαρμογής</string>
+ <string name="app_ops_assist_screenshot">λήψη στιγμιότυπου οθόνης</string>
+ <string name="app_ops_use_body_sensors">χρήση αισθητήρων σώματος</string>
+ <string name="app_ops_read_cell_broadcasts">ανάγνωση εκπομπών κινητής τηλεφωνίας</string>
+ <string name="app_ops_mock_location">αναφορά ψευδής τοποθεσίας</string>
+ <string name="app_ops_read_external_storage">ανάγνωση εξωτερικού αποθ. χώρου</string>
+ <string name="app_ops_write_external_storage">εγγραφή εξωτερικού αποθ. χώρου</string>
+ <string name="app_ops_turn_on_screen">ενεργοποίηση της οθόνης</string>
+ <string name="app_ops_get_accounts">ανάγνωση λογαριασμών συσκευής</string>
+ <string name="app_ops_wifi_change">αλλαγή κατάστασης Wi-Fi</string>
+ <string name="app_ops_su">πρόσβαση root</string>
+ <string name="lock_to_app_toast_no_navbar">Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε και κρατήστε πατημένο το πλήκτρο Πίσω.</string>
+ <string name="live_display_auto">Αυτόματη</string>
+ <string name="live_display_auto_summary">Αυτόματη ρύθμιση της θερμοκρασίας χρώματος της οθόνης μετά το ηλιοβασίλεμα και την ανατολή του ηλίου</string>
+ <string name="live_display_off">Απενεργοποιημένη</string>
+ <string name="live_display_off_summary">Απενεργοποίηση όλων των ρυθμίσεων</string>
+ <string name="live_display_day">Ημέρα</string>
+ <string name="live_display_day_summary">Χρήση μόνο των ρυθμίσεων ημέρας</string>
+ <string name="live_display_night">Νύχτα</string>
+ <string name="live_display_night_summary">Χρήση μόνο των ρυθμίσεων νύχτας</string>
+ <string name="live_display_outdoor">Εξωτερικός χώρος (ήλιος)</string>
+ <string name="live_display_outdoor_summary">Χρήση μόνο των ρυθμίσεων εξωτερικού χώρου</string>
+ <string name="live_display_hint">Το LiveDisplay μπορεί να βοηθήσει στη μείωση της κόπωσης των ματιών και να σας βοηθήσει να κοιμηθείτε τη νύχτα. Κάντε κλικ εδώ για να το δοκιμάσετε!</string>
+ <string name="tethered_notification_no_device_message">Καμία συνδεδεμένη συσκευή</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> συνδεδεμένη συσκευή</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> συνδεδεμένες συσκευές</string>
+ <string name="notify_package_component_protected_title">Η εκκίνηση της δραστηριότητας αποκλείστηκε</string>
+ <string name="notify_package_component_protected_text">Η εφαρμογή <xliff:g id="app_name">%1$s</xliff:g> είναι προστατευμένη. Πιέστε για έλεγχο ταυτότητας και εκκίνηση της εφαρμογής.</string>
+ <string name="notify_battery_fully_charged_title">Μπαταρία πλήρως φορτισμένη</string>
+ <string name="notify_battery_fully_charged_text">Αποσυνδέστε τη συσκευή από το φορτιστή για να βελτιώσετε τη μακροζωία της μπαταρίας.</string>
+</resources>
diff --git a/core/res/res/values-en-rAU/cm_strings.xml b/core/res/res/values-en-rAU/cm_strings.xml
new file mode 100644
index 0000000..8eb89c6
--- /dev/null
+++ b/core/res/res/values-en-rAU/cm_strings.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Screenshot</string>
+ <string name="permlab_receiveProtectedSms">receive protected SMS</string>
+ <string name="permdesc_receiveProtectedSms">Allows the app to receive an incoming protected SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">modify protected SMS list</string>
+ <string name="permdesc_modifyProtectedSmsList">Allows the app to modify the protected SMS address list.</string>
+ <string name="permgrouplab_security">Security</string>
+ <string name="permgroupdesc_security">Permissions related to device security information.</string>
+ <string name="permlab_readPhoneBlacklist">read phone blacklist</string>
+ <string name="permdesc_readPhoneBlacklist">Allows an app to read information about phone numbers that are blocked for incoming calls or messages.</string>
+ <string name="permlab_changePhoneBlacklist">change phone blacklist</string>
+ <string name="permdesc_changePhoneBlacklist">Allows an app to change the phone numbers that are blocked for incoming calls or messages.</string>
+ <string name="permlab_setKeyguardWallpaper">set keyguard wallpaper</string>
+ <string name="permdesc_setKeyguardWallpaper">Allows an app to change the lock screen wallpaper.</string>
+ <string name="global_action_reboot">Reboot</string>
+ <string name="global_action_current_user">Current</string>
+ <string name="reboot_reboot">Reboot</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Soft reboot</string>
+ <string name="reboot_title">Reboot</string>
+ <string name="reboot_confirm" product="tablet">Your tablet will reboot.</string>
+ <string name="reboot_confirm" product="default">Your phone will reboot.</string>
+ <string name="reboot_progress">Rebooting\u2026</string>
+ <string name="app_killed_message">App killed</string>
+ <string name="adb_net_active_notification_title">ADB over network enabled</string>
+ <string name="adb_both_active_notification_title">ADB over USB &amp; network enabled</string>
+ <string name="adb_active_generic_notification_message">Touch to disable debugging.</string>
+ <string name="permlab_interceptPackageLaunch">intercept app launch</string>
+ <string name="stylus_app_not_installed">%s is not installed</string>
+ <string name="permlab_changePrivacyGuardState">enable or disable Privacy Guard</string>
+ <string name="permdesc_changePrivacyGuardState">Allows the app to change whether another app runs with Privacy Guard. When an app is running with Privacy Guard, it will not have access to personal data such as contacts, call logs, or messages.</string>
+ <string name="privacy_guard_notification">Privacy Guard active</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> will not be able to access personal data</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> would like to <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Remember my choice</string>
+ <string name="app_ops_access_camera">access the camera</string>
+ <string name="app_ops_access_location">access your location</string>
+ <string name="app_ops_access_notifications">read your notifications</string>
+ <string name="app_ops_activate_vpn">activate a VPN</string>
+ <string name="app_ops_auto_start">start at power up</string>
+ <string name="app_ops_delete_call_log">delete your call log</string>
+ <string name="app_ops_delete_contacts">delete your contacts</string>
+ <string name="app_ops_delete_mms">delete your MMS messages</string>
+ <string name="app_ops_delete_sms">delete your SMS messages</string>
+ <string name="app_ops_draw_on_top">draw windows on top</string>
+ <string name="app_ops_get_usage_stats">get app usage stats</string>
+ <string name="app_ops_keep_device_awake">keep your device awake</string>
+ <string name="app_ops_make_phone_call">make a phone call</string>
+ <string name="app_ops_modify_calendar">update your calendar</string>
+ <string name="app_ops_modify_call_log">update the call log</string>
+ <string name="app_ops_modify_clipboard">modify the clipboard</string>
+ <string name="app_ops_modify_contacts">update your contacts</string>
+ <string name="app_ops_modify_settings">update system settings</string>
+ <string name="app_ops_mute_unmute_microphone">mute/unmute the microphone</string>
+ <string name="app_ops_play_audio">play audio</string>
+ <string name="app_ops_post_notification">post a notification</string>
+ <string name="app_ops_project_media">project media</string>
+ <string name="app_ops_read_calendar">read your calendar</string>
+ <string name="app_ops_read_call_log">read the call log</string>
+ <string name="app_ops_read_clipboard">read the clipboard</string>
+ <string name="app_ops_read_contacts">read your contacts</string>
+ <string name="app_ops_read_mms">read your MMS messages</string>
+ <string name="app_ops_read_sms">read your SMS messages</string>
+ <string name="app_ops_receive_sms">receive an SMS message</string>
+ <string name="app_ops_record_audio">record audio</string>
+ <string name="app_ops_send_mms">send an MMS message</string>
+ <string name="app_ops_send_sms">send an SMS message</string>
+ <string name="app_ops_start_at_bootup">start at power up</string>
+ <string name="app_ops_toast_window">display toast messages</string>
+ <string name="app_ops_toggle_bluetooth">toggle Bluetooth</string>
+ <string name="app_ops_toggle_nfc">toggle NFC</string>
+ <string name="app_ops_use_alarm_volume">control alarm volume</string>
+ <string name="app_ops_use_audio_focus">control the audio focus</string>
+ <string name="app_ops_use_bluetooth_volume">control the Bluetooth volume</string>
+ <string name="app_ops_use_master_volume">control the master volume</string>
+ <string name="app_ops_use_media_buttons">use the media buttons</string>
+ <string name="app_ops_use_media_volume">control the media volume</string>
+ <string name="app_ops_use_notification_volume">control the notification volume</string>
+ <string name="app_ops_use_ring_volume">control the ringtone volume</string>
+ <string name="app_ops_use_vibrate">use haptic feedback</string>
+ <string name="app_ops_use_voice_volume">control the voice call volume</string>
+ <string name="app_ops_write_mms">write an MMS message</string>
+ <string name="app_ops_write_sms">write an SMS message</string>
+ <string name="app_ops_su">get root access</string>
+ <string name="live_display_auto">Automatic</string>
+ <string name="live_display_auto_summary">Automatically adjust color temperature of screen after sunset and sunrise</string>
+ <string name="live_display_off">Off</string>
+ <string name="live_display_off_summary">Disable all adjustments</string>
+ <string name="live_display_day">Day</string>
+ <string name="live_display_day_summary">Use day settings only</string>
+ <string name="live_display_night">Night</string>
+ <string name="live_display_night_summary">Use night settings only</string>
+ <string name="live_display_outdoor">Outdoor (bright sun)</string>
+ <string name="live_display_outdoor_summary">Use outdoor settings only</string>
+ <string name="live_display_hint">LiveDisplay can help reduce eyestrain and help you sleep at night. Click here to try it out!</string>
+ <string name="tethered_notification_no_device_message">No connected device</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> connected device</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> connected devices</string>
+</resources>
diff --git a/core/res/res/values-en-rIN/cm_strings.xml b/core/res/res/values-en-rIN/cm_strings.xml
new file mode 100644
index 0000000..e5dadee
--- /dev/null
+++ b/core/res/res/values-en-rIN/cm_strings.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Screenshot</string>
+ <string name="permlab_receiveProtectedSms">receive protected SMS</string>
+ <string name="permdesc_receiveProtectedSms">Allows the app to receive an incoming protected SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">modify protected SMS list</string>
+ <string name="permdesc_modifyProtectedSmsList">Allows the app to modify the protected SMS address list.</string>
+ <string name="permgrouplab_security">Security</string>
+ <string name="permgroupdesc_security">Permissions related to device security information.</string>
+ <string name="permlab_readPhoneBlacklist">read phone blacklist</string>
+ <string name="permdesc_readPhoneBlacklist">Allows an app to read information about phone numbers that are blocked for incoming calls or messages.</string>
+ <string name="permlab_changePhoneBlacklist">change phone blacklist</string>
+ <string name="permdesc_changePhoneBlacklist">Allows an app to change the phone numbers that are blocked for incoming calls or messages.</string>
+ <string name="permlab_setKeyguardWallpaper">set keyguard wallpaper</string>
+ <string name="permdesc_setKeyguardWallpaper">Allows an app to change the lock screen wallpaper.</string>
+ <string name="global_action_reboot">Reboot</string>
+ <string name="global_action_current_user">Current</string>
+ <string name="reboot_reboot">Reboot</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Soft reboot</string>
+ <string name="reboot_title">Reboot</string>
+ <string name="reboot_confirm" product="tablet">Your tablet will reboot.</string>
+ <string name="reboot_confirm" product="default">Your phone will reboot.</string>
+ <string name="reboot_progress">Rebooting\u2026</string>
+ <string name="app_killed_message">App killed</string>
+ <string name="adb_net_active_notification_title">ADB over network enabled</string>
+ <string name="adb_both_active_notification_title">ADB over USB &amp; network enabled</string>
+ <string name="adb_active_generic_notification_message">Touch to disable debugging.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; network</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Network</string>
+ <string name="permlab_interceptPackageLaunch">intercept app launch</string>
+ <string name="stylus_app_not_installed">%s is not installed</string>
+ <string name="silent_mode_priority">Priority</string>
+ <string name="silent_mode_none">None</string>
+ <string name="subscription_change_disabled_wifi_ap">Disabled Wi-Fi hotspot due to SIM subscription change</string>
+ <string name="notify_turn_wifi_off_title">Turn Wi-Fi off</string>
+ <string name="permlab_changePrivacyGuardState">enable or disable Privacy Guard</string>
+ <string name="permdesc_changePrivacyGuardState">Allows the app to change whether another app runs with Privacy Guard. When an app is running with Privacy Guard, it will not have access to personal data such as contacts, call logs, or messages.</string>
+ <string name="privacy_guard_notification">Privacy Guard active</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> will not be able to access personal data</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> would like to <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Remember my choice</string>
+ <string name="app_ops_access_camera">access the camera</string>
+ <string name="app_ops_access_location">access your location</string>
+ <string name="app_ops_access_notifications">read your notifications</string>
+ <string name="app_ops_activate_vpn">activate a VPN</string>
+ <string name="app_ops_auto_start">start at power up</string>
+ <string name="app_ops_delete_call_log">delete your call log</string>
+ <string name="app_ops_delete_contacts">delete your contacts</string>
+ <string name="app_ops_delete_mms">delete your MMS messages</string>
+ <string name="app_ops_delete_sms">delete your SMS messages</string>
+ <string name="app_ops_draw_on_top">draw windows on top</string>
+ <string name="app_ops_get_usage_stats">get app usage stats</string>
+ <string name="app_ops_keep_device_awake">keep your device awake</string>
+ <string name="app_ops_make_phone_call">make a phone call</string>
+ <string name="app_ops_modify_calendar">update your calendar</string>
+ <string name="app_ops_modify_call_log">update the call log</string>
+ <string name="app_ops_modify_clipboard">modify the clipboard</string>
+ <string name="app_ops_modify_contacts">update your contacts</string>
+ <string name="app_ops_modify_settings">update system settings</string>
+ <string name="app_ops_mute_unmute_microphone">mute/unmute the microphone</string>
+ <string name="app_ops_play_audio">play audio</string>
+ <string name="app_ops_post_notification">post a notification</string>
+ <string name="app_ops_project_media">project media</string>
+ <string name="app_ops_read_calendar">read your calendar</string>
+ <string name="app_ops_read_call_log">read the call log</string>
+ <string name="app_ops_read_clipboard">read the clipboard</string>
+ <string name="app_ops_read_contacts">read your contacts</string>
+ <string name="app_ops_read_mms">read your MMS messages</string>
+ <string name="app_ops_read_sms">read your SMS messages</string>
+ <string name="app_ops_receive_sms">receive an SMS message</string>
+ <string name="app_ops_record_audio">record audio</string>
+ <string name="app_ops_send_mms">send an MMS message</string>
+ <string name="app_ops_send_sms">send an SMS message</string>
+ <string name="app_ops_start_at_bootup">start at power up</string>
+ <string name="app_ops_toast_window">display toast messages</string>
+ <string name="app_ops_toggle_bluetooth">toggle Bluetooth</string>
+ <string name="app_ops_toggle_nfc">toggle NFC</string>
+ <string name="app_ops_toggle_wifi">toggle Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">control alarm volume</string>
+ <string name="app_ops_use_audio_focus">control the audio focus</string>
+ <string name="app_ops_use_bluetooth_volume">control the Bluetooth volume</string>
+ <string name="app_ops_use_master_volume">control the master volume</string>
+ <string name="app_ops_use_media_buttons">use the media buttons</string>
+ <string name="app_ops_use_media_volume">control the media volume</string>
+ <string name="app_ops_use_notification_volume">control the notification volume</string>
+ <string name="app_ops_use_ring_volume">control the ringtone volume</string>
+ <string name="app_ops_use_vibrate">use haptic feedback</string>
+ <string name="app_ops_use_voice_volume">control the voice call volume</string>
+ <string name="app_ops_write_mms">write an MMS message</string>
+ <string name="app_ops_write_sms">write an SMS message</string>
+ <string name="app_ops_use_fingerprint">use fingerprint</string>
+ <string name="app_ops_add_voicemail">add a voicemail</string>
+ <string name="app_ops_read_phone_state">access phone state</string>
+ <string name="app_ops_scan_wifi">scan Wi-Fi networks</string>
+ <string name="app_ops_change_wallpaper">change the wallpaper</string>
+ <string name="app_ops_assist_structure">use assist structure</string>
+ <string name="app_ops_assist_screenshot">take a screenshot</string>
+ <string name="app_ops_use_body_sensors">use body sensors</string>
+ <string name="app_ops_read_cell_broadcasts">read cell broadcasts</string>
+ <string name="app_ops_mock_location">mock your location</string>
+ <string name="app_ops_read_external_storage">read external storage</string>
+ <string name="app_ops_write_external_storage">write external storage</string>
+ <string name="app_ops_turn_on_screen">turn the screen on</string>
+ <string name="app_ops_get_accounts">get device accounts</string>
+ <string name="app_ops_wifi_change">change Wi-Fi state</string>
+ <string name="app_ops_su">get root access</string>
+ <string name="lock_to_app_toast_no_navbar">To unpin this screen, touch and hold the Back button.</string>
+ <string name="live_display_auto">Automatic</string>
+ <string name="live_display_auto_summary">Automatically adjust color temperature of screen after sunset and sunrise</string>
+ <string name="live_display_off">Off</string>
+ <string name="live_display_off_summary">Disable all adjustments</string>
+ <string name="live_display_day">Day</string>
+ <string name="live_display_day_summary">Use day settings only</string>
+ <string name="live_display_night">Night</string>
+ <string name="live_display_night_summary">Use night settings only</string>
+ <string name="live_display_outdoor">Outdoor (bright sun)</string>
+ <string name="live_display_outdoor_summary">Use outdoor settings only</string>
+ <string name="live_display_hint">LiveDisplay can help reduce eyestrain and help you sleep at night. Click here to try it out!</string>
+ <string name="tethered_notification_no_device_message">No connected device</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> connected device</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> connected devices</string>
+</resources>
diff --git a/core/res/res/values-eo/cm_strings.xml b/core/res/res/values-eo/cm_strings.xml
new file mode 100644
index 0000000..3c9f036
--- /dev/null
+++ b/core/res/res/values-eo/cm_strings.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ekrankopio</string>
+ <string name="permlab_receiveProtectedSms">Alvenis protektita SMS</string>
+ <string name="permdesc_receiveProtectedSms">Permesi al la aplikaĵo ricevi alvenintan protektitan SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">ŝanĝi liston de protektitaj SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Permesi al la aplikaĵo ŝanĝi la liston de protektitaj SMS.</string>
+ <string name="permgrouplab_security">Sekureco</string>
+ <string name="permgroupdesc_security">Permesoj rilataj al aparata sekureca informo.</string>
+ <string name="permlab_readPhoneBlacklist">legi telefonan nigran liston</string>
+ <string name="permdesc_readPhoneBlacklist">Permesas al aplikaĵo lefi informon pri telefon-numeroj, kiuj estas blokitaj por alvenantaj alvokoj aŭ mesaĝoj.</string>
+ <string name="permlab_changePhoneBlacklist">ŝanĝi telefonan nigran liston</string>
+ <string name="permdesc_changePhoneBlacklist">Permesas al aplikaĵo ŝanĝi telefon-numerojn, kiuj estas blokitaj por alvenintaj alvokoj aŭ mesaĝoj.</string>
+ <string name="permlab_setKeyguardWallpaper">difini la ŝlosan ekranfonon</string>
+ <string name="permdesc_setKeyguardWallpaper">Permesas al aplikaĵo ŝanĝi la ŝlosan fonekranon.</string>
+ <string name="global_action_reboot">Relanĉi</string>
+ <string name="global_action_current_user">Nuna</string>
+ <string name="reboot_reboot">Relanĉi</string>
+ <string name="reboot_recovery">Riparado</string>
+ <string name="reboot_bootloader">Praŝargilo</string>
+ <string name="reboot_download">Elŝuti</string>
+ <string name="reboot_soft">Varma relanĉado</string>
+ <string name="reboot_title">Relanĉado</string>
+ <string name="reboot_confirm" product="tablet">Via tabulo relanĉiĝos.</string>
+ <string name="reboot_confirm" product="default">Via telefono relanĉiĝos.</string>
+ <string name="reboot_progress">Relanĉado\u2026</string>
+ <string name="app_killed_message">Aplikaĵo mortigita</string>
+ <string name="adb_net_active_notification_title">reta ADB ŝaltita</string>
+ <string name="adb_both_active_notification_title">ADB sur USB &amp; reto aktiva</string>
+ <string name="adb_active_generic_notification_message">Tuŝeti por malŝalti sencimigon.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; reto</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Reto</string>
+ <string name="permlab_interceptPackageLaunch">interkapti lanĉadon de aplikaĵo</string>
+ <string name="stylus_app_not_installed">%s ne estas instalita</string>
+ <string name="permlab_changePrivacyGuardState">ŝalti aŭ malsălti protektadon de datumoj</string>
+ <string name="permdesc_changePrivacyGuardState">Permesas al la aplikaĵo ŝanĝi ĉu alia aplikaĵo funkcias kun protektado de datumoj. Kiam aplikaĵo funkcias kun protektado de datumoj, ĝi ne rajtos aliri al personaj datumoj kiel kontaktuloj, protokoloj de alvokoj, aŭ mesaĝoj.</string>
+ <string name="privacy_guard_notification">Protektado de datumoj aktiva</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> ne povos aliri personajn datumojn</string>
+ <string name="privacy_guard_dialog_title">Protektado de datumoj</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> ŝatus <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Memori mian elekton</string>
+ <string name="app_ops_access_camera">aliri al fotilo</string>
+ <string name="app_ops_access_location">aliri al via loko</string>
+ <string name="app_ops_access_notifications">legi viajn atentigojn</string>
+ <string name="app_ops_activate_vpn">aktivigi VPN</string>
+ <string name="app_ops_auto_start">lanĉiĝi dum sistema ŝaltado</string>
+ <string name="app_ops_delete_call_log">forigi vian protokolon de alvokoj</string>
+ <string name="app_ops_delete_contacts">forigi viajn kontaktulojn</string>
+ <string name="app_ops_delete_mms">forigi viajn MMS mesaĝojn</string>
+ <string name="app_ops_delete_sms">forigi viajn SMS mesaĝojn</string>
+ <string name="app_ops_draw_on_top">movi fenestron supren</string>
+ <string name="app_ops_get_usage_stats">akiri statistikojn pri la uzado de aplikaĵo</string>
+ <string name="app_ops_keep_device_awake">konservi vian aparaton veka</string>
+ <string name="app_ops_make_phone_call">fari voĉan alvokon</string>
+ <string name="app_ops_modify_calendar">ĝistatigi vian kalendaron</string>
+ <string name="app_ops_modify_call_log">ĝisdatigi la protokolon de alvokoj</string>
+ <string name="app_ops_modify_clipboard">ŝanĝi la tondejon</string>
+ <string name="app_ops_modify_contacts">ĝisdatiĝi viajn kontaktulojn</string>
+ <string name="app_ops_modify_settings">ĝisdatigi sisteman agordon</string>
+ <string name="app_ops_mute_unmute_microphone">mutigi/malmutigi la mikrofonon</string>
+ <string name="app_ops_play_audio">ludi sonojn</string>
+ <string name="app_ops_post_notification">sendi atentigon</string>
+ <string name="app_ops_project_media">projetko medio</string>
+ <string name="app_ops_read_calendar">legi vian kalendaron</string>
+ <string name="app_ops_read_call_log">legi la protokolon de alvokoj</string>
+ <string name="app_ops_read_clipboard">legi la tondejon</string>
+ <string name="app_ops_read_contacts">legi viajn kontaktulojn</string>
+ <string name="app_ops_read_mms">legi viajn MMS mesaĝojn</string>
+ <string name="app_ops_read_sms">legi viajn SMS mesaĝojn</string>
+ <string name="app_ops_receive_sms">ricevi SMS mesaĝon</string>
+ <string name="app_ops_record_audio">registri sonon</string>
+ <string name="app_ops_send_mms">sendi MMS mesaĝon</string>
+ <string name="app_ops_send_sms">sendi SMS mesaĝon</string>
+ <string name="app_ops_start_at_bootup">lanĉiĝi dum sistema ŝaltado</string>
+ <string name="app_ops_toast_window">afiŝi atentigojn</string>
+ <string name="app_ops_toggle_bluetooth">(mal)ŝalti Bludenton</string>
+ <string name="app_ops_toggle_nfc">(mal)ŝalti NFC</string>
+ <string name="app_ops_use_alarm_volume">kontroli laŭtecon de alarmoj</string>
+ <string name="app_ops_use_audio_focus">kontroli sonan fokuson</string>
+ <string name="app_ops_use_bluetooth_volume">kontroli laŭtecon de Bludento</string>
+ <string name="app_ops_use_master_volume">kontroli la cêfan laŭtecon</string>
+ <string name="app_ops_use_media_buttons">uzi la aŭdvidajn butonojn</string>
+ <string name="app_ops_use_media_volume">kontroli laŭtecon de aŭdvidaj</string>
+ <string name="app_ops_use_notification_volume">kontroli laŭtecon de atentigoj</string>
+ <string name="app_ops_use_ring_volume">kontroli laŭtecon de sonoro</string>
+ <string name="app_ops_use_vibrate">uzi tuŝeblan retroefikon</string>
+ <string name="app_ops_use_voice_volume">kontroli laŭtecon de voĉaj alvokoj</string>
+ <string name="app_ops_write_mms">skribi MMS-mesaĝon</string>
+ <string name="app_ops_write_sms">skribi SMS-mesaĝon</string>
+ <string name="app_ops_su">akiri radikuzantajn permesojn</string>
+ <string name="lock_to_app_toast_no_navbar">Por malŝlosi tiun ekranon, tuŝetu kaj tenu la Reen butonon.</string>
+ <string name="live_display_auto">Aŭtomata</string>
+ <string name="live_display_auto_summary">Aŭtomate alĝustigi kolortemperaturon de la ekrano post sunsubiro kaj suniĝo</string>
+ <string name="live_display_off">For</string>
+ <string name="live_display_off_summary">Malŝalti ĉiujn ĝustigojn</string>
+ <string name="live_display_day">Tago</string>
+ <string name="live_display_day_summary">Uzi nur tagajn agordojn</string>
+ <string name="live_display_night">Nokto</string>
+ <string name="live_display_night_summary">Uzi nur noktajn agordojn</string>
+ <string name="live_display_outdoor">Ekstere (brila suno)</string>
+ <string name="live_display_outdoor_summary">Uzi nur eksterajn parametrojn</string>
+ <string name="live_display_hint">LiveDisplay povas helpi vin malgrandigi okulo-streĉon nokte. Alklaku tie por provi!</string>
+ <string name="tethered_notification_no_device_message">Neniu konektata aparato</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> konektita aparato</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> konektitaj aparatoj</string>
+</resources>
diff --git a/core/res/res/values-eo/strings.xml b/core/res/res/values-eo/strings.xml
new file mode 100644
index 0000000..907df4e
--- /dev/null
+++ b/core/res/res/values-eo/strings.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="byteShort">B</string>
+ <string name="kilobyteShort">KB</string>
+ <string name="megabyteShort">MB</string>
+ <string name="gigabyteShort">GB</string>
+ <string name="terabyteShort">TB</string>
+ <string name="petabyteShort">PB</string>
+ <string name="untitled">&lt;Sentitola&gt;</string>
+ <string name="emptyPhoneNumber">(Neniu telefonnumero)</string>
+ <string name="unknownName">Nekonate</string>
+ <string name="defaultVoiceMailAlphaTag">Voĉa mesaĝo</string>
+ <string name="passwordIncorrect">Nekorekta pasvorto.</string>
+ <string name="mmiComplete">MMI kompleta.</string>
+ <string name="badPin">La malnova PIN kiun vi tajpis estas nekorekta.</string>
+ <string name="imei">IMEI</string>
+ <string name="meid">MEID</string>
+ <string name="PwdMmi">Pasvorta ŝanĝo</string>
+ <string name="PinMmi">Ŝanĝo de PIN</string>
+ <string name="DndMmi">Ne ĝenu</string>
+ <string name="serviceClassData">Datumo</string>
+ <string name="me">Mi</string>
+ <string name="recent_tasks_title">Lasttempaj</string>
+ <string name="global_action_bug_report">Cimraporto</string>
+ <string name="global_action_settings">Agordoj</string>
+ <string name="safeMode">Sekura reĝimo</string>
+ <string name="managed_profile_label">Laborejo</string>
+ <string name="permgrouplab_calendar">Kalendaro</string>
+ <string name="permgrouplab_storage">Memorilo</string>
+ <string name="permgrouplab_microphone">Mikrofono</string>
+ <string name="permgroupdesc_microphone">registri sonon</string>
+ <string name="permgrouplab_camera">Fotilo</string>
+ <string name="permgrouplab_phone">Telefono</string>
+ <string name="permlab_readContacts">legi viajn kontaktulojn</string>
+ <string name="permlab_readCallLog">legi alvokan protokolon</string>
+ <string name="permlab_recordAudio">registri sonon</string>
+ <string name="permlab_accessNotifications">atingi atentigojn</string>
+ <string name="phoneTypeCustom">Propra</string>
+ <string name="phoneTypeHome">Hejmo</string>
+ <string name="phoneTypeWork">Laborejo</string>
+ <string name="phoneTypeFaxWork">Laboreja faksilo</string>
+ <string name="phoneTypeFaxHome">Hejma faksilo</string>
+ <string name="phoneTypePager">Televokilo</string>
+ <string name="phoneTypeOther">Aliaj</string>
+ <string name="phoneTypeCallback">Revoko</string>
+ <string name="phoneTypeCar">Aŭtomobilo</string>
+ <string name="phoneTypeOtherFax">Plia telekopiilo</string>
+ <string name="phoneTypeTelex">Telekso</string>
+ <string name="eventTypeCustom">Propra</string>
+ <string name="eventTypeBirthday">Naskiĝtago</string>
+ <string name="eventTypeAnniversary">Datreveno</string>
+ <string name="eventTypeOther">Aliaj</string>
+ <string name="emailTypeCustom">Propra</string>
+ <string name="emailTypeHome">Hejmo</string>
+ <string name="emailTypeWork">Laborejo</string>
+ <string name="emailTypeOther">Aliaj</string>
+ <string name="postalTypeCustom">Propra</string>
+ <string name="postalTypeHome">Hejmo</string>
+ <string name="postalTypeWork">Laborejo</string>
+ <string name="postalTypeOther">Aliaj</string>
+ <string name="imTypeCustom">Propra</string>
+ <string name="imTypeHome">Hejmo</string>
+ <string name="imTypeWork">Laborejo</string>
+ <string name="imTypeOther">Aliaj</string>
+ <string name="imProtocolCustom">Propra</string>
+ <string name="orgTypeWork">Laborejo</string>
+ <string name="orgTypeOther">Aliaj</string>
+ <string name="orgTypeCustom">Propra</string>
+ <string name="relationTypeCustom">Propra</string>
+ <string name="relationTypeChild">Ido</string>
+ <string name="relationTypeManager">Estro</string>
+ <string name="relationTypeSpouse">Edz(in)o</string>
+ <string name="sipAddressTypeCustom">Propra</string>
+ <string name="sipAddressTypeHome">Hejmo</string>
+ <string name="sipAddressTypeWork">Laborejo</string>
+ <string name="sipAddressTypeOther">Aliaj</string>
+ <string name="lockscreen_pattern_wrong">Provu denove</string>
+ <string name="lockscreen_password_wrong">Provu denove</string>
+ <string name="lockscreen_transport_pause_description">Paŭzi</string>
+ <string name="lockscreen_transport_play_description">Ludi</string>
+ <string name="lockscreen_transport_stop_description">Haltigi</string>
+ <string name="lockscreen_transport_rew_description">Reen</string>
+ <string name="emergency_calls_only" msgid="2485604591272668370">Nur urĝaj alvokoj</string>
+ <string name="lockscreen_glogin_username_hint">Uzantnomo (retmesaĝo)</string>
+ <string name="lockscreen_glogin_password_hint">Pasvorto</string>
+ <string name="lockscreen_glogin_submit_button">Aliĝi</string>
+ <string name="lockscreen_unlock_label">Malŝlosi</string>
+ <string name="keyguard_accessibility_widget_empty_slot">Malplene</string>
+ <string name="keyguard_accessibility_status">Stato</string>
+ <string name="keyguard_accessibility_camera">Fotilo</string>
+ <string name="granularity_label_word">vorto</string>
+ <string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
+ <string name="hour_cap_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="PM">%p</xliff:g>"</string>
+ <string name="factorytest_reboot">Restartigi</string>
+ <string name="save_password_label">Konfirmi</string>
+ <string name="autofill_state">Stato</string>
+ <string name="autofill_department">Distrikto</string>
+ <string name="autofill_area">Areo</string>
+ <string name="save_password_notnow">Ne nun</string>
+ <string name="save_password_remember">Memorigi</string>
+ <string name="save_password_never">Neniam</string>
+ <string name="menu_space_shortcut_label">spaco</string>
+ <string name="menu_delete_shortcut_label">forigi</string>
+ <string name="search_go">Serĉi</string>
+ <string name="searchview_description_search">Serĉi</string>
+ <string name="searchview_description_voice">Voĉa serĉado</string>
+ <string name="oneMonthDurationPast">antaŭ 1 monato</string>
+ <string name="last_month">Lastmonate</string>
+ <string name="day">tago</string>
+ <string name="days">tagoj</string>
+ <string name="hour">horo</string>
+ <string name="hours">horoj</string>
+ <string name="week">semajno</string>
+ <string name="weeks">semajnoj</string>
+ <string name="year">jaro</string>
+ <string name="years">jaroj</string>
+ <string name="relative_time">"<xliff:g id="date" example="4 hours ago">%1$s</xliff:g>, <xliff:g id="time" example="11:00 am">%2$s</xliff:g>"</string>
+ <string name="selectAll">Elekti ĉiujn</string>
+ <string name="cut">Eltondi</string>
+ <string name="copy">Kopii</string>
+ <string name="paste">Alglui</string>
+ <string name="delete">Forigi</string>
+ <string name="copyUrl">Kopii la URL-on</string>
+ <string name="deleteText">Forigi</string>
+ <string name="cancel">Nuligi</string>
+ <string name="no">Nuligi</string>
+ <string name="loading">Ŝarĝado\u2026</string>
+ <string name="capital_on">EK</string>
+ <string name="capital_off">FOR</string>
+ <string name="whichViewApplication">Malfermi per</string>
+ <string name="force_close">Konfirmi</string>
+ <string name="screen_compat_mode_scale">Skali</string>
+ <string name="volume_music">Aŭdvida laŭteco</string>
+ <string name="volume_alarm">Laŭteco de alarmo</string>
+ <string name="volume_notification">Atentiga laŭteco</string>
+ <string name="volume_icon_description_bluetooth">Bludanta laŭteco</string>
+ <string name="sms_control_yes">Permesi</string>
+ <string name="sms_control_no">Malpermesi</string>
+ <string name="sms_short_code_confirm_allow">Sendi</string>
+ <string name="sms_short_code_confirm_deny">Nuligi</string>
+ <string name="sms_short_code_remember_choice">Memori mian elekton</string>
+ <string name="sim_done_button">Farite</string>
+ <string name="sim_restart_button">Restartigi</string>
+ <string name="date_time_set">Agordi</string>
+ <string name="date_time_done">Farite</string>
+ <string name="dlg_ok">Konfirmi</string>
+ <string name="hardware">Aparataro</string>
+ <string name="ime_action_go">Ek</string>
+ <string name="ime_action_search">Serĉi</string>
+ <string name="ime_action_send">Sendi</string>
+ <string name="ime_action_next">Sekva</string>
+ <string name="ime_action_done">Farite</string>
+ <string name="ime_action_default">Lanĉi</string>
+ <string name="allow">Permesi</string>
+ <string name="deny">Malpermesi</string>
+ <string name="accessibility_binding_label">Alirebleco</string>
+ <string name="upload_file">Elekti dosieron</string>
+ <string name="reset">Reagordi</string>
+ <string name="submit">Sendi</string>
+ <string name="back_button_label">Reen</string>
+ <string name="next_button_label">Sekva</string>
+ <string name="skip_button_label">Preterpasi</string>
+ <string name="action_mode_done">Farite</string>
+ <string name="progress_erasing" product="nosdcard">Forviŝado de USB-memorilo\u2026</string>
+ <string name="progress_erasing" product="default">Forviŝado de la SD-karto\u2026</string>
+ <string name="share">Komunigi</string>
+ <string name="find">Serĉi</string>
+ <string name="gpsVerifYes">Jes</string>
+ <string name="gpsVerifNo">Ne</string>
+ <string name="keyboardview_keycode_alt">Alt-klavo</string>
+ <string name="keyboardview_keycode_cancel">Nuligi</string>
+ <string name="keyboardview_keycode_delete">Forigi</string>
+ <string name="keyboardview_keycode_done">Farite</string>
+ <string name="keyboardview_keycode_shift">Majuskliga klavo</string>
+ <string name="action_menu_overflow_description">Pliaj opcioj</string>
+ <string name="storage_sd_card">SD-karto</string>
+ <string name="storage_usb">USB memorilo</string>
+ <string name="list_delimeter">", "</string>
+ <string name="activity_resolver_use_always">Ĉiam</string>
+ <string name="default_audio_route_name" product="tablet">Tabulkomputilo</string>
+ <string name="default_audio_route_name" product="default">Telefono</string>
+ <string name="default_audio_route_name_headphones">Kapaŭskultilo</string>
+ <string name="default_audio_route_category_name">Sistemo</string>
+ <string name="media_route_chooser_extended_settings">Agordoj</string>
+ <string name="media_route_controller_disconnect">Malkonekti</string>
+ <string name="media_route_status_available">Disponebla</string>
+ <string name="media_route_status_not_available">Ne atingebla</string>
+ <string name="kg_login_username_hint">Uzantnomo (retmesaĝo)</string>
+ <string name="kg_login_password_hint">Pasvorto</string>
+ <string name="kg_login_submit_button">Aliĝi</string>
+ <string name="kg_login_checking_password">Kontrolado de konto\u2026</string>
+ <string name="kg_text_message_separator" product="default">" \u2014 "</string>
+ <string name="kg_reordering_delete_drop_target_text">Forigi</string>
+ <string name="owner_name" msgid="3879126011135546571">Posedanto</string>
+ <string name="error_message_title">Eraro</string>
+ <string name="revoke">Senvalidigi</string>
+ <string name="mediasize_na_gvrnmt_letter">Regada letero</string>
+ <string name="mediasize_na_legal">Laŭleĝa avizo</string>
+ <string name="mediasize_na_tabloid">Etformata gazeto</string>
+ <string name="write_fail_reason_cancelled">Nuligite</string>
+ <string name="reason_unknown">nekonate</string>
+ <string name="done_label">Farite</string>
+ <string name="zen_mode_feature_name">Ne ĝenu</string>
+ <string name="floating_toolbar_open_overflow_description">Pliaj opcioj</string>
+</resources>
diff --git a/core/res/res/values-es/cm_strings.xml b/core/res/res/values-es/cm_strings.xml
new file mode 100644
index 0000000..eba3ba5
--- /dev/null
+++ b/core/res/res/values-es/cm_strings.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Captura de pantalla</string>
+ <string name="permlab_receiveProtectedSms">recibir SMS protegidos</string>
+ <string name="permdesc_receiveProtectedSms">Permite que la aplicación reciba mensajes SMS entrantes protegidos.</string>
+ <string name="permlab_modifyProtectedSmsList">modificar lista de SMS protegidos</string>
+ <string name="permdesc_modifyProtectedSmsList">Permite que la aplicación modifique la lista de contactos SMS protegidos.</string>
+ <string name="permgrouplab_security">Seguridad</string>
+ <string name="permgroupdesc_security">Permisos relacionados con la seguridad de la información del dispositivo.</string>
+ <string name="permlab_readPhoneBlacklist">leer lista negra del teléfono</string>
+ <string name="permdesc_readPhoneBlacklist">Permite que la aplicación lea la información sobre los números de teléfono bloqueados para llamadas o mensajes entrantes.</string>
+ <string name="permlab_changePhoneBlacklist">cambiar la lista negra del teléfono</string>
+ <string name="permdesc_changePhoneBlacklist">Permite que la aplicación cambie los números de teléfono bloqueados de llamadas o mensajes entrantes.</string>
+ <string name="permlab_setKeyguardWallpaper">establecer fondo de pantalla de bloqueo</string>
+ <string name="permdesc_setKeyguardWallpaper">Permite que la aplicación establezca el fondo de pantalla de bloqueo.</string>
+ <string name="global_action_reboot">Reiniciar</string>
+ <string name="global_action_current_user">Actual</string>
+ <string name="reboot_reboot">Reiniciar</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Modo Bootloader</string>
+ <string name="reboot_download">Descargar</string>
+ <string name="reboot_soft">Reinicio rápido</string>
+ <string name="reboot_title">Reiniciar</string>
+ <string name="reboot_confirm" product="tablet">El tablet se reiniciará.</string>
+ <string name="reboot_confirm" product="default">El teléfono se reiniciará.</string>
+ <string name="reboot_progress">Reiniciando\u2026</string>
+ <string name="app_killed_message">Aplicación finalizada</string>
+ <string name="adb_net_active_notification_title">ADB sobre red activado</string>
+ <string name="adb_both_active_notification_title">ADB sobre USB y red activado</string>
+ <string name="adb_active_generic_notification_message">Toca para desactivar la depuración.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB y red</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Red</string>
+ <string name="permlab_interceptPackageLaunch">interceptar la ejecución de aplicaciones</string>
+ <string name="stylus_app_not_installed">%s no está instalada</string>
+ <string name="silent_mode_priority">Prioridad</string>
+ <string name="silent_mode_none">Ninguno</string>
+ <string name="subscription_change_disabled_wifi_ap">Zona Wi-Fi desactivada debido a un cambio de suscripción en la SIM</string>
+ <string name="notify_turn_wifi_off_title">Desactivar Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">activar o desactivar el protector de privacidad</string>
+ <string name="permdesc_changePrivacyGuardState">Permite que la aplicación cambie el estado de privacidad de otra. Cuando una aplicación se ejecuta con la privacidad activada, no podrá acceder a los datos personales, tales como contactos, mensajes o registros de llamadas.</string>
+ <string name="privacy_guard_notification">Privacidad activada</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> no podrá acceder a los datos personales</string>
+ <string name="privacy_guard_dialog_title">Privacidad</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> quiere <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Recordar mi elección</string>
+ <string name="app_ops_access_camera">acceder a la cámara</string>
+ <string name="app_ops_access_location">acceder a tu ubicación</string>
+ <string name="app_ops_access_notifications">leer tus notificaciones</string>
+ <string name="app_ops_activate_vpn">activar VPN</string>
+ <string name="app_ops_auto_start">ejecutar al inicio</string>
+ <string name="app_ops_delete_call_log">borrar el registro de llamadas</string>
+ <string name="app_ops_delete_contacts">borrar tus contactos</string>
+ <string name="app_ops_delete_mms">eliminar tus mensajes MMS</string>
+ <string name="app_ops_delete_sms">eliminar tus mensajes MMS</string>
+ <string name="app_ops_draw_on_top">dibujar ventanas encima</string>
+ <string name="app_ops_get_usage_stats">obtener estadísticas de uso de la aplicación</string>
+ <string name="app_ops_keep_device_awake">mantener tu dispositivo encendido</string>
+ <string name="app_ops_make_phone_call">realizar una llamada</string>
+ <string name="app_ops_modify_calendar">actualizar tu calendario</string>
+ <string name="app_ops_modify_call_log">actualizar el registro de llamadas</string>
+ <string name="app_ops_modify_clipboard">modificar el portapapeles</string>
+ <string name="app_ops_modify_contacts">actualizar tus contactos</string>
+ <string name="app_ops_modify_settings">actualizar los ajustes del sistema</string>
+ <string name="app_ops_mute_unmute_microphone">activar/desactivar el micrófono</string>
+ <string name="app_ops_play_audio">reproducir sonido</string>
+ <string name="app_ops_post_notification">publicar una notificación</string>
+ <string name="app_ops_project_media">proyectar medios</string>
+ <string name="app_ops_read_calendar">leer tu calendario</string>
+ <string name="app_ops_read_call_log">leer el registro de llamadas</string>
+ <string name="app_ops_read_clipboard">leer el portapapeles</string>
+ <string name="app_ops_read_contacts">leer tus contactos</string>
+ <string name="app_ops_read_mms">leer tus mensajes MMS</string>
+ <string name="app_ops_read_sms">leer tus mensajes SMS</string>
+ <string name="app_ops_receive_sms">recibir un mensaje SMS</string>
+ <string name="app_ops_record_audio">grabar sonido</string>
+ <string name="app_ops_send_mms">enviar un mensaje MMS</string>
+ <string name="app_ops_send_sms">enviar un mensaje SMS</string>
+ <string name="app_ops_start_at_bootup">ejecutar al inicio</string>
+ <string name="app_ops_toast_window">mostrar notificaciones emergentes</string>
+ <string name="app_ops_toggle_bluetooth">alternar Bluetooth</string>
+ <string name="app_ops_toggle_nfc">alternar NFC</string>
+ <string name="app_ops_toggle_wifi">alternar Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">controlar el volumen de la alarma</string>
+ <string name="app_ops_use_audio_focus">controlar volumen del sonido</string>
+ <string name="app_ops_use_bluetooth_volume">controlar el volumen de Bluetooth</string>
+ <string name="app_ops_use_master_volume">controlar el volumen</string>
+ <string name="app_ops_use_media_buttons">usar los botones multimedia</string>
+ <string name="app_ops_use_media_volume">controlar el volumen multimedia</string>
+ <string name="app_ops_use_notification_volume">controlar el volumen de notificaciones</string>
+ <string name="app_ops_use_ring_volume">controlar el volumen del tono de llamada</string>
+ <string name="app_ops_use_vibrate">usar la respuesta háptica</string>
+ <string name="app_ops_use_voice_volume">controlar el volumen del teléfono</string>
+ <string name="app_ops_write_mms">escribir un mensaje MMS</string>
+ <string name="app_ops_write_sms">escribir un mensaje SMS</string>
+ <string name="app_ops_use_fingerprint">usar huella digital</string>
+ <string name="app_ops_add_voicemail">añadir un mensaje de voz</string>
+ <string name="app_ops_read_phone_state">acceder al estado del móvil</string>
+ <string name="app_ops_scan_wifi">escanear redes Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">cambiar el fondo de pantalla</string>
+ <string name="app_ops_assist_structure">utilizar estructura de asistencia</string>
+ <string name="app_ops_assist_screenshot">tomar una captura de pantalla</string>
+ <string name="app_ops_use_body_sensors">utilizar sensores corporales</string>
+ <string name="app_ops_read_cell_broadcasts">leer transmisiones celulares</string>
+ <string name="app_ops_mock_location">simular tu ubicación</string>
+ <string name="app_ops_read_external_storage">leer almacenamiento externo</string>
+ <string name="app_ops_write_external_storage">escribir el almacenamiento externo</string>
+ <string name="app_ops_turn_on_screen">encender la pantalla</string>
+ <string name="app_ops_get_accounts">obtener cuentas de dispositivo</string>
+ <string name="app_ops_wifi_change">cambiar estado de Wi-Fi</string>
+ <string name="app_ops_su">obtener acceso administrativo</string>
+ <string name="lock_to_app_toast_no_navbar">Para liberar esta pantalla, mantén pulsado el botón Atrás.</string>
+ <string name="live_display_auto">Automático</string>
+ <string name="live_display_auto_summary">Ajustar automáticamente la temperatura del color de pantalla con el amanecer y el anochecer</string>
+ <string name="live_display_off">Desactivado</string>
+ <string name="live_display_off_summary">Desactivar todos los ajustes</string>
+ <string name="live_display_day">Día</string>
+ <string name="live_display_day_summary">Utilizar solo los ajustes de día</string>
+ <string name="live_display_night">Noche</string>
+ <string name="live_display_night_summary">Utilizar solo los ajustes de noche</string>
+ <string name="live_display_outdoor">Al aire libre (luz del sol)</string>
+ <string name="live_display_outdoor_summary">Utilizar solo los ajustes al aire libre</string>
+ <string name="live_display_hint">LiveDisplay puede reducir la fatiga visual y ayudar a dormir por la noche. ¡Toca aquí para probarlo!</string>
+ <string name="tethered_notification_no_device_message">Ningún dispositivo conectado</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivo conectado</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivos conectados</string>
+</resources>
diff --git a/core/res/res/values-et-rEE/cm_strings.xml b/core/res/res/values-et-rEE/cm_strings.xml
new file mode 100644
index 0000000..c0843d8
--- /dev/null
+++ b/core/res/res/values-et-rEE/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ekraanipilt</string>
+ <string name="permlab_receiveProtectedSms">saa kaitstud SMSe</string>
+ <string name="permdesc_receiveProtectedSms">Lubab rakendusel vastu võtta sissetuleva kaitstud SMSi.</string>
+ <string name="permlab_modifyProtectedSmsList">muuda kaitstud SMS nimekirja</string>
+ <string name="permdesc_modifyProtectedSmsList">Lubab rakendusel muuta kaitstud SMS aadressiloendit.</string>
+ <string name="permgrouplab_security">Turvalisus</string>
+ <string name="permgroupdesc_security">Õigused on seotud seadme turvalisuse teabega.</string>
+ <string name="permlab_readPhoneBlacklist">lugeda telefoni musta nimekirja</string>
+ <string name="permdesc_readPhoneBlacklist">Lubab rakendusel lugeda teavet telefoninumbrite kohta, mis on sissetulevate kõnede ja sõnumite jaoks blokeeritud.</string>
+ <string name="permlab_changePhoneBlacklist">muuta telefoni musta nimekirja</string>
+ <string name="permdesc_changePhoneBlacklist">Annab rakendusele õiguse muuta sissetulevate kõnede ja sõnumite jaoks blokeeritud numbreid.</string>
+ <string name="permlab_setKeyguardWallpaper">muuta lukuekraani pilti</string>
+ <string name="permdesc_setKeyguardWallpaper">Lubab rakendusel muuta lukustusekraani taustapilti.</string>
+ <string name="global_action_reboot">Taaskäivitamine</string>
+ <string name="global_action_current_user">Praegune</string>
+ <string name="reboot_reboot">Taaskäivita</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download režiim</string>
+ <string name="reboot_soft">Poolik taaskäivitus</string>
+ <string name="reboot_title">Taaskäivita</string>
+ <string name="reboot_confirm" product="tablet">Teie tahvelarvuti taaskäivitub.</string>
+ <string name="reboot_confirm" product="default">Teie telefon taaskäivitub.</string>
+ <string name="reboot_progress">Taaskäivitamine\u2026</string>
+ <string name="app_killed_message">Rakendus suletud</string>
+ <string name="adb_net_active_notification_title">ADB üle võrgu aktiveeritud</string>
+ <string name="adb_both_active_notification_title">ADB üle USB &amp; võrgu aktiveeritud</string>
+ <string name="adb_active_generic_notification_message">Puuduta silumise lõpetamiseks.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; võrk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Võrk</string>
+ <string name="permlab_interceptPackageLaunch">rakenduse käivitamise katkestamine</string>
+ <string name="stylus_app_not_installed">%s ei ole installitud</string>
+ <string name="silent_mode_priority">Prioriteet</string>
+ <string name="silent_mode_none">Puudub</string>
+ <string name="subscription_change_disabled_wifi_ap">WiFi hotspot lülitati välja kuna muutus SIM kaardi teenused</string>
+ <string name="notify_turn_wifi_off_title">Lülita WiFi välja</string>
+ <string name="permlab_changePrivacyGuardState">lubada või keelata privaatsuskaitset</string>
+ <string name="permdesc_changePrivacyGuardState">Sellega lubate muuta mõne muu rakenduse käivitumist Privaatsuskaitsega. Kui rakendus töötab sisselülitatud Privaatsuskaitsega, puudub rakendusel ligipääs isiklikele andmetele nagu kontaktid, kõnelogid või sõnumid.</string>
+ <string name="privacy_guard_notification">Privaatsuskaitse aktiveeritud</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> ei pääse ligi isiklikele andmetele</string>
+ <string name="privacy_guard_dialog_title">Privaatsuskaitse</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> tahab <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Jäta meelde minu valik</string>
+ <string name="app_ops_access_camera">kontrollida kaamerat</string>
+ <string name="app_ops_access_location">kontrollida asukohta</string>
+ <string name="app_ops_access_notifications">lugeda teateid</string>
+ <string name="app_ops_activate_vpn">aktiveeri VPN</string>
+ <string name="app_ops_auto_start">käivitada sisselülitamisel</string>
+ <string name="app_ops_delete_call_log">kustutada kõnelogi</string>
+ <string name="app_ops_delete_contacts">kustutada kontakte</string>
+ <string name="app_ops_delete_mms">kustutada MMS sõnumeid</string>
+ <string name="app_ops_delete_sms">kustutada SMS sõnumeid</string>
+ <string name="app_ops_draw_on_top">joonistada aknaid peale</string>
+ <string name="app_ops_get_usage_stats">saada rakenduse kasutamise statistikat</string>
+ <string name="app_ops_keep_device_awake">hoida seade ärkvel</string>
+ <string name="app_ops_make_phone_call">teha telefoni kõnet</string>
+ <string name="app_ops_modify_calendar">värskendada kalendrit</string>
+ <string name="app_ops_modify_call_log">värskendada kõnelogi</string>
+ <string name="app_ops_modify_clipboard">muuta lõikelauda</string>
+ <string name="app_ops_modify_contacts">värskendada kontakte</string>
+ <string name="app_ops_modify_settings">värskendada süsteemiseadeid</string>
+ <string name="app_ops_mute_unmute_microphone">välja/sisse lülitada mikrofoni</string>
+ <string name="app_ops_play_audio">mängida heli</string>
+ <string name="app_ops_post_notification">postitada teateid</string>
+ <string name="app_ops_project_media">projekteerida meediat</string>
+ <string name="app_ops_read_calendar">vaadata kalendrit</string>
+ <string name="app_ops_read_call_log">vaadata kõnelogi</string>
+ <string name="app_ops_read_clipboard">vaadata lõikelauda</string>
+ <string name="app_ops_read_contacts">vaadata kontakte</string>
+ <string name="app_ops_read_mms">lugeda MMS sõnumeid</string>
+ <string name="app_ops_read_sms">lugeda SMS sõnumeid</string>
+ <string name="app_ops_receive_sms">võtta vastu SMS sõnum</string>
+ <string name="app_ops_record_audio">salvestada heli</string>
+ <string name="app_ops_send_mms">saata MMS sõnum</string>
+ <string name="app_ops_send_sms">saata SMS sõnum</string>
+ <string name="app_ops_start_at_bootup">käivitada sisselülitamisel</string>
+ <string name="app_ops_toast_window">näidata lühisõnumeid</string>
+ <string name="app_ops_toggle_bluetooth">lülitada Bluetooth\'i</string>
+ <string name="app_ops_toggle_nfc">lülitada NFC</string>
+ <string name="app_ops_use_alarm_volume">muuta alarmi helitugevust</string>
+ <string name="app_ops_use_audio_focus">muuta audio fookust</string>
+ <string name="app_ops_use_bluetooth_volume">muuta Bluetooth heli tugevust</string>
+ <string name="app_ops_use_master_volume">muuta üldist helitugevust</string>
+ <string name="app_ops_use_media_buttons">kasutada meedia nuppe</string>
+ <string name="app_ops_use_media_volume">muuta meedia helitugevust</string>
+ <string name="app_ops_use_notification_volume">muuta teavituse helitugevust</string>
+ <string name="app_ops_use_ring_volume">muuta helina tugevust</string>
+ <string name="app_ops_use_vibrate">kasutada puute vibratsiooni</string>
+ <string name="app_ops_use_voice_volume">muuta telefoni kõne helitugevust</string>
+ <string name="app_ops_write_mms">kirjutada MMS sõnumit</string>
+ <string name="app_ops_write_sms">kirjutada SMS sõnumit</string>
+ <string name="app_ops_su">saada root ligipääsu</string>
+ <string name="lock_to_app_toast_no_navbar">Selle ekraani vabastamiseks puudutage ja hoidke all Tagasi nuppu.</string>
+ <string name="live_display_auto">Automaatne</string>
+ <string name="live_display_auto_summary">Automaatselt reguleeri ekraani värvitemperaturri pärast päikeseloojangut ja -tõusu</string>
+ <string name="live_display_off">Väljas</string>
+ <string name="live_display_off_summary">Keela kõik kohandused</string>
+ <string name="live_display_day">Päev</string>
+ <string name="live_display_day_summary">Kasuta ainult päeva seadeid</string>
+ <string name="live_display_night">Öö</string>
+ <string name="live_display_night_summary">Kasuta ainult öö seadeid</string>
+ <string name="live_display_outdoor">Õues (ere päike)</string>
+ <string name="live_display_outdoor_summary">Kasuta ainult õue seadeid</string>
+ <string name="live_display_hint">LiveDisplay võimaldab vähendada silmade pinget ja lasta sul öösel magada. Kliki siin et seda proovida!</string>
+ <string name="tethered_notification_no_device_message">Pole ühtegi ühendatud seadet</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> ühendatud seade</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> ühendatud seadet</string>
+</resources>
diff --git a/core/res/res/values-eu-rES/cm_strings.xml b/core/res/res/values-eu-rES/cm_strings.xml
new file mode 100644
index 0000000..e902e97
--- /dev/null
+++ b/core/res/res/values-eu-rES/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Pantaila-argazkia</string>
+ <string name="permlab_receiveProtectedSms">jaso SMS babestua</string>
+ <string name="permdesc_receiveProtectedSms">SMS mezu babestua jasotzea ahalbidetzen dio aplikazioari.</string>
+ <string name="permlab_modifyProtectedSmsList">aldatu SMS babestuen zerrenda</string>
+ <string name="permdesc_modifyProtectedSmsList">SMS babestuen helbide zerrenda aldatzea ahalbidetzen dio aplikazioari.</string>
+ <string name="permgrouplab_security">Segurtasuna</string>
+ <string name="permgroupdesc_security">Gailuaren segurtasun informazioarekin erlazionaturiko baimenak.</string>
+ <string name="permlab_readPhoneBlacklist">Telefonoaren zerrenda beltza irakurri</string>
+ <string name="permdesc_readPhoneBlacklist">Sarrera dei edo SMS mezuak blokeatuta dituzten telefono zenbakien informazioa irakurtzea ahalbidetzen dio aplikazioari.</string>
+ <string name="permlab_changePhoneBlacklist">aldatu telefonoen zerrenda beltza</string>
+ <string name="permdesc_changePhoneBlacklist">Sarrera deiak eta SMS mezuak blokeatuta dituzten zenbakien zerrenda aldatzea ahalbidetzen dio aplikazioari.</string>
+ <string name="permlab_setKeyguardWallpaper">Ezarri blokeo-pantailarako horma-papera</string>
+ <string name="permdesc_setKeyguardWallpaper">Blokeo-pantailarako horma-papera aldatzea ahalbidetzen dio aplikazioari.</string>
+ <string name="global_action_reboot">Berrabiarazi</string>
+ <string name="global_action_current_user">Oraingoa</string>
+ <string name="reboot_reboot">Berrabiarazi</string>
+ <string name="reboot_recovery">Berreskuratzea</string>
+ <string name="reboot_bootloader">Abiarazlea</string>
+ <string name="reboot_download">Deskarga</string>
+ <string name="reboot_soft">Berrabiatze leuna</string>
+ <string name="reboot_title">Berrabiarazi</string>
+ <string name="reboot_confirm" product="tablet">Tableta berrabiarazi egingo da.</string>
+ <string name="reboot_confirm" product="default">Telefonoa berrabiarazi egingo da.</string>
+ <string name="reboot_progress">Berrabiarazten\u2026</string>
+ <string name="app_killed_message">Aplikazioa eten da</string>
+ <string name="adb_net_active_notification_title">Sare gaineko ADB gaitua</string>
+ <string name="adb_both_active_notification_title">USB eta sare gaineko ADB gaitua</string>
+ <string name="adb_active_generic_notification_message">Sakatu arazketa ezgaitzeko.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB eta sarea</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Sarea</string>
+ <string name="permlab_interceptPackageLaunch">Eragotzi aplikazioak abiaraztea</string>
+ <string name="stylus_app_not_installed">%s ez dago instalatuta</string>
+ <string name="silent_mode_priority">Lehentasuna</string>
+ <string name="silent_mode_none">Bat ere ez</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi-Fi gunea desgaitu da SIM harpidetza aldatu delako</string>
+ <string name="notify_turn_wifi_off_title">Ezgaitu Wi-Fia</string>
+ <string name="permlab_changePrivacyGuardState">gaitu edo ezgaitu Privacy Guard</string>
+ <string name="permdesc_changePrivacyGuardState">Beste aplikazio bat Privacy Guard menpean dagoen aldatzea ahalbidetzen dio aplikazioari. Aplikazio bat Privacy Guard menpean dagoenean ezin izango du datu pertsonalik ikusi, ez kontakturik, ez dei erregistrorik, ezta mezurik ere.</string>
+ <string name="privacy_guard_notification">Privacy Guard aktibo</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> aplikazioak ezingo du datu pertsonalik irakurri</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> aplikazioak <xliff:g id="op">%2$s</xliff:g> ahal izatea nahi du.</string>
+ <string name="permission_remember_choice">Gogoratu nire aukera</string>
+ <string name="app_ops_access_camera">kamera atzitu</string>
+ <string name="app_ops_access_location">zure kokalekua atzitu</string>
+ <string name="app_ops_access_notifications">zure jakinarazpenak irakurri</string>
+ <string name="app_ops_activate_vpn">VPN bat aktibatu</string>
+ <string name="app_ops_auto_start">abioan exekutatu</string>
+ <string name="app_ops_delete_call_log">zure dei egunkaria ezabatu</string>
+ <string name="app_ops_delete_contacts">zure kontaktuak ezabatu</string>
+ <string name="app_ops_delete_mms">zure MMS mezuak ezabatu</string>
+ <string name="app_ops_delete_sms">zure SMS mezuak ezabatu</string>
+ <string name="app_ops_draw_on_top">leihoak besteen gainetik marraztu</string>
+ <string name="app_ops_get_usage_stats">aplikazioen erabilera estatistikak jaso</string>
+ <string name="app_ops_keep_device_awake">gailua esnatuta mantendu</string>
+ <string name="app_ops_make_phone_call">telefono dei bat egin</string>
+ <string name="app_ops_modify_calendar">egutegia eguneratu</string>
+ <string name="app_ops_modify_call_log">dei erregistroa eguneratu</string>
+ <string name="app_ops_modify_clipboard">arbela aldatu</string>
+ <string name="app_ops_modify_contacts">zure kontaktuak eguneratu</string>
+ <string name="app_ops_modify_settings">sistema ezarpenak aldatu</string>
+ <string name="app_ops_mute_unmute_microphone">mikrofonoa mututu/desmututu</string>
+ <string name="app_ops_play_audio">soinua erreproduzitu</string>
+ <string name="app_ops_post_notification">jakinarazpen bat argitaratu</string>
+ <string name="app_ops_project_media">multimedia proiektatu</string>
+ <string name="app_ops_read_calendar">zure egutegia irakurri</string>
+ <string name="app_ops_read_call_log">dei erregistroa irakurri</string>
+ <string name="app_ops_read_clipboard">arbela irakurri</string>
+ <string name="app_ops_read_contacts">zure kontaktuak irakurri</string>
+ <string name="app_ops_read_mms">zure MMS mezuak irakurri</string>
+ <string name="app_ops_read_sms">zure SMS mezuak irakurri</string>
+ <string name="app_ops_receive_sms">SMS mezu bat jaso</string>
+ <string name="app_ops_record_audio">soinua grabatu</string>
+ <string name="app_ops_send_mms">MMS mezu bat bidali</string>
+ <string name="app_ops_send_sms">SMS mezu bat bidali</string>
+ <string name="app_ops_start_at_bootup">exekutatu abioan</string>
+ <string name="app_ops_toast_window">laster-leihoa mezuak bistaratu</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth txandakatu</string>
+ <string name="app_ops_toggle_mobile_data">txandakatu datu mugikorrak</string>
+ <string name="app_ops_toggle_nfc">NFC txandakatu</string>
+ <string name="app_ops_toggle_wifi">Wi-Fia txandakatu</string>
+ <string name="app_ops_use_alarm_volume">alarmen bolumena kontrolatu</string>
+ <string name="app_ops_use_audio_focus">audio fokua kontrolatu</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetooth bolumena kontrolatu</string>
+ <string name="app_ops_use_master_volume">bolumen orokorra kontrolatu</string>
+ <string name="app_ops_use_media_buttons">multimedia botoiak erabili</string>
+ <string name="app_ops_use_media_volume">multimedia bolumena kontrolatu</string>
+ <string name="app_ops_use_notification_volume">jakinarazpen bolumena kontrolatu</string>
+ <string name="app_ops_use_ring_volume">dei doinuaren bolumena kontrolatu</string>
+ <string name="app_ops_use_vibrate">erantzun haptikoa erabili</string>
+ <string name="app_ops_use_voice_volume">ahots deiaren bolumena kontrolatu</string>
+ <string name="app_ops_write_mms">MMS mezu bat idatzi</string>
+ <string name="app_ops_write_sms">SMS mezu bat idatzi</string>
+ <string name="app_ops_use_fingerprint">hatz-marka erabili</string>
+ <string name="app_ops_add_voicemail">gehitu ahots postontzia</string>
+ <string name="app_ops_read_phone_state">telefonoaren egoera atzitu</string>
+ <string name="app_ops_scan_wifi">eskaneatu Wi-Fi sareak</string>
+ <string name="app_ops_change_wallpaper">aldatu horma-irudia</string>
+ <string name="app_ops_assist_structure">estruktura lagungarria erabili</string>
+ <string name="app_ops_assist_screenshot">egin pantaila-argazkia</string>
+ <string name="app_ops_use_body_sensors">erabili gorputz sentsoreak</string>
+ <string name="app_ops_read_cell_broadcasts">zelulen banaketa mezuak irakurri</string>
+ <string name="app_ops_mock_location">kokapena faltsutu</string>
+ <string name="app_ops_read_external_storage">kanpo biltegiratzea irakurri</string>
+ <string name="app_ops_write_external_storage">kanpo biltegiratzean idatzi</string>
+ <string name="app_ops_turn_on_screen">pantaila piztu</string>
+ <string name="app_ops_get_accounts">eskuratu gailuaren kontuak</string>
+ <string name="app_ops_wifi_change">Wi-Fiaren egoera aldatu</string>
+ <string name="app_ops_su">root sarbidea eskuratu</string>
+ <string name="lock_to_app_toast_no_navbar">Pantaila hau desiltzatzeko sakatu eta mantendu atzera botoia.</string>
+ <string name="live_display_auto">Automatikoa</string>
+ <string name="live_display_auto_summary">Doitu automatikoki pantailaren kolore tenperatura ilunabarra eta egunsentiaren ostean</string>
+ <string name="live_display_off">Ez</string>
+ <string name="live_display_off_summary">Ezgaitu doitze guztiak</string>
+ <string name="live_display_day">Eguna</string>
+ <string name="live_display_day_summary">Erabili egun ezarpenak besterik ez</string>
+ <string name="live_display_night">Gaua</string>
+ <string name="live_display_night_summary">Erabili gau ezarpenak besterik ez</string>
+ <string name="live_display_outdoor">Kalean (eguzkipean)</string>
+ <string name="live_display_outdoor_summary">Erabili kaleko ezarpenak besterik ez</string>
+ <string name="live_display_hint">LiveDisplayk begi nekea gutxitu eta gauez lo egiten lagundu dezake. Probatu ezazu!</string>
+ <string name="tethered_notification_no_device_message">Ez da gailurik konektatu</string>
+ <string name="tethered_notification_one_device_message">gailu <xliff:g id="count">%1$s</xliff:g> konektatuta</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> gailu konektatuta</string>
+ <string name="notify_package_component_protected_title">Aktibitatea abiatzea blokeatu da</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> abiatzeko babestuta dago. Sakatu nortasuna egiaztatzeko eta aplikazioa abiatzeko.</string>
+ <string name="notify_battery_fully_charged_title">Bateria erabat kargatuta</string>
+ <string name="notify_battery_fully_charged_text">Deskonektatu zure gailua kargagailutik bateriaren bizitza luzatzeko.</string>
+</resources>
diff --git a/core/res/res/values-fa/cm_strings.xml b/core/res/res/values-fa/cm_strings.xml
new file mode 100644
index 0000000..81d51c3
--- /dev/null
+++ b/core/res/res/values-fa/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">تصویر صفحه</string>
+ <string name="permlab_receiveProtectedSms">دریافت پیامک محفاظت شده</string>
+ <string name="permdesc_receiveProtectedSms">به برنامه اجازه می‌دهد پیام محافظت شده‌ای دریافت کند.</string>
+ <string name="permlab_modifyProtectedSmsList">ویرایش لیست پیامک محافظت شده</string>
+ <string name="permdesc_modifyProtectedSmsList">به برنامه اجازه می‌دهد لیست آدرس پیامک‌های محافظت شده را تغییردهد.</string>
+ <string name="permgrouplab_security">امنیت</string>
+ <string name="permgroupdesc_security">مجوزهای مربوط به اطلاعات امنیتی دستگاه.</string>
+ <string name="permlab_readPhoneBlacklist">مشاهده لیست سیاه گوشی</string>
+ <string name="permdesc_readPhoneBlacklist">به برنامه اجازه می‌دهد اطلاعات مربوط به شماره تلفن‌های مسدود را برای پیام‌ها یا تماس‌های ورودی بخواند.</string>
+ <string name="permlab_changePhoneBlacklist">تغییر لیست سیاه گوشی</string>
+ <string name="permdesc_changePhoneBlacklist">به برنامه اجازه می‌دهد شماره تلفن‌های مسدود را برای پیام‌ها یا تماس‌های ورودی تغییر دهد.</string>
+ <string name="permlab_setKeyguardWallpaper">تنظیم کاغذدیواری قفل صفحه</string>
+ <string name="permdesc_setKeyguardWallpaper">به برنامه اجازه می‌دهد کاغذدیواری قفل صفحه را تغییر دهد.</string>
+ <string name="global_action_reboot">راه‌اندازی مجدد</string>
+ <string name="global_action_current_user">فعلی</string>
+ <string name="reboot_reboot">معمولی</string>
+ <string name="reboot_recovery">ریکاوری</string>
+ <string name="reboot_bootloader">بوت لودر</string>
+ <string name="reboot_download">دانلود</string>
+ <string name="reboot_soft">سافت</string>
+ <string name="reboot_title">راه‌اندازی مجدد</string>
+ <string name="reboot_confirm" product="tablet">تبلت شما مجددا راه‌اندازی خواهد شد.</string>
+ <string name="reboot_confirm" product="default">گوشی شما مجددا راه‌اندازی خواهد شد.</string>
+ <string name="reboot_progress">راه‌اندازی مجدد\u2026</string>
+ <string name="app_killed_message">برنامه بسته شد</string>
+ <string name="adb_net_active_notification_title">ای‌دی‌بی از طریق شبکه فعال شد</string>
+ <string name="adb_both_active_notification_title">ای‌دی‌بی از طریق شبکه و یواس‌بی فعال شد</string>
+ <string name="adb_active_generic_notification_message">برای غیرفعال کردن اشکال‌زدایی لمس کنید.</string>
+ <string name="adb_active_custom_tile">ای‌دی‌بی - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">شبکه و یواس‌بی</string>
+ <string name="adb_active_custom_tile_usb">یواس‌بی</string>
+ <string name="adb_active_custom_tile_net">شبکه</string>
+ <string name="permlab_interceptPackageLaunch">جلوگیری از اجرا شدن برنامه</string>
+ <string name="stylus_app_not_installed">%s نصب نیست</string>
+ <string name="silent_mode_priority">اولویت‌دار</string>
+ <string name="silent_mode_none">هیچ‌کدام</string>
+ <string name="subscription_change_disabled_wifi_ap">نقطه اتصال قابل حمل وای‌فای به دلیل تغییر تعرفه سیم کارت، غیرفعال شد</string>
+ <string name="notify_turn_wifi_off_title">خاموش کردن وای‌فای</string>
+ <string name="permlab_changePrivacyGuardState">فعال یا غیرفعال کردن محافظ حریم خصوصی</string>
+ <string name="permdesc_changePrivacyGuardState">به برنامه اجازه می‌دهد اجرا شدن برنامه‌های دیگر با محافظ حریم خصوصی را تغییر دهد. هنگامی که یک برنامه با محافظ حریم خصوصی اجرا می‌شود، به اطلاعات شخصی مانند مخاطبین، گزارش‌های تماس یا پیام‌ها دسترسی نخواهد داشت.</string>
+ <string name="privacy_guard_notification">محافظ حریم خصوصی فعال است</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> به اصلاعات شخصی دسترسی نخواهد داشت</string>
+ <string name="privacy_guard_dialog_title">محافظ حریم خصوصی</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> می‌خواهد <xliff:g id="op">%2$s</xliff:g> انجام دهد.</string>
+ <string name="permission_remember_choice">انتخابم را به یاد داشته باش</string>
+ <string name="app_ops_access_camera">دسترسی به دوربین</string>
+ <string name="app_ops_access_location">دسترسی به مکان شما</string>
+ <string name="app_ops_access_notifications">مشاهده اعلان‌های شما</string>
+ <string name="app_ops_activate_vpn">فعال کردن وی‌پی‌ان</string>
+ <string name="app_ops_auto_start">اجرا هنگام روشن شدن</string>
+ <string name="app_ops_delete_call_log">حذف گزارش تماس شما</string>
+ <string name="app_ops_delete_contacts">حذف مخاطبین شما</string>
+ <string name="app_ops_delete_mms">حذف پیام‌های ام‌ام‌اس شما</string>
+ <string name="app_ops_delete_sms">حذف پیامک‌های شما</string>
+ <string name="app_ops_draw_on_top">نمایش در بالای پنجره‌های دیگر</string>
+ <string name="app_ops_get_usage_stats">دریافت وضعیت استفاده از برنامه‌ها</string>
+ <string name="app_ops_keep_device_awake">بیدار نگه داشتن دستگاه</string>
+ <string name="app_ops_make_phone_call">برقراری تماس</string>
+ <string name="app_ops_modify_calendar">بروز کردن تقویم شما</string>
+ <string name="app_ops_modify_call_log">بروز کردن گزارش تماس</string>
+ <string name="app_ops_modify_clipboard">ویرایش کلیپ برد</string>
+ <string name="app_ops_modify_contacts">بروز کردن مخاطبین</string>
+ <string name="app_ops_modify_settings">بروز کردن تنظیمات سیستمی</string>
+ <string name="app_ops_mute_unmute_microphone">قطع/وصل کردن میکروفون</string>
+ <string name="app_ops_play_audio">پخش صدا</string>
+ <string name="app_ops_post_notification">ارسال اعلان</string>
+ <string name="app_ops_project_media">پخش رسانه</string>
+ <string name="app_ops_read_calendar">مشاهده تقویم شما</string>
+ <string name="app_ops_read_call_log">مشاهده گزارش تماس</string>
+ <string name="app_ops_read_clipboard">مشاهده کلیپ برد</string>
+ <string name="app_ops_read_contacts">مشاهده مخاطبین شما</string>
+ <string name="app_ops_read_mms">مشاهده پیام‌های ام‌ام‌اس شما</string>
+ <string name="app_ops_read_sms">مشاهده پیامک‌های شما</string>
+ <string name="app_ops_receive_sms">دریافت پیامک</string>
+ <string name="app_ops_record_audio">ضبط صدا</string>
+ <string name="app_ops_send_mms">ارسال پیام ام‌ام‌اس</string>
+ <string name="app_ops_send_sms">ارسال پیامک</string>
+ <string name="app_ops_start_at_bootup">اجرا هنگام روشن شدن</string>
+ <string name="app_ops_toast_window">نمایش متن‌های کوچک</string>
+ <string name="app_ops_toggle_bluetooth">روشن و خاموش کردن بلوتوث</string>
+ <string name="app_ops_toggle_nfc">روشن و خاموش کردن ان‌اف‌سی</string>
+ <string name="app_ops_use_alarm_volume">کنترل صدای هشدار</string>
+ <string name="app_ops_use_audio_focus">کنترل کانون صدا</string>
+ <string name="app_ops_use_bluetooth_volume">کنترل صدای بلوتوث</string>
+ <string name="app_ops_use_master_volume">کنترل صدای اصلی</string>
+ <string name="app_ops_use_media_buttons">استفاده از کلیدهای رسانه</string>
+ <string name="app_ops_use_media_volume">کنترل صدای رسانه</string>
+ <string name="app_ops_use_notification_volume">کنترل صدای اعلان</string>
+ <string name="app_ops_use_ring_volume">کنترل صدای زنگ</string>
+ <string name="app_ops_use_vibrate">استفاده از بازخورد لمسی</string>
+ <string name="app_ops_use_voice_volume">کنترل صدای تماس صوتی</string>
+ <string name="app_ops_write_mms">نوشتن پیام ام‌ام‌اس</string>
+ <string name="app_ops_write_sms">نوشتن پیامک</string>
+ <string name="app_ops_su">دریافت دسترسی روت</string>
+ <string name="lock_to_app_toast_no_navbar">برای از سنجاق درآوردن این صفحه، دکمه بازگشت را زده و نگه دارید.</string>
+ <string name="live_display_auto">خودکار</string>
+ <string name="live_display_auto_summary">تنظیم خودکار دمای رنگ صفحه بعد از طلوع و غروب خورشید</string>
+ <string name="live_display_off">خاموش</string>
+ <string name="live_display_off_summary">غیرفعال کردن همه تنظیمات</string>
+ <string name="live_display_day">روز</string>
+ <string name="live_display_day_summary">فقط استفاده از تنظیمات روز</string>
+ <string name="live_display_night">شب</string>
+ <string name="live_display_night_summary">فقط استفاده از تنظیمات شب</string>
+ <string name="live_display_outdoor">فضای باز (نور خورشید)</string>
+ <string name="live_display_outdoor_summary">فقط استفاده از تنظیمات فضای باز</string>
+ <string name="live_display_hint">نمایش پویا کمک می‌کند چشم‌هایتان کم‌تر خسته شده و شب راحت‌تر به خواب بروید. برای امتحان آن اینجا کلیک کنید!</string>
+ <string name="tethered_notification_no_device_message">هیچ دستگاه متصلی وجود ندارد</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> دستگاه متصل</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> دستگاه متصل</string>
+</resources>
diff --git a/core/res/res/values-fi/cm_strings.xml b/core/res/res/values-fi/cm_strings.xml
new file mode 100644
index 0000000..1df6487
--- /dev/null
+++ b/core/res/res/values-fi/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Kuvakaappaus</string>
+ <string name="permlab_receiveProtectedSms">vastaanota suojattuja tekstiviestejä</string>
+ <string name="permdesc_receiveProtectedSms">Sallii sovelluksen vastaanottaa suojattuja tekstiviestejä.</string>
+ <string name="permlab_modifyProtectedSmsList">muokkaa suojattujen tekstiviestien listaa</string>
+ <string name="permdesc_modifyProtectedSmsList">Sallii sovelluksen muokata suojattujen tekstiviestien osoiteluetteloa.</string>
+ <string name="permgrouplab_security">Turvallisuus</string>
+ <string name="permgroupdesc_security">Laitteen turvallisuuteen liittyvät oikeudet.</string>
+ <string name="permlab_readPhoneBlacklist">lue puhelimen mustaa listaa</string>
+ <string name="permdesc_readPhoneBlacklist">Sallii sovelluksen lukea tietoja numeroista, joista saapuvat puhelut ja viestit on estetty.</string>
+ <string name="permlab_changePhoneBlacklist">muokkaa puhelimen mustaa listaa</string>
+ <string name="permdesc_changePhoneBlacklist">Sallii sovelluksen muokata puhelinnumeroita, joista saapuvat puhelut ja viestit on estetty.</string>
+ <string name="permlab_setKeyguardWallpaper">aseta näppäinlukon taustakuva</string>
+ <string name="permdesc_setKeyguardWallpaper">Sallii sovelluksen vaihtaa lukitusnäytön taustakuva.</string>
+ <string name="global_action_reboot">Käynnistä uudelleen</string>
+ <string name="global_action_current_user">Nykyinen</string>
+ <string name="reboot_reboot">Käynnistä uudelleen</string>
+ <string name="reboot_recovery">Recovery-tila</string>
+ <string name="reboot_bootloader">Bootloader-tila</string>
+ <string name="reboot_download">Download-tila</string>
+ <string name="reboot_soft">Käynnistä uudelleen (soft)</string>
+ <string name="reboot_title">Käynnistä uudelleen</string>
+ <string name="reboot_confirm" product="tablet">Tabletti käynnistyy uudelleen.</string>
+ <string name="reboot_confirm" product="default">Puhelin käynnistyy uudelleen.</string>
+ <string name="reboot_progress">Käynnistetään uudelleen\u2026</string>
+ <string name="app_killed_message">Sovellus tapettu</string>
+ <string name="adb_net_active_notification_title">ADB verkon yli käytössä</string>
+ <string name="adb_both_active_notification_title">ADB verkon &amp; USB:n kautta käytössä</string>
+ <string name="adb_active_generic_notification_message">Paina poistaaksesi vianetsinnän käytöstä.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; verkko</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Verkko</string>
+ <string name="permlab_interceptPackageLaunch">keskeytä sovelluksen käynnistys</string>
+ <string name="stylus_app_not_installed">%s ei ole asennettu</string>
+ <string name="silent_mode_priority">Prioriteetti</string>
+ <string name="silent_mode_none">Ei mitään</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi-Fi-tukiasema poistettiin käytöstä SIMin vaihdon vuoksi</string>
+ <string name="notify_turn_wifi_off_title">Poista Wi-Fi käytöstä</string>
+ <string name="permlab_changePrivacyGuardState">ota yksityisyyden suojaus käyttöön tai poista se käytöstä</string>
+ <string name="permdesc_changePrivacyGuardState">Sallii sovelluksen valita, milloin muut sovellukset käyttävät yksityisyyden suojausta. Kun sovellus käyttää yksityisyyden suojausta, sillä ei ole pääsyä henkilökohtaisiin tietoihin kuten yhteystietoihin, puhelulokeihin tai viesteihin.</string>
+ <string name="privacy_guard_notification">Yksityisyyden suojaus käytössä</string>
+ <string name="privacy_guard_notification_detail">Sovelluksella <xliff:g id="app">%1$s</xliff:g> ei ole pääsyä henkilökohtaisiin tietoihin</string>
+ <string name="privacy_guard_dialog_title">Yksityisyyden suojaus</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> haluaa <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Muista valinta</string>
+ <string name="app_ops_access_camera">käyttää kameraa</string>
+ <string name="app_ops_access_location">käyttää sijaintia</string>
+ <string name="app_ops_access_notifications">lukea ilmoituksiasi</string>
+ <string name="app_ops_activate_vpn">aktivoida VPN-yhteyden</string>
+ <string name="app_ops_auto_start">käynnistyä laitetta käynnistettäessä</string>
+ <string name="app_ops_delete_call_log">poistaa puhelulokin</string>
+ <string name="app_ops_delete_contacts">poistaa yhteystietojasi</string>
+ <string name="app_ops_delete_mms">poistaa multimediaviestejäsi</string>
+ <string name="app_ops_delete_sms">poistaa tekstiviestejäsi</string>
+ <string name="app_ops_draw_on_top">piirtää ikkunan päälle</string>
+ <string name="app_ops_get_usage_stats">käyttää sovelluksen käyttötilastoja</string>
+ <string name="app_ops_keep_device_awake">pitää laitteen hereillä</string>
+ <string name="app_ops_make_phone_call">soittaa puhelun</string>
+ <string name="app_ops_modify_calendar">päivittää kalenteria</string>
+ <string name="app_ops_modify_call_log">päivittää puhelulokia</string>
+ <string name="app_ops_modify_clipboard">muokata leikepöytää</string>
+ <string name="app_ops_modify_contacts">päivittää yhteystietoja</string>
+ <string name="app_ops_modify_settings">päivittää järjestelmän asetuksia</string>
+ <string name="app_ops_mute_unmute_microphone">mykistä/poista mykistys mikrofonista</string>
+ <string name="app_ops_play_audio">toistaa ääntä</string>
+ <string name="app_ops_post_notification">lähettää ilmoituksen</string>
+ <string name="app_ops_project_media">heijastaa mediaa</string>
+ <string name="app_ops_read_calendar">lukea kalenteria</string>
+ <string name="app_ops_read_call_log">lukea puhelulokia</string>
+ <string name="app_ops_read_clipboard">lukea leikepöytää</string>
+ <string name="app_ops_read_contacts">lukea yhteystietoja</string>
+ <string name="app_ops_read_mms">luekea multimediaviestejä</string>
+ <string name="app_ops_read_sms">lukea tekstiviestejä</string>
+ <string name="app_ops_receive_sms">vastaanottaa tekstiviestejä</string>
+ <string name="app_ops_record_audio">tallentaa ääntä</string>
+ <string name="app_ops_send_mms">lähettää multimediaviestin</string>
+ <string name="app_ops_send_sms">lähettää tekstiviestin</string>
+ <string name="app_ops_start_at_bootup">käynnistyä laitetta käynnistettäessä</string>
+ <string name="app_ops_toast_window">Näytä toast-ilmoitukset</string>
+ <string name="app_ops_toggle_bluetooth">ottaa Bluetoothin käyttöön</string>
+ <string name="app_ops_toggle_mobile_data">ota mobiilidata käyttöön</string>
+ <string name="app_ops_toggle_nfc">ota NFC käyttöön</string>
+ <string name="app_ops_toggle_wifi">vaihtaa Wi-Fi-verkkoja</string>
+ <string name="app_ops_use_alarm_volume">säätää hälytyksen äänenvoimakkuutta</string>
+ <string name="app_ops_use_audio_focus">säätää äänen kohdistusta</string>
+ <string name="app_ops_use_bluetooth_volume">säätää Bluetoothin äänenvoimakkuutta</string>
+ <string name="app_ops_use_master_volume">säätää pää-äänenvoimakkuutta</string>
+ <string name="app_ops_use_media_buttons">käyttää mediapainikkeita</string>
+ <string name="app_ops_use_media_volume">säätää median äänenvoimakkuutta</string>
+ <string name="app_ops_use_notification_volume">säätää ilmoitusten äänenvoimakkuutta</string>
+ <string name="app_ops_use_ring_volume">säätää soittoäänen voimakkuutta</string>
+ <string name="app_ops_use_vibrate">käyttää haptista palautetta</string>
+ <string name="app_ops_use_voice_volume">säätää puhelun äänenvoimakkuutta</string>
+ <string name="app_ops_write_mms">kirjoittaa multimediaviestin</string>
+ <string name="app_ops_write_sms">kirjoittaa tekstiviestin</string>
+ <string name="app_ops_use_fingerprint">käyttää sormenjälkeä</string>
+ <string name="app_ops_add_voicemail">lisätä vastaajaviestin</string>
+ <string name="app_ops_read_phone_state">lukea puhelimen tilan</string>
+ <string name="app_ops_scan_wifi">hakea Wi-Fi-verkkoja</string>
+ <string name="app_ops_change_wallpaper">vaihtaa taustakuvan</string>
+ <string name="app_ops_assist_structure">käyttää apurakennetta</string>
+ <string name="app_ops_assist_screenshot">ottaa kuvankaappauksen</string>
+ <string name="app_ops_use_body_sensors">käyttää kehon antureita</string>
+ <string name="app_ops_read_cell_broadcasts">lukea hätätilalähetyksiä</string>
+ <string name="app_ops_mock_location">väärentää sijaintisi</string>
+ <string name="app_ops_read_external_storage">lukea ulkoista tallennustilaa</string>
+ <string name="app_ops_write_external_storage">kirjoittaa ulkoiseen tallennustilaan</string>
+ <string name="app_ops_turn_on_screen">kytkeä näytön päälle</string>
+ <string name="app_ops_get_accounts">lukea laitteen tilejä</string>
+ <string name="app_ops_wifi_change">vaihtaa Wi-Fi:n tilaa</string>
+ <string name="app_ops_su">pääkäyttäjän oikeudet</string>
+ <string name="lock_to_app_toast_no_navbar">Irrottaaksesi tämän näytön, paina ja pidä Takasin-näppäintä pohjassa.</string>
+ <string name="live_display_auto">Automaattinen</string>
+ <string name="live_display_auto_summary">Säädä näytön värilämpötilaa automaattisesti auringonlaskun ja -nousun jälkeen</string>
+ <string name="live_display_off">Pois käytöstä</string>
+ <string name="live_display_off_summary">Poista kaikki mukautukset</string>
+ <string name="live_display_day">Päivä</string>
+ <string name="live_display_day_summary">Käytä vain päiväasetusta</string>
+ <string name="live_display_night">Yö</string>
+ <string name="live_display_night_summary">Käytä vain yöasetusta</string>
+ <string name="live_display_outdoor">Ulkoilma (kirkas aurinko)</string>
+ <string name="live_display_outdoor_summary">Käytä vain ulkoilma-asetusta</string>
+ <string name="live_display_hint">LiveDisplay voi vähentää silmien rasitusta ja auttaa nukkumaan öisin. Kokeile sitä painamalla tästä!</string>
+ <string name="tethered_notification_no_device_message">Ei kytkettyä laitetta</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> yhdistetty laite</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> yhdistettyä laitetta</string>
+ <string name="notify_package_component_protected_title">Toiminnan käynnistäminen estetty</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> on suojattu sovellus. Napauta todentaaksesi ja käynnistääksesi sovelluksen.</string>
+ <string name="notify_battery_fully_charged_title">Akku täynnä</string>
+ <string name="notify_battery_fully_charged_text">Irrota laite laturista pidentääksesi akun käyttöikää.</string>
+</resources>
diff --git a/core/res/res/values-fr/cm_strings.xml b/core/res/res/values-fr/cm_strings.xml
new file mode 100644
index 0000000..c8af1ac
--- /dev/null
+++ b/core/res/res/values-fr/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Capture d\'écran</string>
+ <string name="permlab_receiveProtectedSms">recevoir des SMS protégés</string>
+ <string name="permdesc_receiveProtectedSms">Permet à l\'application de recevoir un SMS protégé.</string>
+ <string name="permlab_modifyProtectedSmsList">modifier la liste des SMS protégés</string>
+ <string name="permdesc_modifyProtectedSmsList">Permet à l\'application de modifier la liste des adresses des SMS protégés.</string>
+ <string name="permgrouplab_security">Sécurité</string>
+ <string name="permgroupdesc_security">Autorisations relatives aux informations de sécurité de l\'appareil.</string>
+ <string name="permlab_readPhoneBlacklist">lire la liste noire du téléphone</string>
+ <string name="permdesc_readPhoneBlacklist">Permet à l\'application de lire les informations sur les numéros de téléphone qui sont bloqués pour les appels ou les messages entrants.</string>
+ <string name="permlab_changePhoneBlacklist">modifier la liste noire du téléphone</string>
+ <string name="permdesc_changePhoneBlacklist">Permet à l\'application de modifier les numéros de téléphone qui sont bloqués pour les appels ou les messages entrants.</string>
+ <string name="permlab_setKeyguardWallpaper">Définir le fond d\'écran de verrouillage</string>
+ <string name="permdesc_setKeyguardWallpaper">Permet à l\'application de changer le fond de l\'écran de verrouillage.</string>
+ <string name="global_action_reboot">Redémarrer</string>
+ <string name="global_action_current_user">Actuel</string>
+ <string name="reboot_reboot">Redémarrer</string>
+ <string name="reboot_recovery">Récupération</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Redémarrage logiciel</string>
+ <string name="reboot_title">Redémarrer</string>
+ <string name="reboot_confirm" product="tablet">Votre tablette va redémarrer</string>
+ <string name="reboot_confirm" product="default">Votre téléphone va redémarrer</string>
+ <string name="reboot_progress">Redémarrage en cours\u2026</string>
+ <string name="app_killed_message">Application arrêtée</string>
+ <string name="adb_net_active_notification_title">ADB sur réseau activé</string>
+ <string name="adb_both_active_notification_title">ADB sur USB et réseau activé</string>
+ <string name="adb_active_generic_notification_message">Appuyez pour désactiver le débogage.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB et réseau</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Réseau</string>
+ <string name="permlab_interceptPackageLaunch">intercepter le lancement d\'application</string>
+ <string name="stylus_app_not_installed">%s n\'est pas installé</string>
+ <string name="silent_mode_priority">Priorité</string>
+ <string name="silent_mode_none">Aucun</string>
+ <string name="subscription_change_disabled_wifi_ap">Point d\'accès Wi-Fi désactivé en raison d\'un changement d\'abonnement SIM</string>
+ <string name="notify_turn_wifi_off_title">Désactiver le Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">activer ou désactiver la protection des données</string>
+ <string name="permdesc_changePrivacyGuardState">Permet à l\'application d\'en exécuter une autre avec la protection des données. Lorsqu\'une application est exécutée avec la protection des données, elle n\'aura pas accès aux données personnelles telles que les contacts, les journaux d\'appels ou les messages.</string>
+ <string name="privacy_guard_notification">Protection des données activée</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> ne sera pas en mesure d\'accéder aux données personnelles</string>
+ <string name="privacy_guard_dialog_title">Protection des données</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> voudrait <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Se souvenir de mon choix</string>
+ <string name="app_ops_access_camera">accéder à l\'appareil photo</string>
+ <string name="app_ops_access_location">accéder à votre position</string>
+ <string name="app_ops_access_notifications">lire vos notifications</string>
+ <string name="app_ops_activate_vpn">activer un VPN</string>
+ <string name="app_ops_auto_start">démarrer avec le système</string>
+ <string name="app_ops_delete_call_log">supprimer votre journal d\'appels</string>
+ <string name="app_ops_delete_contacts">supprimer vos contacts</string>
+ <string name="app_ops_delete_mms">supprimer vos messages MMS</string>
+ <string name="app_ops_delete_sms">supprimer vos messages SMS</string>
+ <string name="app_ops_draw_on_top">déplacer au dessus</string>
+ <string name="app_ops_get_usage_stats">obtenir les statistiques d\'utilisation de l\'application</string>
+ <string name="app_ops_keep_device_awake">garder votre appareil allumé</string>
+ <string name="app_ops_make_phone_call">passer un appel téléphonique</string>
+ <string name="app_ops_modify_calendar">mettre à jour votre agenda</string>
+ <string name="app_ops_modify_call_log">mettre à jour le journal d\'appels</string>
+ <string name="app_ops_modify_clipboard">modifier le presse-papiers</string>
+ <string name="app_ops_modify_contacts">mettre à jour vos contacts</string>
+ <string name="app_ops_modify_settings">mettre à jour les paramètres du système</string>
+ <string name="app_ops_mute_unmute_microphone">activer/désactiver le microphone</string>
+ <string name="app_ops_play_audio">lecture audio</string>
+ <string name="app_ops_post_notification">afficher une notification</string>
+ <string name="app_ops_project_media">projet média</string>
+ <string name="app_ops_read_calendar">lire votre agenda</string>
+ <string name="app_ops_read_call_log">lire le journal d\'appels</string>
+ <string name="app_ops_read_clipboard">lire le presse-papiers</string>
+ <string name="app_ops_read_contacts">lire vos contacts</string>
+ <string name="app_ops_read_mms">lire vos messages MMS</string>
+ <string name="app_ops_read_sms">lire vos messages SMS</string>
+ <string name="app_ops_receive_sms">recevoir un SMS</string>
+ <string name="app_ops_record_audio">enregistrer un son</string>
+ <string name="app_ops_send_mms">envoyer un MMS</string>
+ <string name="app_ops_send_sms">envoyer un SMS</string>
+ <string name="app_ops_start_at_bootup">démarrer à la mise sous tension</string>
+ <string name="app_ops_toast_window">afficher les messages toast</string>
+ <string name="app_ops_toggle_bluetooth">activer/désactiver le Bluetooth</string>
+ <string name="app_ops_toggle_nfc">activer/désactiver le NFC</string>
+ <string name="app_ops_toggle_wifi">activer le Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">contrôler le volume des alarmes</string>
+ <string name="app_ops_use_audio_focus">contrôler le focus audio</string>
+ <string name="app_ops_use_bluetooth_volume">contrôler le volume du Bluetooth</string>
+ <string name="app_ops_use_master_volume">contrôler le volume principal</string>
+ <string name="app_ops_use_media_buttons">utiliser les boutons de médias</string>
+ <string name="app_ops_use_media_volume">contrôler le volume des médias</string>
+ <string name="app_ops_use_notification_volume">contrôler le volume des notifications</string>
+ <string name="app_ops_use_ring_volume">contrôler le volume de la sonnerie</string>
+ <string name="app_ops_use_vibrate">utiliser le retour haptique</string>
+ <string name="app_ops_use_voice_volume">contrôler le volume d\'appels</string>
+ <string name="app_ops_write_mms">écrire un MMS</string>
+ <string name="app_ops_write_sms">écrire un SMS</string>
+ <string name="app_ops_use_fingerprint">utiliser les empreintes digitales</string>
+ <string name="app_ops_add_voicemail">ajouter un message vocal</string>
+ <string name="app_ops_read_phone_state">accéder à l\'état du téléphone</string>
+ <string name="app_ops_scan_wifi">scanner les réseaux Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">changer le fond d\'écran</string>
+ <string name="app_ops_assist_structure">utiliser l\'aide à la structure</string>
+ <string name="app_ops_assist_screenshot">prendre une capture d\'écran</string>
+ <string name="app_ops_use_body_sensors">utiliser les capteurs corporels</string>
+ <string name="app_ops_read_cell_broadcasts">lire les diffusions cellulaires</string>
+ <string name="app_ops_mock_location">simuler votre localisation</string>
+ <string name="app_ops_read_external_storage">lire le stockage externe</string>
+ <string name="app_ops_write_external_storage">écrire sur le stockage externe</string>
+ <string name="app_ops_turn_on_screen">allumer l\'écran</string>
+ <string name="app_ops_get_accounts">obtenir les comptes de l\'appareil</string>
+ <string name="app_ops_wifi_change">changer l\'état du Wi-Fi</string>
+ <string name="app_ops_su">obtenir l\'accès root</string>
+ <string name="lock_to_app_toast_no_navbar">Pour déverrouiller l\'écran, appuyez et maintenez le bouton Retour.</string>
+ <string name="live_display_auto">Automatique</string>
+ <string name="live_display_auto_summary">Ajuster automatiquement la température des couleurs de l\'écran après le coucher et le lever du soleil</string>
+ <string name="live_display_off">Désactivé</string>
+ <string name="live_display_off_summary">Désactiver tous les réglages</string>
+ <string name="live_display_day">Jour</string>
+ <string name="live_display_day_summary">Utiliser uniquement les paramètres de jour</string>
+ <string name="live_display_night">Nuit</string>
+ <string name="live_display_night_summary">Utiliser uniquement les paramètres de nuit</string>
+ <string name="live_display_outdoor">Extérieur (plein soleil)</string>
+ <string name="live_display_outdoor_summary">Utiliser uniquement les paramètres extérieurs</string>
+ <string name="live_display_hint">LiveDisplay peut aider à réduire la fatigue oculaire et vous aider à dormir la nuit. Appuyez ici pour l\'essayer !</string>
+ <string name="tethered_notification_no_device_message">Aucun appareil connecté</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> appareil connecté</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> appareils connectés</string>
+ <string name="notify_package_component_protected_title">Lancement d\'activité bloqué</string>
+</resources>
diff --git a/core/res/res/values-gl-rES/cm_strings.xml b/core/res/res/values-gl-rES/cm_strings.xml
new file mode 100644
index 0000000..13986eb
--- /dev/null
+++ b/core/res/res/values-gl-rES/cm_strings.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Captura de pantalla</string>
+ <string name="permlab_receiveProtectedSms">recibir SMS protexidas</string>
+ <string name="permdesc_receiveProtectedSms">Permitir que a aplicación reciba unha SMS protexida.</string>
+ <string name="permlab_modifyProtectedSmsList">modificar a lista de SMS protexidas</string>
+ <string name="permdesc_modifyProtectedSmsList">Permitir que a aplicación modifique a lista de enderezos de SMS protexidas.</string>
+ <string name="permgrouplab_security">Seguridade</string>
+ <string name="permgroupdesc_security">Permisos relacionados coa información de seguridade do dispositivo.</string>
+ <string name="permlab_readPhoneBlacklist">ler a lista de bloqueo do teléfono</string>
+ <string name="permdesc_readPhoneBlacklist">Permítelle a unha aplicación ler a información sobre os números de teléfono que están bloqueados, dos que non se recibirán nin chamadas nin mensaxes.</string>
+ <string name="permlab_changePhoneBlacklist">cambiar a lista de bloqueo do teléfono</string>
+ <string name="permdesc_changePhoneBlacklist">Permítelle a unha aplicación cambiar os números de teléfono que están bloqueados, dos que nin se recibirán chamadas nin mensaxes.</string>
+ <string name="permlab_setKeyguardWallpaper">estabelecer fondo de pantalla de bloqueo</string>
+ <string name="permdesc_setKeyguardWallpaper">Permitir que unha aplicación cambie o fondo da pantalla de bloqueo.</string>
+ <string name="global_action_reboot">Reiniciar</string>
+ <string name="global_action_current_user">Actual</string>
+ <string name="reboot_reboot">Reiniciar</string>
+ <string name="reboot_recovery">Recuperar</string>
+ <string name="reboot_bootloader">Xestor de arranque</string>
+ <string name="reboot_download">Descargar</string>
+ <string name="reboot_soft">Reinicio do sistema</string>
+ <string name="reboot_title">Reiniciar</string>
+ <string name="reboot_confirm" product="tablet">Vaise reiniciar a súa tableta.</string>
+ <string name="reboot_confirm" product="default">Vaise reiniciar o seu teléfono.</string>
+ <string name="reboot_progress">Reiniciando\u2026</string>
+ <string name="app_killed_message">Aplicación terminada</string>
+ <string name="adb_net_active_notification_title">Activouse a rede en ADB</string>
+ <string name="adb_both_active_notification_title">Activada a ADB en USB e rede</string>
+ <string name="adb_active_generic_notification_message">Toque para desactivar a depuración.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB e rede</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Rede</string>
+ <string name="permlab_interceptPackageLaunch">Interromper o inicio de aplicacións</string>
+ <string name="stylus_app_not_installed">%s non está instalada</string>
+ <string name="silent_mode_priority">Prioridade</string>
+ <string name="silent_mode_none">Ningún</string>
+ <string name="subscription_change_disabled_wifi_ap">Hotspot Wi-Fi desactivado debido ao cambio da subscrición da SIM</string>
+ <string name="notify_turn_wifi_off_title">Apagar o Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">activar ou desactivar a Protección da privacidade</string>
+ <string name="permdesc_changePrivacyGuardState">Permítelle á aplicación decidir sobre se outra aplicación debe executarse ou non con Protección da privacidade. De unha aplicación estarse a executar con Protección da privacidade, non poderá acceder a contactos, rexistros de chamadas nin mensaxes.</string>
+ <string name="privacy_guard_notification">Protección da privacidade activada</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> non poderá acceder aos datos persoais</string>
+ <string name="privacy_guard_dialog_title">Protección da privacidade</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> quere <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Lembrar a miña escolla</string>
+ <string name="app_ops_access_camera">Acceder á cámara</string>
+ <string name="app_ops_access_location">Acceder á súa localización</string>
+ <string name="app_ops_access_notifications">Ler as súas notificacións</string>
+ <string name="app_ops_activate_vpn">Activar unha VPN</string>
+ <string name="app_ops_auto_start">Iniciar ao arrancar</string>
+ <string name="app_ops_delete_call_log">Borrar o seu rexistro de chamadas</string>
+ <string name="app_ops_delete_contacts">Borrar os seus contactos</string>
+ <string name="app_ops_delete_mms">Borrar as súas mensaxes MMS</string>
+ <string name="app_ops_delete_sms">Borrar as súas mensaxes SMS</string>
+ <string name="app_ops_draw_on_top">amosar enriba</string>
+ <string name="app_ops_get_usage_stats">obter estatísticas sobre o uso da aplicación</string>
+ <string name="app_ops_keep_device_awake">manter o seu dispositivo esperto</string>
+ <string name="app_ops_make_phone_call">realizar unha chamada de teléfono</string>
+ <string name="app_ops_modify_calendar">actualizar o seu calendario</string>
+ <string name="app_ops_modify_call_log">actualizar o rexistro de chamadas</string>
+ <string name="app_ops_modify_clipboard">modificar o seu portapapeis</string>
+ <string name="app_ops_modify_contacts">actualizar os seus contactos</string>
+ <string name="app_ops_modify_settings">actualizar a configuración do sistema</string>
+ <string name="app_ops_mute_unmute_microphone">activar/desactivar o micrófono</string>
+ <string name="app_ops_play_audio">reproducir son</string>
+ <string name="app_ops_post_notification">enviar unha notificación</string>
+ <string name="app_ops_project_media">visualizar recursos multimedia</string>
+ <string name="app_ops_read_calendar">ler o seu calendario</string>
+ <string name="app_ops_read_call_log">ler o rexistro de chamadas</string>
+ <string name="app_ops_read_clipboard">ler o portapapeis</string>
+ <string name="app_ops_read_contacts">ler os seus contactos</string>
+ <string name="app_ops_read_mms">ler as súas mensaxes MMS</string>
+ <string name="app_ops_read_sms">ler as súas mensaxes SMS</string>
+ <string name="app_ops_receive_sms">recibir unha mensaxe SMS</string>
+ <string name="app_ops_record_audio">gravar son</string>
+ <string name="app_ops_send_mms">enviar unha mensaxe MMS</string>
+ <string name="app_ops_send_sms">enviar unha mensaxe SMS</string>
+ <string name="app_ops_start_at_bootup">iniciar ao arrancar</string>
+ <string name="app_ops_toast_window">amosar notificacións emerxentes</string>
+ <string name="app_ops_toggle_bluetooth">trocar o Bluetooth</string>
+ <string name="app_ops_toggle_nfc">trocar o NFC</string>
+ <string name="app_ops_use_alarm_volume">controlar o volume da alarma</string>
+ <string name="app_ops_use_audio_focus">controlar o foco de son</string>
+ <string name="app_ops_use_bluetooth_volume">controlar o volume do Bluetooth</string>
+ <string name="app_ops_use_master_volume">controlar o volume global</string>
+ <string name="app_ops_use_media_buttons">empregar os botóns de multimedia</string>
+ <string name="app_ops_use_media_volume">controlar o volume de multimedia</string>
+ <string name="app_ops_use_notification_volume">controlar o volume das notificacións</string>
+ <string name="app_ops_use_ring_volume">controlar o volume do ton de chamada</string>
+ <string name="app_ops_use_vibrate">utilizar a resposta háptica</string>
+ <string name="app_ops_use_voice_volume">controlar o volume das chamadas de voz</string>
+ <string name="app_ops_write_mms">escribir unha mensaxe MMS</string>
+ <string name="app_ops_write_sms">escribir unha mensaxe SMS</string>
+ <string name="app_ops_read_phone_state">acceder ao estado do móbil</string>
+ <string name="app_ops_assist_structure">usar a estrutura de asistencia</string>
+ <string name="app_ops_assist_screenshot">realizar captura de pantalla</string>
+ <string name="app_ops_turn_on_screen">acender a pantalla</string>
+ <string name="app_ops_get_accounts">obter as contas do dispositivo</string>
+ <string name="app_ops_su">Obter acceso como superusuario</string>
+ <string name="lock_to_app_toast_no_navbar">Para deixar de fixar esta pantalla, mantén tocado o botón Atrás.</string>
+ <string name="live_display_auto">Automático</string>
+ <string name="live_display_auto_summary">Axustar automaticamente os tons da pantalla ao amencer e o solpor</string>
+ <string name="live_display_off">Apagado</string>
+ <string name="live_display_off_summary">Desactivar todos os axustes</string>
+ <string name="live_display_day">Día</string>
+ <string name="live_display_day_summary">Utilizar tan só os axustes de día</string>
+ <string name="live_display_night">Noite</string>
+ <string name="live_display_night_summary">Utilizar tan só os axustes de noite</string>
+ <string name="live_display_outdoor">Exteriores (iluminado)</string>
+ <string name="live_display_outdoor_summary">Utilizar tan só os axustes de exteriores</string>
+ <string name="live_display_hint">O modo LiveDisplay pode axudar coa dor de ollos e a conciliar o sono. Toca aquí para probalo!</string>
+ <string name="tethered_notification_no_device_message">Dispositivo non conectado</string>
+ <string name="tethered_notification_one_device_message">Dispositivo <xliff:g id="count">%1$s</xliff:g> conectado</string>
+ <string name="tethered_notification_multi_device_message">Dispositivos <xliff:g id="count">%1$s</xliff:g> conectados</string>
+</resources>
diff --git a/core/res/res/values-hi/cm_strings.xml b/core/res/res/values-hi/cm_strings.xml
new file mode 100644
index 0000000..8fbbcbc
--- /dev/null
+++ b/core/res/res/values-hi/cm_strings.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">स्क्रीनशॉट</string>
+ <string name="permlab_receiveProtectedSms">रक्षित एसएमएस प्राप्त करें</string>
+ <string name="permdesc_receiveProtectedSms">ऐप को आवक रक्षित एसएमएस प्राप्त करने देता है।</string>
+ <string name="permlab_modifyProtectedSmsList">रक्षित एसएमएस सूची को संशोधित करें</string>
+ <string name="permdesc_modifyProtectedSmsList">ऐप को रक्षित एसएमएस पता सूची को संशोधित करने देता है।</string>
+ <string name="permgrouplab_security">सुरक्षा</string>
+ <string name="permgroupdesc_security">उपकरण सुरक्षा जानकारी से संबंधित अनुमतियाँ।</string>
+ <string name="permlab_readPhoneBlacklist">फ़ोन काली सूची पढ़ें</string>
+ <string name="permdesc_readPhoneBlacklist">ऐप को आवक कॉलों या संदेशों के लिए जिन फ़ोन नंबरों को अवरुद्ध किया गया है, उनसे संबंधित जानकारी पढ़ने देता है।</string>
+ <string name="permlab_changePhoneBlacklist">फ़ोन काली सूची को परिवर्तित करें</string>
+ <string name="permdesc_changePhoneBlacklist">ऐप को आवक कॉलों या संदेशों के लिए जिन फ़ोन नंबरों को अवरुद्ध किया गया है, उन्हें परिवर्तित करने देता है।</string>
+ <string name="permlab_setKeyguardWallpaper">कुंजीकवच वॉलपेपर सेट करें</string>
+ <string name="permdesc_setKeyguardWallpaper">ऐप को स्क्रीन वॉलपेपर लॉक को बदलने देता है।</string>
+ <string name="global_action_reboot">रीबूट करें</string>
+ <string name="global_action_current_user">वर्तमान</string>
+ <string name="reboot_reboot">रीबूट करें</string>
+ <string name="reboot_recovery">रिकवरी</string>
+ <string name="reboot_bootloader">बूटलोडर</string>
+ <string name="reboot_download">डाउनलोड करें</string>
+ <string name="reboot_soft">नरम रीबूट</string>
+ <string name="reboot_title">रीबूट करें</string>
+ <string name="reboot_confirm" product="tablet">आपका टैब्लेट रीबूट करेगा।</string>
+ <string name="reboot_confirm" product="default">आपका फ़ोन रीबूट करेगा।</string>
+ <string name="reboot_progress">रीबूट कर रहे हैं\u2026</string>
+ <string name="app_killed_message">ऐप को मार दिया गया</string>
+ <string name="adb_net_active_notification_title">नेटवर्क पर एडीबी को सक्षम कर दिया गया</string>
+ <string name="adb_both_active_notification_title">यूएसबी और नेटवर्क पर एडीबी को सक्षम कर दिया गया</string>
+ <string name="adb_active_generic_notification_message">डीबगिंग को अक्षम करने के लिए छुएँ।</string>
+ <string name="adb_active_custom_tile">एडीबी - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">यूएसबी और नेटवर्क</string>
+ <string name="adb_active_custom_tile_usb">यूएसबी</string>
+ <string name="adb_active_custom_tile_net">नेटवर्क</string>
+ <string name="permlab_interceptPackageLaunch">ऐप लॉन्च का अंतररोधन करें</string>
+ <string name="stylus_app_not_installed">%s स्थापित नहीं है</string>
+ <string name="silent_mode_priority">वरीयता</string>
+ <string name="silent_mode_none">कुछ नहीं</string>
+ <string name="permlab_changePrivacyGuardState">गोपनीयता रक्षक को सक्षम या अक्षम करें</string>
+ <string name="permdesc_changePrivacyGuardState">ऐप को इसे बदलने देता है कि कोई दूसरा ऐप गोपनीयता रक्षक के साथ चलेगा अथवा नहीं। जब ऐप गोपनीयता रक्षक के साथ चलता है, उसे संपर्क, कॉल लॉग, या संदेश जैसे निजी डेटा तक पहुँचने की अनुमति नहीं होगी।</string>
+ <string name="privacy_guard_notification">गोपनीयता रक्षक सक्रिय है</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> निजी डेटा में पहुँच नहीं सकेगा</string>
+ <string name="privacy_guard_dialog_title">गोपनीयता रक्षक</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> क्या आप <xliff:g id="op">%2$s</xliff:g> करना चाहते हैं।</string>
+ <string name="permission_remember_choice">मेरी पसंद को याद रखें</string>
+ <string name="app_ops_access_camera">कैमरे में पहुँचें</string>
+ <string name="app_ops_access_location">अपने स्थान का उपयोग करें</string>
+ <string name="app_ops_access_notifications">अपनी अधिसूचनाओं को पढ़ें</string>
+ <string name="app_ops_activate_vpn">वीपीएन को सक्रिय करें</string>
+ <string name="app_ops_auto_start">पावर अप के दौरान चालू करें</string>
+ <string name="app_ops_delete_call_log">अपने कॉल लॉग को हटाएँ</string>
+ <string name="app_ops_delete_contacts">अपने संपर्कों को हटाएँ</string>
+ <string name="app_ops_delete_mms">अपने एमएमएस संदेशों को हटाएँ</string>
+ <string name="app_ops_delete_sms">अपने एसएमएस संदेशों को हटाएँ</string>
+ <string name="app_ops_draw_on_top">ऊपर विंडो बनाएँ</string>
+ <string name="app_ops_get_usage_stats">ऐप उपयोग आँकड़े प्राप्त करें</string>
+ <string name="app_ops_keep_device_awake">अपने उपकरण को जागृत रखें</string>
+ <string name="app_ops_make_phone_call">फ़ोन कॉल करें</string>
+ <string name="app_ops_modify_calendar">अपने कैलेंडर को अद्यतन करें</string>
+ <string name="app_ops_modify_call_log">अपने कॉल लॉग को अद्यतन करें</string>
+ <string name="app_ops_modify_clipboard">अपने क्लिपबोर्ड को संशोधित करें</string>
+ <string name="app_ops_modify_contacts">अपने संपर्कों को अद्यतन करें</string>
+ <string name="app_ops_modify_settings">सिस्टम सेटिंग को अद्यतन करें</string>
+ <string name="app_ops_mute_unmute_microphone">माइक्रोफ़ोन को मूक/वाचाल करें</string>
+ <string name="app_ops_play_audio">ऑडियो चलाएँ</string>
+ <string name="app_ops_post_notification">अधिसूचना पोस्ट करें</string>
+ <string name="app_ops_project_media">परियोजना माध्यम</string>
+ <string name="app_ops_read_calendar">अपने कैलेंडर को पढ़ें</string>
+ <string name="app_ops_read_call_log">कॉल लॉग को पढ़ें</string>
+ <string name="app_ops_read_clipboard">क्लिपबोर्ड को पढ़ें</string>
+ <string name="app_ops_read_contacts">अपने संपर्कों को पढ़ें</string>
+ <string name="app_ops_read_mms">अपने एमएमएस संदेशों को पढ़ें</string>
+ <string name="app_ops_read_sms">अपने एसएमएस संदेशों को पढ़ें</string>
+ <string name="app_ops_receive_sms">एसएमएस संदेश प्राप्त करें</string>
+ <string name="app_ops_record_audio">ऑडियो रिकॉर्ड करें</string>
+ <string name="app_ops_send_mms">एमएमएस संदेश भेजें</string>
+ <string name="app_ops_send_sms">एसएमएस संदेश भेजें</string>
+ <string name="app_ops_start_at_bootup">पावर अप पर चालू करें</string>
+ <string name="app_ops_toast_window">टोस्ट संदेश प्रदर्शित करें</string>
+ <string name="app_ops_toggle_bluetooth">ब्लूटूथ को बंद-चालू करें</string>
+ <string name="app_ops_toggle_nfc">एनएफसी को बंद-चालू करें</string>
+ <string name="app_ops_use_alarm_volume">अलार्म वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_use_audio_focus">ऑडियो फ़ोकस को नियंत्रित करें</string>
+ <string name="app_ops_use_bluetooth_volume">ब्लूटूथ वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_use_master_volume">मास्टर वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_use_media_buttons">माध्यम बटनों का उपयोग करें</string>
+ <string name="app_ops_use_media_volume">माध्यम वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_use_notification_volume">अधिसूचना वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_use_ring_volume">रिंगटोन वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_use_vibrate">हैप्टिक फ़ीडबैक का उपयोग करें</string>
+ <string name="app_ops_use_voice_volume">वोइल कॉल वोल्यूम को नियंत्रित करें</string>
+ <string name="app_ops_write_mms">एक एमएमएस संदेश लिखें</string>
+ <string name="app_ops_write_sms">एक एसएमएस संदेश लिखें</string>
+ <string name="app_ops_su">मूल तक पहुँच प्राप्त करें</string>
+ <string name="lock_to_app_toast_no_navbar">इस स्क्रीन को अनपिन करने के लिए पीछे के बटन को कुछ देर के लिए छुएँ।</string>
+ <string name="live_display_auto">स्वचालित</string>
+ <string name="live_display_auto_summary">सूर्यास्त और सूर्योदय के बाद अपने आप ही स्क्रीन के रंग तापमान को समायोजित करें</string>
+ <string name="live_display_off">बंद</string>
+ <string name="live_display_off_summary">सभी समायोजनों को अक्षम करें</string>
+ <string name="live_display_day">दिन</string>
+ <string name="live_display_day_summary">केवल दिन की सेटिंग का उपयोग करें</string>
+ <string name="live_display_night">रात</string>
+ <string name="live_display_night_summary">केवल रात की सेटिंग का उपयोग करें</string>
+ <string name="live_display_outdoor">बाहर (तेज़ धूप)</string>
+ <string name="live_display_outdoor_summary">केवल बाहर की सेटिंग का उपयोग करें</string>
+ <string name="live_display_hint">लाइवडिस्प्ले आँखों पर पड़नेवाले दबाव को घटा सकता है और आपको रात को अच्छी तरह से सोने में मदद कर सकता है। इसे आज़माने के लिए यहाँ क्लिक करें।</string>
+ <string name="tethered_notification_no_device_message">कोई जुड़ा हुआ उपकरण नहीं है</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> जुड़ा हुआ उपकरण</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> जुड़े हुए उपकरण</string>
+</resources>
diff --git a/core/res/res/values-hr/cm_strings.xml b/core/res/res/values-hr/cm_strings.xml
new file mode 100644
index 0000000..8c04191
--- /dev/null
+++ b/core/res/res/values-hr/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Snimak zaslona</string>
+ <string name="permlab_receiveProtectedSms">primaj zaštićeni SMS</string>
+ <string name="permdesc_receiveProtectedSms">Dopušta aplikaciji da prima dolazeći zaštićeni SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">Izmjena popisa zaštićenih SMS poruka</string>
+ <string name="permdesc_modifyProtectedSmsList">Dozvoljava aplikaciji izmjenu popisa adresa zaštićenih SMS poruka.</string>
+ <string name="permgrouplab_security">Sigurnost</string>
+ <string name="permgroupdesc_security">Dopuštenja vezana za sigurnosne informacije uređaja.</string>
+ <string name="permlab_readPhoneBlacklist">čitati listu blokiranih poziva</string>
+ <string name="permdesc_readPhoneBlacklist">Dopušta aplikaciji čitanje informacija o telefonskim brojevima čije su dolazne poruke ili pozivi blokirani.</string>
+ <string name="permlab_changePhoneBlacklist">promjeniti popis blokiranih poziva</string>
+ <string name="permdesc_changePhoneBlacklist">Dopušta aplikaciji promjenu telefonskih brojeva čije su dolazne poruke ili pozivi blokirani.</string>
+ <string name="permlab_setKeyguardWallpaper">postaviti pozadinu zaslona zaključavanja</string>
+ <string name="permdesc_setKeyguardWallpaper">Dozvoljava aplikaciji promjenu pozadine zaslona zaključavanja.</string>
+ <string name="global_action_reboot">Ponovno pokreni</string>
+ <string name="global_action_current_user">Trenutna</string>
+ <string name="reboot_reboot">Ponovno pokreni</string>
+ <string name="reboot_recovery">Način oporavka</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Brzo ponovno pokretanje</string>
+ <string name="reboot_title">Ponovno pokretanje</string>
+ <string name="reboot_confirm" product="tablet">Tablet će ponovno biti pokrenut.</string>
+ <string name="reboot_confirm" product="default">Telefon će ponovno biti pokrenut.</string>
+ <string name="reboot_progress">Ponovno pokretanje\u2026</string>
+ <string name="app_killed_message">Aplikacija prisilno zaustavljena</string>
+ <string name="adb_net_active_notification_title">Mrežni ADB omogućen</string>
+ <string name="adb_both_active_notification_title">ADB preko USB &amp; mreže omogućen</string>
+ <string name="adb_active_generic_notification_message">Dodirnite za onemogućavanje ispravljanja pogrešaka.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s </xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB i mrežni</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Mreža</string>
+ <string name="permlab_interceptPackageLaunch">Presresti pokretanje aplikacija</string>
+ <string name="stylus_app_not_installed">%s nije instalirano</string>
+ <string name="silent_mode_priority">Prioritet</string>
+ <string name="silent_mode_none">Ništa</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi- Fi Hotspot onemogućen zbog SIM promjene</string>
+ <string name="notify_turn_wifi_off_title">Isključite Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">omogućiti ili onemogućiti Zaštitu privatnosti</string>
+ <string name="permdesc_changePrivacyGuardState">Dopušta aplikaciji odrediti hoće li druga aplikacija biti pokrenuta pod Nadzorom Privatnosti. Kada ja aplikacija pod Nadzorom Privatnosti, neće imati pristup osobnim podacima kao što su kontakti, zapisi poziva ili poruke.</string>
+ <string name="privacy_guard_notification">Nadzor privatnosti aktivan</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> neće moći pristupiti osobnim podacima</string>
+ <string name="privacy_guard_dialog_title">Nadzor privatnosti</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> želi <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Zapamti moj odabir</string>
+ <string name="app_ops_access_camera">pristupiti kameri</string>
+ <string name="app_ops_access_location">pristupiti vašoj lokaciji</string>
+ <string name="app_ops_access_notifications">čitati vaše obavijesti</string>
+ <string name="app_ops_activate_vpn">Aktiviraj VPN</string>
+ <string name="app_ops_auto_start">Pokrenuti pri podizanju sustava</string>
+ <string name="app_ops_delete_call_log">Obriši popis poziva</string>
+ <string name="app_ops_delete_contacts">Obriši kontakte</string>
+ <string name="app_ops_delete_mms">Obriši MMS poruke</string>
+ <string name="app_ops_delete_sms">Obriši SMS poruke</string>
+ <string name="app_ops_draw_on_top">Iscrtaj prozore na vrhu</string>
+ <string name="app_ops_get_usage_stats">Statistika korištenja aplikacija</string>
+ <string name="app_ops_keep_device_awake">održavati uređaj budnim</string>
+ <string name="app_ops_make_phone_call">uspostaviti poziv</string>
+ <string name="app_ops_modify_calendar">ažurirati kalendar</string>
+ <string name="app_ops_modify_call_log">ažurirati zapisnik poziva</string>
+ <string name="app_ops_modify_clipboard">urediti clipboard</string>
+ <string name="app_ops_modify_contacts">ažurirati kontakte</string>
+ <string name="app_ops_modify_settings">ažurirati postavke sistema</string>
+ <string name="app_ops_mute_unmute_microphone">Isključiti/uključiti mikrofon</string>
+ <string name="app_ops_play_audio">producirati zvuk</string>
+ <string name="app_ops_post_notification">obavijestiti</string>
+ <string name="app_ops_project_media">Pokrenuti multimediju</string>
+ <string name="app_ops_read_calendar">čitati vaš kalendar</string>
+ <string name="app_ops_read_call_log">čitati zapisnik poziva</string>
+ <string name="app_ops_read_clipboard">čitati Clipboard</string>
+ <string name="app_ops_read_contacts">čitati vaše kontakte</string>
+ <string name="app_ops_read_mms">čitati vaše MMS poruke</string>
+ <string name="app_ops_read_sms">čitati vaše SMS poruke</string>
+ <string name="app_ops_receive_sms">primiti SMS poruku</string>
+ <string name="app_ops_record_audio">snimiti zvuk</string>
+ <string name="app_ops_send_mms">poslati MMS poruku</string>
+ <string name="app_ops_send_sms">poslati SMS poruku</string>
+ <string name="app_ops_start_at_bootup">se pokrenuti pri pokretanju sistema</string>
+ <string name="app_ops_toast_window">Prikazivati toast poruke</string>
+ <string name="app_ops_toggle_bluetooth">upravljati Bluetooth-om</string>
+ <string name="app_ops_toggle_mobile_data">uključi/isključi mobilne podatke</string>
+ <string name="app_ops_toggle_nfc">Uključi/isključi NFC</string>
+ <string name="app_ops_toggle_wifi">upravljati Wi-Fi-em</string>
+ <string name="app_ops_use_alarm_volume">kontrolirati glasnoću alarma</string>
+ <string name="app_ops_use_audio_focus">kontrolirati fokus zvuka</string>
+ <string name="app_ops_use_bluetooth_volume">kontrolirati glasnoću Bluetooth-a</string>
+ <string name="app_ops_use_master_volume">kontrolirati glavnu glasnoću zvuka</string>
+ <string name="app_ops_use_media_buttons">koristiti tipke medija</string>
+ <string name="app_ops_use_media_volume">kontrolirati glasnoću medija</string>
+ <string name="app_ops_use_notification_volume">kontrolirati glasnoću zvuka obavijesti</string>
+ <string name="app_ops_use_ring_volume">kontrolirati glasnoću melodije zvona</string>
+ <string name="app_ops_use_vibrate">koristiti vibraciju</string>
+ <string name="app_ops_use_voice_volume">kontrolirati glasnoću glasovnog poziva</string>
+ <string name="app_ops_write_mms">napisati MMS poruku</string>
+ <string name="app_ops_write_sms">napisati SMS poruku</string>
+ <string name="app_ops_use_fingerprint">koristite otisak prsta</string>
+ <string name="app_ops_add_voicemail">dodajte glasovnu poruku</string>
+ <string name="app_ops_read_phone_state">pristup stanju telefona</string>
+ <string name="app_ops_scan_wifi">skeniraj Wi-Fi mreže</string>
+ <string name="app_ops_change_wallpaper">promjeni pozadinsku sliku</string>
+ <string name="app_ops_assist_structure">koristi pomoćne strukture</string>
+ <string name="app_ops_assist_screenshot">snimak zaslona</string>
+ <string name="app_ops_use_body_sensors">koristi senzore</string>
+ <string name="app_ops_read_cell_broadcasts">pročitati signal odašiljača</string>
+ <string name="app_ops_mock_location">prikazivanje lažne lokacije</string>
+ <string name="app_ops_read_external_storage">čitaj vanjsku pohranu</string>
+ <string name="app_ops_write_external_storage">piši na vanjsku pohranu</string>
+ <string name="app_ops_turn_on_screen">uključite zaslon</string>
+ <string name="app_ops_get_accounts">dobavi račune uređaja</string>
+ <string name="app_ops_wifi_change">promjeni Wi-Fi stanje</string>
+ <string name="app_ops_su">Zatraži root pristup</string>
+ <string name="lock_to_app_toast_no_navbar">Za otkvačiti ovaj zaslon dodirnite i držite tipku za natrag</string>
+ <string name="live_display_auto">Automatski</string>
+ <string name="live_display_auto_summary">Automatski prilagodi temperaturu boje zaslona nakon zalaska i izlaska sunca</string>
+ <string name="live_display_off">Isključeno</string>
+ <string name="live_display_off_summary">Onemogući sva prilagođavanja</string>
+ <string name="live_display_day">Dan</string>
+ <string name="live_display_day_summary">Koristi samo postavke za dan</string>
+ <string name="live_display_night">Noć</string>
+ <string name="live_display_night_summary">Koristi samo postavke za noć</string>
+ <string name="live_display_outdoor">Vani (jako sunce)</string>
+ <string name="live_display_outdoor_summary">Koristi samo postavke za van</string>
+ <string name="live_display_hint">LiveDisplay može smanjiti naprezanje očiju i poboljšati san. Dodirnite ovdje ako ga želite isprobati!</string>
+ <string name="tethered_notification_no_device_message">Uređaj nije spojen</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> povezani uređaj</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> povezanih uređaja</string>
+ <string name="notify_package_component_protected_title">Blokirana aktivnost pokretanja</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> je zaštićena od pokretanja. Dodirnite za potvrdu i pokrenite aplikaciju.</string>
+ <string name="notify_battery_fully_charged_title">Baterija puna</string>
+ <string name="notify_battery_fully_charged_text">Odspojite punjač s uređaja da bi poboljšali trajnost baterije.</string>
+</resources>
diff --git a/core/res/res/values-hu/cm_strings.xml b/core/res/res/values-hu/cm_strings.xml
new file mode 100644
index 0000000..99e1062
--- /dev/null
+++ b/core/res/res/values-hu/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Képernyőmentés</string>
+ <string name="permlab_receiveProtectedSms">védett SMS fogadása</string>
+ <string name="permdesc_receiveProtectedSms">Lehetővé teszi az alkalmazás számára, hogy védett SMS-t fogadjon.</string>
+ <string name="permlab_modifyProtectedSmsList">védett SMS lista módosítása</string>
+ <string name="permdesc_modifyProtectedSmsList">Lehetővé teszi az alkalmazás számára, hogy módosítsa a védett SMS címlistát.</string>
+ <string name="permgrouplab_security">Biztonság</string>
+ <string name="permgroupdesc_security">Engedélyek az eszköz biztonsági információira vonatkozóan.</string>
+ <string name="permlab_readPhoneBlacklist">tiltólista olvasása</string>
+ <string name="permdesc_readPhoneBlacklist">Lehetővé teszi az alkalmazás számára, hogy olvassa azokat a számokat, melyek blokkolva vannak bejövő hívásnál vagy üzenetnél.</string>
+ <string name="permlab_changePhoneBlacklist">tiltólista módosítása</string>
+ <string name="permdesc_changePhoneBlacklist">Lehetővé teszi az alkalmazás számára, hogy szerkessze azokat a telefonszámokat melyek blokkolva vannak bejövő hívásnál vagy üzenetnél.</string>
+ <string name="permlab_setKeyguardWallpaper">billentyűzár háttérképének beállítása</string>
+ <string name="permdesc_setKeyguardWallpaper">Lehetővé teszi az alkalmazás számára, hogy módosítsa a képernyőzár hátterét.</string>
+ <string name="global_action_reboot">Újraindítás</string>
+ <string name="global_action_current_user">Jelenlegi</string>
+ <string name="reboot_reboot">Újraindítás</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Lágy újraindítás</string>
+ <string name="reboot_title">Újraindítás</string>
+ <string name="reboot_confirm" product="tablet">A táblagép újraindul.</string>
+ <string name="reboot_confirm" product="default">A telefon újraindul.</string>
+ <string name="reboot_progress">Újraindítás\u2026</string>
+ <string name="app_killed_message">Alkalmazás leállítva</string>
+ <string name="adb_net_active_notification_title">ADB hálózaton keresztül engedélyezve</string>
+ <string name="adb_both_active_notification_title">ADB USB-n &amp; hálózaton keresztül engedélyezve</string>
+ <string name="adb_active_generic_notification_message">Érintse meg a hibakeresés letiltásához.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; hálózat</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Hálózat</string>
+ <string name="permlab_interceptPackageLaunch">alkalmazás indításának feltartóztatása</string>
+ <string name="stylus_app_not_installed">%s nincs telepítve</string>
+ <string name="silent_mode_priority">Prioritás</string>
+ <string name="silent_mode_none">Nincs</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi\u2011Fi hotspot kikapcsolva a SIM előfizetés módosítása miatt</string>
+ <string name="notify_turn_wifi_off_title">Wi\u2011Fi kikapcsolása</string>
+ <string name="permlab_changePrivacyGuardState">adatvédelem engedélyezése vagy tiltása</string>
+ <string name="permdesc_changePrivacyGuardState">Lehetővé teszi, hogy más alkalmazások számára engedélyezze, vagy letiltsa az adatvédelmet. Amikor az alkalmazás adatvédelmi módban fut, nem fog hozzáférni az Ön személyes adataihoz, mint a névjegyzékéhez, üzeneteihez, vagy a hívásnaplójához.</string>
+ <string name="privacy_guard_notification">Adatvédelem aktív</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> nem fog hozzáférni a személyes adataihoz</string>
+ <string name="privacy_guard_dialog_title">Adatvédelmi beállítások</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> a következő műveletet szeretné végrehajtani: <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Jegyezze meg a választást</string>
+ <string name="app_ops_access_camera">hozzáférés a kamerához</string>
+ <string name="app_ops_access_location">hozzáférés a helyadataihoz</string>
+ <string name="app_ops_access_notifications">értesítések olvasása</string>
+ <string name="app_ops_activate_vpn">VPN-kapcsolat aktiválása</string>
+ <string name="app_ops_auto_start">bekapcsoláskor elindul</string>
+ <string name="app_ops_delete_call_log">hívásnapló törlése</string>
+ <string name="app_ops_delete_contacts">névjegyek törlése</string>
+ <string name="app_ops_delete_mms">MMS-üzenetek törlése</string>
+ <string name="app_ops_delete_sms">SMS-üzenetek törlése</string>
+ <string name="app_ops_draw_on_top">átfedő ablakok rajzolása</string>
+ <string name="app_ops_get_usage_stats">hozzáférés alkalmazás használati statisztikákhoz</string>
+ <string name="app_ops_keep_device_awake">készülék ébrentartása</string>
+ <string name="app_ops_make_phone_call">hívást kezdeményezhet</string>
+ <string name="app_ops_modify_calendar">frissítheti a naptárat</string>
+ <string name="app_ops_modify_call_log">frissítheti a hívásnaplót</string>
+ <string name="app_ops_modify_clipboard">módosíthatja a vágólapot</string>
+ <string name="app_ops_modify_contacts">frissítheti a névjegyzéket</string>
+ <string name="app_ops_modify_settings">frissítheti a rendszerbeállításokat</string>
+ <string name="app_ops_mute_unmute_microphone">mikrofon némítása/némítás feloldása</string>
+ <string name="app_ops_play_audio">zene lejátszása</string>
+ <string name="app_ops_post_notification">értesítés küldése</string>
+ <string name="app_ops_project_media">hozzáférés a médiához</string>
+ <string name="app_ops_read_calendar">naptár olvasása</string>
+ <string name="app_ops_read_call_log">hívásnapló olvasása</string>
+ <string name="app_ops_read_clipboard">vágólap olvasása</string>
+ <string name="app_ops_read_contacts">névjegyek olvasása</string>
+ <string name="app_ops_read_mms">MMS üzenetek olvasása</string>
+ <string name="app_ops_read_sms">SMS üzenetek olvasása</string>
+ <string name="app_ops_receive_sms">SMS üzenet fogadása</string>
+ <string name="app_ops_record_audio">hangfelvétel készítése</string>
+ <string name="app_ops_send_mms">MMS üzenet küldése</string>
+ <string name="app_ops_send_sms">SMS üzenet küldése</string>
+ <string name="app_ops_start_at_bootup">bekapcsoláskor elindul</string>
+ <string name="app_ops_toast_window">buborékszöveg üzenetek megjelenítése</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth kapcsolása</string>
+ <string name="app_ops_toggle_mobile_data">mobilnet váltása</string>
+ <string name="app_ops_toggle_nfc">NFC kapcsolása</string>
+ <string name="app_ops_toggle_wifi">Wi-Fi kapcsolása</string>
+ <string name="app_ops_use_alarm_volume">ébresztőhang vezérlése</string>
+ <string name="app_ops_use_audio_focus">hang fókusz vezérlése</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetooth hangerő vezérlése</string>
+ <string name="app_ops_use_master_volume">fő hangerő vezérlése</string>
+ <string name="app_ops_use_media_buttons">média gombok használata</string>
+ <string name="app_ops_use_media_volume">média hangerő vezérlése</string>
+ <string name="app_ops_use_notification_volume">értesítési hangerő vezérlése</string>
+ <string name="app_ops_use_ring_volume">csengőhang hangerejének vezérlése</string>
+ <string name="app_ops_use_vibrate">érintési visszajelzés használata</string>
+ <string name="app_ops_use_voice_volume">hívás közbeni hang vezérlése</string>
+ <string name="app_ops_write_mms">MMS írása</string>
+ <string name="app_ops_write_sms">SMS írása</string>
+ <string name="app_ops_use_fingerprint">ujjlenyomat használata</string>
+ <string name="app_ops_add_voicemail">hangposta hozzáadása</string>
+ <string name="app_ops_read_phone_state">hozzáférés telefon állapotához</string>
+ <string name="app_ops_scan_wifi">Wi-Fi hálózatok keresése</string>
+ <string name="app_ops_change_wallpaper">háttérkép módosítása</string>
+ <string name="app_ops_assist_structure">támogatási szerkezet használata</string>
+ <string name="app_ops_assist_screenshot">képernyőmentés készítése</string>
+ <string name="app_ops_use_body_sensors">testszenzorok használata</string>
+ <string name="app_ops_read_cell_broadcasts">hálózati üzenetek olvasása</string>
+ <string name="app_ops_mock_location">helyutánzatok engedélyezése</string>
+ <string name="app_ops_read_external_storage">külső tároló olvasása</string>
+ <string name="app_ops_write_external_storage">külső tároló írása</string>
+ <string name="app_ops_turn_on_screen">képernyő bekapcsolása</string>
+ <string name="app_ops_get_accounts">eszköz fiókok lekérése</string>
+ <string name="app_ops_wifi_change">Wi-Fi állapot módosítása</string>
+ <string name="app_ops_su">rendszergazdai jogosultság szerzése</string>
+ <string name="lock_to_app_toast_no_navbar">Képernyő rögzítésének feloldásához érintse meg és tartsa nyomva a Vissza gombot.</string>
+ <string name="live_display_auto">Automatikus</string>
+ <string name="live_display_auto_summary">Automatikusan beállítja a képernyő színhőmérsékletét napnyugta és napkelte után</string>
+ <string name="live_display_off">Ki</string>
+ <string name="live_display_off_summary">Az összes beállítás kikapcsolása</string>
+ <string name="live_display_day">Nappal</string>
+ <string name="live_display_day_summary">Csak a nappali beállítások használata</string>
+ <string name="live_display_night">Éjszaka</string>
+ <string name="live_display_night_summary">Csak az éjszakai béállítások használata</string>
+ <string name="live_display_outdoor">Kültéri (erős napfény)</string>
+ <string name="live_display_outdoor_summary">Csak a kültéri beállítások használata</string>
+ <string name="live_display_hint">A LiveDisplay segíthet a szemek terhelésének csökkentésében és a jobb éjszakai alvásban. Kattintson ide, hogy kipróbálja!</string>
+ <string name="tethered_notification_no_device_message">Nincs csatlakoztatott készülék</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> csatlakoztatott eszköz</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> csatlakoztatott eszköz</string>
+ <string name="notify_package_component_protected_title">Tevékenység elindítás blokkolva</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> védve van az indításra. Kattintson a hitelesítésére és indítsa el az alkalmazást.</string>
+ <string name="notify_battery_fully_charged_title">Akkumulátor teljesen feltöltve</string>
+ <string name="notify_battery_fully_charged_text">A készüléket vegye le a töltőről, hogy javítsa az akkumulátor élettartamát.</string>
+</resources>
diff --git a/core/res/res/values-in/cm_strings.xml b/core/res/res/values-in/cm_strings.xml
new file mode 100644
index 0000000..0b540da
--- /dev/null
+++ b/core/res/res/values-in/cm_strings.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Tangkapan Layar</string>
+ <string name="permlab_receiveProtectedSms">terima SMS yang dilindungi</string>
+ <string name="permdesc_receiveProtectedSms">Izinkan aplikasi untuk menerima SMS masuk yang dilindungi.</string>
+ <string name="permlab_modifyProtectedSmsList">modifikasi daftar SMS yang dilindungi</string>
+ <string name="permdesc_modifyProtectedSmsList">Izinkan aplikasi untuk mengubah daftar alamat SMS yang dilindungi.</string>
+ <string name="permgrouplab_security">Keamanan</string>
+ <string name="permgroupdesc_security">Izin terkait dengan informasi keamanan perangkat.</string>
+ <string name="permlab_readPhoneBlacklist">baca blacklist telepon</string>
+ <string name="permdesc_readPhoneBlacklist">Memungkinkan aplikasi untuk membaca informasi tentang nomor telepon yang diblokir untuk panggilan atau pesan.</string>
+ <string name="permlab_changePhoneBlacklist">ubah blacklist telepon</string>
+ <string name="permdesc_changePhoneBlacklist">Memungkinkan aplikasi untuk mengubah nomor telepon yang diblokir untuk panggilan atau pesan.</string>
+ <string name="permlab_setKeyguardWallpaper">set keyguard wallpaper</string>
+ <string name="permdesc_setKeyguardWallpaper">Izinkan aplikasi untuk mengubah wallpaper layar kunci.</string>
+ <string name="global_action_reboot">Reboot</string>
+ <string name="global_action_current_user">Saat ini</string>
+ <string name="reboot_reboot">Reboot</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Soft reboot</string>
+ <string name="reboot_title">Reboot</string>
+ <string name="reboot_confirm" product="tablet">Tablet Anda akan direboot.</string>
+ <string name="reboot_confirm" product="default">Ponsel Anda akan direboot.</string>
+ <string name="reboot_progress">Rebooting\u2026</string>
+ <string name="app_killed_message">Aplikasi dimatikan</string>
+ <string name="adb_net_active_notification_title">ADB melalui jaringan diaktifkan</string>
+ <string name="adb_both_active_notification_title">ADB melalui USB &amp; jaringan diaktifkan</string>
+ <string name="adb_active_generic_notification_message">Sentuh untuk menonaktifkan debug.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">Jaringan &amp; USB</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Jaringan</string>
+ <string name="permlab_interceptPackageLaunch">Mencegah memulai aplikasi</string>
+ <string name="stylus_app_not_installed">%s tidak terpasang</string>
+ <string name="silent_mode_priority">Prioritas</string>
+ <string name="silent_mode_none">Tidak Ada</string>
+ <string name="permlab_changePrivacyGuardState">Aktifkan atau nonaktifkan Penjaga Privasi</string>
+ <string name="permdesc_changePrivacyGuardState">Perbolehkan aplikasi untuk mengubah apakah applikasi lain berjalan dengan Penjaga Privasi. Ketika aplikasi berjalan dengan Penjaga Privasi, aplikasi tidak akan memiliki akses ke data pribadi seperti kontak, daftar panggilan atau pesan.</string>
+ <string name="privacy_guard_notification">Penjaga Privasi aktif</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> tidak akan dapat mengakses data pribadi</string>
+ <string name="privacy_guard_dialog_title">Penjaga Privasi</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> ingin <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Ingat pilihan saya</string>
+ <string name="app_ops_access_camera">mengakses kamera</string>
+ <string name="app_ops_access_location">mengakses lokasi anda</string>
+ <string name="app_ops_access_notifications">membaca notifikasi anda</string>
+ <string name="app_ops_activate_vpn">Aktifkan VPN</string>
+ <string name="app_ops_auto_start">mulai pada saat dinyalakan</string>
+ <string name="app_ops_delete_call_log">hapus log panggilan Anda</string>
+ <string name="app_ops_delete_contacts">hapus kontak Anda</string>
+ <string name="app_ops_delete_mms">hapus pesan MMS Anda</string>
+ <string name="app_ops_delete_sms">hapus pesan SMS Anda</string>
+ <string name="app_ops_draw_on_top">menarik jendela di atas</string>
+ <string name="app_ops_get_usage_stats">dapatkan statistik penggunaan aplikasi</string>
+ <string name="app_ops_keep_device_awake">jaga perangkat anda tetap bangun</string>
+ <string name="app_ops_make_phone_call">membuat panggilan telepon</string>
+ <string name="app_ops_modify_calendar">memperbarui kalender anda</string>
+ <string name="app_ops_modify_call_log">memperbarui daftar panggilan</string>
+ <string name="app_ops_modify_clipboard">memodifikasi clipboard</string>
+ <string name="app_ops_modify_contacts">memperbarui kontak anda</string>
+ <string name="app_ops_modify_settings">memperbarui pengaturan sistem</string>
+ <string name="app_ops_mute_unmute_microphone">diam/mengaktifkan suara mikrofon</string>
+ <string name="app_ops_play_audio">putar audio</string>
+ <string name="app_ops_post_notification">mengirim pemberitahuan</string>
+ <string name="app_ops_project_media">proyek media</string>
+ <string name="app_ops_read_calendar">membaca kalender anda</string>
+ <string name="app_ops_read_call_log">membaca daftar panggilan</string>
+ <string name="app_ops_read_clipboard">membaca clipboard</string>
+ <string name="app_ops_read_contacts">membaca kontak anda</string>
+ <string name="app_ops_read_mms">membaca pesan MMS anda</string>
+ <string name="app_ops_read_sms">membaca pesan SMS anda</string>
+ <string name="app_ops_receive_sms">menerima pesan SMS</string>
+ <string name="app_ops_record_audio">merekam audio</string>
+ <string name="app_ops_send_mms">mengirim pesan MMS</string>
+ <string name="app_ops_send_sms">mengirim pesan SMS</string>
+ <string name="app_ops_start_at_bootup">mulai pada saat dinyalakan</string>
+ <string name="app_ops_toast_window">tampilkan pesan toast</string>
+ <string name="app_ops_toggle_bluetooth">toggle Bluetooth</string>
+ <string name="app_ops_toggle_nfc">toggle NFC</string>
+ <string name="app_ops_use_alarm_volume">mengatur volume alarm</string>
+ <string name="app_ops_use_audio_focus">mengatur fokus audio</string>
+ <string name="app_ops_use_bluetooth_volume">mengatur volume Bluetooth</string>
+ <string name="app_ops_use_master_volume">mengatur volume utama</string>
+ <string name="app_ops_use_media_buttons">menggunakan tombol media</string>
+ <string name="app_ops_use_media_volume">mengatur volume media</string>
+ <string name="app_ops_use_notification_volume">mengatur volume pemberitahuan</string>
+ <string name="app_ops_use_ring_volume">mengatur volume nada dering</string>
+ <string name="app_ops_use_vibrate">menggunakan umpan balik haptic</string>
+ <string name="app_ops_use_voice_volume">mengatur volume panggilan suara</string>
+ <string name="app_ops_write_mms">tulis pesan MMS</string>
+ <string name="app_ops_write_sms">tulis pesan SMS</string>
+ <string name="app_ops_su">dapatkan akses root</string>
+ <string name="lock_to_app_toast_no_navbar">Untuk melepas sematan layar ini, sentuh dan tahan tombol Kembali.</string>
+ <string name="live_display_auto">Otomatis</string>
+ <string name="live_display_auto_summary">Secara otomatis menyesuaikan suhu warna layar setelah matahari terbenam dan terbit</string>
+ <string name="live_display_off">Nonaktif</string>
+ <string name="live_display_off_summary">Menonaktifkan semua penyesuaian</string>
+ <string name="live_display_day">Hari</string>
+ <string name="live_display_day_summary">Menggunakan pengaturan hari hanya</string>
+ <string name="live_display_night">Malam</string>
+ <string name="live_display_night_summary">Menggunakan pengaturan malam saja</string>
+ <string name="live_display_outdoor">Luar ruangan (matahari terang)</string>
+ <string name="live_display_outdoor_summary">Gunakan pengaturan luar ruangan saja</string>
+ <string name="live_display_hint">LiveDisplay dapat membantu mengurangi kelelahan mata dan membantu Anda tidur di malam hari. Klik di sini untuk mencobanya!</string>
+ <string name="tethered_notification_no_device_message">Tidak ada perangkat yang terhubung</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> perangkat yang terhubung</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> perangkat yang terhubung</string>
+</resources>
diff --git a/core/res/res/values-it/cm_strings.xml b/core/res/res/values-it/cm_strings.xml
new file mode 100644
index 0000000..0c418b7
--- /dev/null
+++ b/core/res/res/values-it/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Cattura schermata</string>
+ <string name="permlab_receiveProtectedSms">ricevere SMS protetti</string>
+ <string name="permdesc_receiveProtectedSms">Consenti all\'app di ricevere SMS protetti.</string>
+ <string name="permlab_modifyProtectedSmsList">modifica la lista di SMS protetti</string>
+ <string name="permdesc_modifyProtectedSmsList">Consente all\'app di modificare la lista indirizzi SMS protetta.</string>
+ <string name="permgrouplab_security">Sicurezza</string>
+ <string name="permgroupdesc_security">Autorizzazioni relative alle informazioni sulla sicurezza del dispositivo.</string>
+ <string name="permlab_readPhoneBlacklist">legge la blacklist del telefono</string>
+ <string name="permdesc_readPhoneBlacklist">Consente all\'app di leggere le informazioni sui numeri di telefono che vengono bloccati per messaggi o chiamate in arrivo.</string>
+ <string name="permlab_changePhoneBlacklist">modifica la blacklist del telefono</string>
+ <string name="permdesc_changePhoneBlacklist">Consente all\'app di modificare i numeri di telefono che vengono bloccati per messaggi o chiamate in arrivo.</string>
+ <string name="permlab_setKeyguardWallpaper">imposta sfondo sblocco schermo</string>
+ <string name="permdesc_setKeyguardWallpaper">Consente all\'app di cambiare lo sfondo della schermata di sblocco.</string>
+ <string name="global_action_reboot">Riavvia</string>
+ <string name="global_action_current_user">Corrente</string>
+ <string name="reboot_reboot">Riavvia</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Riavvio veloce</string>
+ <string name="reboot_title">Riavvia</string>
+ <string name="reboot_confirm" product="tablet">Il dispositivo verrà riavviato.</string>
+ <string name="reboot_confirm" product="default">Il telefono verrà riavviato.</string>
+ <string name="reboot_progress">Riavvio\u2026</string>
+ <string name="app_killed_message">App terminata</string>
+ <string name="adb_net_active_notification_title">ADB attraverso la rete attivato</string>
+ <string name="adb_both_active_notification_title">ADB attraverso USB &amp; rete attivato</string>
+ <string name="adb_active_generic_notification_message">Tocca per disattivare il debug.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; rete</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Rete</string>
+ <string name="permlab_interceptPackageLaunch">Intercetta lancio app</string>
+ <string name="stylus_app_not_installed">%s non è installato</string>
+ <string name="silent_mode_priority">Priorità</string>
+ <string name="silent_mode_none">Nessuno</string>
+ <string name="subscription_change_disabled_wifi_ap">Hotspot WiFi disattivato in seguito al cambio di SIM</string>
+ <string name="notify_turn_wifi_off_title">Spegni Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">attiva o disattiva Privacy Guard</string>
+ <string name="permdesc_changePrivacyGuardState">Consente all\'app di decidere se un\'altra app viene eseguita con Privacy Guard. Quando un\'app viene eseguita con Privacy Guard, non ha accesso a dati personali come contatti, lista chiamate o messaggi.</string>
+ <string name="privacy_guard_notification">Privacy Guard attiva</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> non sarà in grado di accedere ai dati personali</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> vorrebbe <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Ricorda la mia scelta</string>
+ <string name="app_ops_access_camera">accedere alla fotocamera</string>
+ <string name="app_ops_access_location">accedere alla posizione</string>
+ <string name="app_ops_access_notifications">leggere le tue notifiche</string>
+ <string name="app_ops_activate_vpn">Attiva una VPN</string>
+ <string name="app_ops_auto_start">avvia all\'accensione</string>
+ <string name="app_ops_delete_call_log">Elimina la tua lista delle chiamate</string>
+ <string name="app_ops_delete_contacts">Elimina i tuoi contatti</string>
+ <string name="app_ops_delete_mms">Elimina i tuoi messaggi MMS</string>
+ <string name="app_ops_delete_sms">Elimina i tuoi messaggi SMS</string>
+ <string name="app_ops_draw_on_top">disegna sopra</string>
+ <string name="app_ops_get_usage_stats">Ottieni le statistiche di utilizzo</string>
+ <string name="app_ops_keep_device_awake">mantenere il dispositivo sveglio</string>
+ <string name="app_ops_make_phone_call">effettuare una chiamata</string>
+ <string name="app_ops_modify_calendar">aggiornare il tuo calendario</string>
+ <string name="app_ops_modify_call_log">aggiornare il registro chiamate</string>
+ <string name="app_ops_modify_clipboard">modificare gli appunti</string>
+ <string name="app_ops_modify_contacts">aggiornare i tuoi contatti</string>
+ <string name="app_ops_modify_settings">aggiornare le impostazioni di sistema</string>
+ <string name="app_ops_mute_unmute_microphone">attiva/disattiva microfono</string>
+ <string name="app_ops_play_audio">riprodurre audio</string>
+ <string name="app_ops_post_notification">inviare una notifica</string>
+ <string name="app_ops_project_media">proietta media</string>
+ <string name="app_ops_read_calendar">leggere il tuo calendario</string>
+ <string name="app_ops_read_call_log">leggere il registro chiamate</string>
+ <string name="app_ops_read_clipboard">leggere gli appunti</string>
+ <string name="app_ops_read_contacts">leggere i tuoi contatti</string>
+ <string name="app_ops_read_mms">leggere i tuoi messaggi MMS</string>
+ <string name="app_ops_read_sms">leggere i tuoi messaggi SMS</string>
+ <string name="app_ops_receive_sms">ricevere un messaggio SMS</string>
+ <string name="app_ops_record_audio">registrare audio</string>
+ <string name="app_ops_send_mms">inviare un messaggio MMS</string>
+ <string name="app_ops_send_sms">inviare un messaggio SMS</string>
+ <string name="app_ops_start_at_bootup">avviarsi all\'accensione</string>
+ <string name="app_ops_toast_window">mostra messaggi di nofifica</string>
+ <string name="app_ops_toggle_bluetooth">cambiare stato del Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">modifica dati mobili</string>
+ <string name="app_ops_toggle_nfc">cambiare stato dell\'NFC</string>
+ <string name="app_ops_toggle_wifi">modifica Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">controllare il volume sveglia</string>
+ <string name="app_ops_use_audio_focus">controllare il focus audio</string>
+ <string name="app_ops_use_bluetooth_volume">controllare il volume Bluetooth</string>
+ <string name="app_ops_use_master_volume">controllare il volume master</string>
+ <string name="app_ops_use_media_buttons">usare i pulsanti multimediali</string>
+ <string name="app_ops_use_media_volume">controllare il volume multimediale</string>
+ <string name="app_ops_use_notification_volume">controllare il volume notifiche</string>
+ <string name="app_ops_use_ring_volume">controllare il volume suoneria</string>
+ <string name="app_ops_use_vibrate">usare il feedback aptico</string>
+ <string name="app_ops_use_voice_volume">controllare il volume della chiamata</string>
+ <string name="app_ops_write_mms">scrivere un messaggio MMS</string>
+ <string name="app_ops_write_sms">scrivere un messaggio SMS</string>
+ <string name="app_ops_use_fingerprint">utilizza le impronte digitali</string>
+ <string name="app_ops_add_voicemail">aggiungi un messaggio vocale</string>
+ <string name="app_ops_read_phone_state">accedi allo stato del telefono</string>
+ <string name="app_ops_scan_wifi">scansiona reti Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">cambia lo sfondo</string>
+ <string name="app_ops_assist_structure">utilizza struttura assistenza</string>
+ <string name="app_ops_assist_screenshot">cattura una schermata</string>
+ <string name="app_ops_use_body_sensors">utilizza sensori per il corpo</string>
+ <string name="app_ops_read_cell_broadcasts">leggi trasmissioni cellulari</string>
+ <string name="app_ops_mock_location">falsifica la tua posizione</string>
+ <string name="app_ops_read_external_storage">leggi scheda SD</string>
+ <string name="app_ops_write_external_storage">scrivi su scheda SD</string>
+ <string name="app_ops_turn_on_screen">accendi lo schermo</string>
+ <string name="app_ops_get_accounts">ottieni account dispositivo</string>
+ <string name="app_ops_wifi_change">cambia stato Wi-Fi</string>
+ <string name="app_ops_su">Ottieni accesso root</string>
+ <string name="lock_to_app_toast_no_navbar">Per sbloccare questo schermo, tocca e tieni premuto il pulsante indietro.</string>
+ <string name="live_display_auto">Automatico</string>
+ <string name="live_display_auto_summary">Regola automaticamente la temperatura del colore dello schermo dopo il tramonto e l\'alba</string>
+ <string name="live_display_off">Disattivato</string>
+ <string name="live_display_off_summary">Disattiva tutte le regolazioni</string>
+ <string name="live_display_day">Giorno</string>
+ <string name="live_display_day_summary">Usa solo impostazioni giorno</string>
+ <string name="live_display_night">Notte</string>
+ <string name="live_display_night_summary">Utilizza solo impostazioni notte</string>
+ <string name="live_display_outdoor">All\'aperto (sole)</string>
+ <string name="live_display_outdoor_summary">Utilizza solo impostazioni all\'aperto</string>
+ <string name="live_display_hint">LiveDisplay aiuta a ridurre l\'affaticamento degli occhi e aiuta a dormire di notte. Clicca per provarlo!</string>
+ <string name="tethered_notification_no_device_message">Nessun dispositivo connesso</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivo connesso</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivi connessi</string>
+ <string name="notify_package_component_protected_title">Lancio dell\'app bloccato</string>
+ <string name="notify_package_component_protected_text">L\'app <xliff:g id="app_name">%1$s</xliff:g> è protetta. Tocca qui per autenticarti e aprire l\'app.</string>
+ <string name="notify_battery_fully_charged_title">Batteria completamente carica</string>
+ <string name="notify_battery_fully_charged_text">Disconnetti il dispositivo dal caricatore per preservare la longevità della batteria.</string>
+</resources>
diff --git a/core/res/res/values-iw/cm_strings.xml b/core/res/res/values-iw/cm_strings.xml
new file mode 100644
index 0000000..42da952
--- /dev/null
+++ b/core/res/res/values-iw/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">צילום מסך</string>
+ <string name="permlab_receiveProtectedSms">קבלת הודעות SMS מוגנות</string>
+ <string name="permdesc_receiveProtectedSms">מאפשר ליישום לקבל הודעות SMS מוגנות.</string>
+ <string name="permlab_modifyProtectedSmsList">שינוי רשימת הודעות SMS מוגנות</string>
+ <string name="permdesc_modifyProtectedSmsList">מאפשר ליישום לשנות את רשימת הכתובות של הודעות SMS מוגנות.</string>
+ <string name="permgrouplab_security">אבטחה</string>
+ <string name="permgroupdesc_security">הרשאות הקשורות לאבטחת המידע במכשיר.</string>
+ <string name="permlab_readPhoneBlacklist">קריאת הרשימה השחורה של המכשיר</string>
+ <string name="permdesc_readPhoneBlacklist">מאפשר ליישום לגשת למידע אודות מספרי הטלפון שנחסמו לקבלת שיחות והודעות נכנסות.</string>
+ <string name="permlab_changePhoneBlacklist">שינוי הרשימה השחורה</string>
+ <string name="permdesc_changePhoneBlacklist">מאפשר ליישום לשנות את המספרים המופיעים ברשימה השחורה, אשר נחסמו לקבלת שיחות והודעות נכנסות.</string>
+ <string name="permlab_setKeyguardWallpaper">הגדרת טפט למסך הנעילה</string>
+ <string name="permdesc_setKeyguardWallpaper">מאפשר ליישום לשנות את הטפט של מסך הנעילה.</string>
+ <string name="global_action_reboot">הפעלה מחדש</string>
+ <string name="global_action_current_user">נוכחי</string>
+ <string name="reboot_reboot">הפעלה מחדש</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">מצב הורדה</string>
+ <string name="reboot_soft">אתחול מהיר</string>
+ <string name="reboot_title">הפעלה מחדש</string>
+ <string name="reboot_confirm" product="tablet">הטאבלט יופעל מחדש.</string>
+ <string name="reboot_confirm" product="default">המכשיר יופעל מחדש.</string>
+ <string name="reboot_progress">מאתחל\u2026</string>
+ <string name="app_killed_message">היישום נסגר</string>
+ <string name="adb_net_active_notification_title">ADB דרך רשת מופעל</string>
+ <string name="adb_both_active_notification_title">ADB דרך USB ורשת מופעל</string>
+ <string name="adb_active_generic_notification_message">לחץ לעצירת איתור באגים.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB ורשת</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">רשת</string>
+ <string name="permlab_interceptPackageLaunch">יירוט הפעלת יישום</string>
+ <string name="stylus_app_not_installed">%s לא מותקן</string>
+ <string name="silent_mode_priority">עדיפות</string>
+ <string name="silent_mode_none">ללא</string>
+ <string name="subscription_change_disabled_wifi_ap">נקודת Wi-Fi חמה הושבתה עקב שינוי מנוי SIM</string>
+ <string name="notify_turn_wifi_off_title">כיבוי Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">הפעלה או השבתה של שומר הפרטיות</string>
+ <string name="permdesc_changePrivacyGuardState">מאפשר ליישום לקבוע האם יישום אחר יפעל תחת שומר הפרטיות. כאשר יישום פועל תחת שומר הפרטיות, לא תהיה לו גישה למידע פרטי כמו אנשי קשר, יומן שיחות והודעות.</string>
+ <string name="privacy_guard_notification">שומר הפרטיות פעיל</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> לא יוכל לגשת למידע אישי</string>
+ <string name="privacy_guard_dialog_title">שומר הפרטיות</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> מבקש <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">זכור את הבחירה שלי</string>
+ <string name="app_ops_access_camera">גישה למצלמה</string>
+ <string name="app_ops_access_location">גישה למיקום שלך</string>
+ <string name="app_ops_access_notifications">קריאת ההתראות שלך</string>
+ <string name="app_ops_activate_vpn">הפעלת VPN</string>
+ <string name="app_ops_auto_start">התחלת פעילות בהדלקת המכשיר</string>
+ <string name="app_ops_delete_call_log">מחיקת יומן השיחות שלך</string>
+ <string name="app_ops_delete_contacts">מחיקת אנשי הקשר שלך</string>
+ <string name="app_ops_delete_mms">מחיקת הודעות ה-MMS שלך</string>
+ <string name="app_ops_delete_sms">מחיקת הודעות ה-SMS שלך</string>
+ <string name="app_ops_draw_on_top">הצגת תוכן מעל יישומים אחרים</string>
+ <string name="app_ops_get_usage_stats">קבלת סטטיסטיקות שימוש ביישום</string>
+ <string name="app_ops_keep_device_awake">השארת המכשיר ער</string>
+ <string name="app_ops_make_phone_call">ביצוע שיחת טלפון</string>
+ <string name="app_ops_modify_calendar">עדכון לוח השנה שלך</string>
+ <string name="app_ops_modify_call_log">עדכון יומן השיחות</string>
+ <string name="app_ops_modify_clipboard">שינוי לוח ההעתקה</string>
+ <string name="app_ops_modify_contacts">עדכון אנשי הקשר שלך</string>
+ <string name="app_ops_modify_settings">עדכון הגדרות המערכת</string>
+ <string name="app_ops_mute_unmute_microphone">השתקת/הפעלת המיקרופון</string>
+ <string name="app_ops_play_audio">ניגון שמע</string>
+ <string name="app_ops_post_notification">פרסום התראה</string>
+ <string name="app_ops_project_media">הקרנת מדיה</string>
+ <string name="app_ops_read_calendar">קריאת לוח השנה שלך</string>
+ <string name="app_ops_read_call_log">קריאת יומן השיחות</string>
+ <string name="app_ops_read_clipboard">קריאת לוח ההעתקה</string>
+ <string name="app_ops_read_contacts">קריאת אנשי הקשר שלך</string>
+ <string name="app_ops_read_mms">קריאת הודעות ה-MMS שלך</string>
+ <string name="app_ops_read_sms">קריאת הודעות ה-SMS שלך</string>
+ <string name="app_ops_receive_sms">קבלת הודעת SMS</string>
+ <string name="app_ops_record_audio">הקלטת שמע</string>
+ <string name="app_ops_send_mms">שליחת הודעת MMS</string>
+ <string name="app_ops_send_sms">שליחת הודעת SMS</string>
+ <string name="app_ops_start_at_bootup">התחלת פעילות בהדלקת המכשיר</string>
+ <string name="app_ops_toast_window">הצגת הודעות קופצות</string>
+ <string name="app_ops_toggle_bluetooth">שינוי מצב ה-Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">הפעלת/כיבוי נתונים סלולריים</string>
+ <string name="app_ops_toggle_nfc">שינוי מצב ה-NFC</string>
+ <string name="app_ops_toggle_wifi">הפעלת/כיבוי Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">שליטה בעוצמת השעון המעורר</string>
+ <string name="app_ops_use_audio_focus">שליטה במיקוד הקול</string>
+ <string name="app_ops_use_bluetooth_volume">שליטה על עוצמת השמע ב-Bluetooth</string>
+ <string name="app_ops_use_master_volume">שליטה על עוצמת השמע הראשית</string>
+ <string name="app_ops_use_media_buttons">שימוש בכפתורי המדיה</string>
+ <string name="app_ops_use_media_volume">שליטה על עוצמת השמעת מדיה</string>
+ <string name="app_ops_use_notification_volume">שליטה על עוצמת צליל ההתראות</string>
+ <string name="app_ops_use_ring_volume">שליטה על עוצמת הצלצול</string>
+ <string name="app_ops_use_vibrate">שימוש ברטט</string>
+ <string name="app_ops_use_voice_volume">שליטה על עוצמת הקול בשיחה</string>
+ <string name="app_ops_write_mms">כתיבת הודעת MMS</string>
+ <string name="app_ops_write_sms">כתיבת הודעת SMS</string>
+ <string name="app_ops_use_fingerprint">שימוש בטביעת אצבע</string>
+ <string name="app_ops_add_voicemail">הוספת תא קולי</string>
+ <string name="app_ops_read_phone_state">גישה למצב המכשיר</string>
+ <string name="app_ops_scan_wifi">סריקת רשתות Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">החלפת טפט</string>
+ <string name="app_ops_assist_structure">שימוש במבנה סיוע</string>
+ <string name="app_ops_assist_screenshot">צילום המסך</string>
+ <string name="app_ops_use_body_sensors">שימוש בחיישני גוף</string>
+ <string name="app_ops_read_cell_broadcasts">קריאת שידורי סלולר</string>
+ <string name="app_ops_mock_location">הסוואת מיקום</string>
+ <string name="app_ops_read_external_storage">קריאת אחסון חיצוני</string>
+ <string name="app_ops_write_external_storage">כתיבה לאחסון חיצוני</string>
+ <string name="app_ops_turn_on_screen">הפעלת המסך</string>
+ <string name="app_ops_get_accounts">קבלת חשבונות המכשיר</string>
+ <string name="app_ops_wifi_change">שינוי מצב Wi-Fi</string>
+ <string name="app_ops_su">קבלת גישת שורש (Root)</string>
+ <string name="lock_to_app_toast_no_navbar">כדי לבטל נעיצת מסך זה, לחץ על כפתור \"חזור\" והחזק אותו.</string>
+ <string name="live_display_auto">אוטומטי</string>
+ <string name="live_display_auto_summary">התאם אוטומטית את טמפרטורת הצבע של המסך לאחר הזריחה והשקיעה</string>
+ <string name="live_display_off">כבוי</string>
+ <string name="live_display_off_summary">בטל את כל ההתאמות</string>
+ <string name="live_display_day">יום</string>
+ <string name="live_display_day_summary">השתמש בהגדרות יום בלבד</string>
+ <string name="live_display_night">לילה</string>
+ <string name="live_display_night_summary">השתמש בהגדרות לילה בלבד</string>
+ <string name="live_display_outdoor">בחוץ (שמש בהירה)</string>
+ <string name="live_display_outdoor_summary">השתמש בהגדרות חוץ בלבד</string>
+ <string name="live_display_hint">LiveDisplay יכולה למזער את עייפות העין ולעזור לך לישון בלילה. לחץ כאן כדי לנסות!</string>
+ <string name="tethered_notification_no_device_message">אין מכשירים מחוברים</string>
+ <string name="tethered_notification_one_device_message">מכשיר <xliff:g id="count">%1$s</xliff:g> מחובר</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> מכשירים מחוברים</string>
+ <string name="notify_package_component_protected_title">הפעלת הפעולה נחסמה</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> מוגן מפני הפעלה. לחץ כדי להזדהות ולהפעיל את היישום.</string>
+ <string name="notify_battery_fully_charged_title">סוללה טעונה במלואה</string>
+ <string name="notify_battery_fully_charged_text">נתק את מכשירך מהמטען כדי לשפר את אורך חיי סוללה.</string>
+</resources>
diff --git a/core/res/res/values-ja/cm_strings.xml b/core/res/res/values-ja/cm_strings.xml
new file mode 100644
index 0000000..bc6636a
--- /dev/null
+++ b/core/res/res/values-ja/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">スクリーンショット</string>
+ <string name="permlab_receiveProtectedSms">保護されたSMSの受信</string>
+ <string name="permdesc_receiveProtectedSms">保護されたSMSの受信をアプリに許可します。</string>
+ <string name="permlab_modifyProtectedSmsList">保護されたSMSリストの変更</string>
+ <string name="permdesc_modifyProtectedSmsList">保護されたSMSアドレスリストの変更をアプリに許可します。</string>
+ <string name="permgrouplab_security">セキュリティ</string>
+ <string name="permgroupdesc_security">端末のセキュリティ情報に関連する権限です。</string>
+ <string name="permlab_readPhoneBlacklist">携帯電話の着信拒否リストの読み取り</string>
+ <string name="permdesc_readPhoneBlacklist">着信やメッセージを拒否している電話番号に関する情報の読み取りをアプリに許可します。</string>
+ <string name="permlab_changePhoneBlacklist">携帯電話の着信拒否リストの変更</string>
+ <string name="permdesc_changePhoneBlacklist">着信やメッセージを拒否している電話番号の変更をアプリに許可します。</string>
+ <string name="permlab_setKeyguardWallpaper">キーガードの壁紙の設定</string>
+ <string name="permdesc_setKeyguardWallpaper">ロック画面の壁紙の変更をアプリに許可します。</string>
+ <string name="global_action_reboot">再起動</string>
+ <string name="global_action_current_user">現在</string>
+ <string name="reboot_reboot">再起動</string>
+ <string name="reboot_recovery">リカバリー</string>
+ <string name="reboot_bootloader">ブートローダ</string>
+ <string name="reboot_download">ダウンロード</string>
+ <string name="reboot_soft">ソフトリブート</string>
+ <string name="reboot_title">再起動</string>
+ <string name="reboot_confirm" product="tablet">タブレットは再起動します。</string>
+ <string name="reboot_confirm" product="default">携帯電話は再起動します。</string>
+ <string name="reboot_progress">再起動中\u2026</string>
+ <string name="app_killed_message">アプリを終了しました。</string>
+ <string name="adb_net_active_notification_title">ネットワーク経由のADBが有効です</string>
+ <string name="adb_both_active_notification_title">USBとネットワーク経由のADBが有効です</string>
+ <string name="adb_active_generic_notification_message">タップしてデバッグを無効にします。</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USBとネットワーク</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">ネットワーク</string>
+ <string name="permlab_interceptPackageLaunch">アプリの起動の監視</string>
+ <string name="stylus_app_not_installed">%sはインストールされていません</string>
+ <string name="silent_mode_priority">優先順位</string>
+ <string name="silent_mode_none">なし</string>
+ <string name="subscription_change_disabled_wifi_ap">SIMサブスクリプションの変更によってWi-Fiアクセスポイントが無効になりました</string>
+ <string name="notify_turn_wifi_off_title">Wi-FiをOFFにする</string>
+ <string name="permlab_changePrivacyGuardState">プライバシーガードを有効/無効にする</string>
+ <string name="permdesc_changePrivacyGuardState">他のアプリでプライバシーガードを有効にするかどうかの変更をアプリに許可します。プライバシーガードを有効にしてアプリを実行すると、そのアプリは連絡先、通話履歴、メッセージなどの個人データにアクセスできなくなります。</string>
+ <string name="privacy_guard_notification">プライバシーガードが有効です</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g>は個人データにアクセスできません</string>
+ <string name="privacy_guard_dialog_title">プライバシーガード</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g>が<xliff:g id="op">%2$s</xliff:g>をしようとしています。</string>
+ <string name="permission_remember_choice">選択を記憶</string>
+ <string name="app_ops_access_camera">カメラへのアクセス</string>
+ <string name="app_ops_access_location">位置情報へのアクセス</string>
+ <string name="app_ops_access_notifications">通知の読み取り</string>
+ <string name="app_ops_activate_vpn">VPNの有効化</string>
+ <string name="app_ops_auto_start">電源投入時の実行</string>
+ <string name="app_ops_delete_call_log">通話履歴の削除</string>
+ <string name="app_ops_delete_contacts">連絡先の削除</string>
+ <string name="app_ops_delete_mms">MMSメッセージの削除</string>
+ <string name="app_ops_delete_sms">SMSメッセージの削除</string>
+ <string name="app_ops_draw_on_top">上部への描画</string>
+ <string name="app_ops_get_usage_stats">アプリの使用統計の取得</string>
+ <string name="app_ops_keep_device_awake">端末のスリープの無効化</string>
+ <string name="app_ops_make_phone_call">通話の発信</string>
+ <string name="app_ops_modify_calendar">カレンダーの更新</string>
+ <string name="app_ops_modify_call_log">通話履歴の更新</string>
+ <string name="app_ops_modify_clipboard">クリップボードの変更</string>
+ <string name="app_ops_modify_contacts">連絡先の更新</string>
+ <string name="app_ops_modify_settings">システムの設定の更新</string>
+ <string name="app_ops_mute_unmute_microphone">マイクのミュート/ミュート解除</string>
+ <string name="app_ops_play_audio">音声の再生</string>
+ <string name="app_ops_post_notification">通知の配信</string>
+ <string name="app_ops_project_media">メディアの投影</string>
+ <string name="app_ops_read_calendar">カレンダーの読み取り</string>
+ <string name="app_ops_read_call_log">通話履歴の読み取り</string>
+ <string name="app_ops_read_clipboard">クリップボードの読み取り</string>
+ <string name="app_ops_read_contacts">連絡先の読み取り</string>
+ <string name="app_ops_read_mms">MMSメッセージの読み取り</string>
+ <string name="app_ops_read_sms">SMSメッセージの読み取り</string>
+ <string name="app_ops_receive_sms">SMSメッセージの受信</string>
+ <string name="app_ops_record_audio">音声の録音</string>
+ <string name="app_ops_send_mms">MMSメッセージの送信</string>
+ <string name="app_ops_send_sms">SMSメッセージの送信</string>
+ <string name="app_ops_start_at_bootup">起動時の実行</string>
+ <string name="app_ops_toast_window">トーストメッセージの表示</string>
+ <string name="app_ops_toggle_bluetooth">Bluetoothの切り替え</string>
+ <string name="app_ops_toggle_mobile_data">データ通信の切り替え</string>
+ <string name="app_ops_toggle_nfc">NFCの切り替え</string>
+ <string name="app_ops_toggle_wifi">Wi-Fiの切り替え</string>
+ <string name="app_ops_use_alarm_volume">アラームの音量の制御</string>
+ <string name="app_ops_use_audio_focus">音声フォーカスの制御</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetoothの音量の制御</string>
+ <string name="app_ops_use_master_volume">主音量の制御</string>
+ <string name="app_ops_use_media_buttons">メディアボタンの使用</string>
+ <string name="app_ops_use_media_volume">メディアの音量の制御</string>
+ <string name="app_ops_use_notification_volume">通知音量の制御</string>
+ <string name="app_ops_use_ring_volume">着信音の音量の制御</string>
+ <string name="app_ops_use_vibrate">触覚フィードバックの使用</string>
+ <string name="app_ops_use_voice_volume">音声の音量の制御</string>
+ <string name="app_ops_write_mms">MMSメッセージの書き込み</string>
+ <string name="app_ops_write_sms">SMSメッセージの書き込み</string>
+ <string name="app_ops_use_fingerprint">指紋の使用</string>
+ <string name="app_ops_add_voicemail">ボイスメールの追加</string>
+ <string name="app_ops_read_phone_state">携帯電話の状態へのアクセス</string>
+ <string name="app_ops_scan_wifi">Wi-Fiネットワークのスキャン</string>
+ <string name="app_ops_change_wallpaper">壁紙の変更</string>
+ <string name="app_ops_assist_structure">ストラクチャのアシストの使用</string>
+ <string name="app_ops_assist_screenshot">スクリーンショットの撮影</string>
+ <string name="app_ops_use_body_sensors">ボディセンサーの使用</string>
+ <string name="app_ops_read_cell_broadcasts">セルブロードキャストの読み取り</string>
+ <string name="app_ops_mock_location">位置情報の仮想</string>
+ <string name="app_ops_read_external_storage">外部ストレージの読み取り</string>
+ <string name="app_ops_write_external_storage">外部ストレージの書き込み</string>
+ <string name="app_ops_turn_on_screen">画面の点灯</string>
+ <string name="app_ops_get_accounts">端末のアカウントの取得</string>
+ <string name="app_ops_wifi_change">Wi-Fiの状態の変更</string>
+ <string name="app_ops_su">ルートアクセスの取得</string>
+ <string name="lock_to_app_toast_no_navbar">この画面の固定を解除するには、戻るボタンを長押しします。</string>
+ <string name="live_display_auto">自動</string>
+ <string name="live_display_auto_summary">太陽の動きに合わせて画面の色温度を自動的に調整する</string>
+ <string name="live_display_off">OFF</string>
+ <string name="live_display_off_summary">すべての調整を無効にする</string>
+ <string name="live_display_day">昼</string>
+ <string name="live_display_day_summary">昼の設定のみを使用する</string>
+ <string name="live_display_night">夜</string>
+ <string name="live_display_night_summary">夜の設定のみを使用する</string>
+ <string name="live_display_outdoor">屋外(日光)</string>
+ <string name="live_display_outdoor_summary">屋外の設定のみを使用する</string>
+ <string name="live_display_hint">LiveDisplayは目を疲れにくくし、夜の睡眠を邪魔しません。ここをタップして試してみてください。</string>
+ <string name="tethered_notification_no_device_message">接続しているデバイスはありません</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g>台のデバイスが接続しています</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g>台のデバイスが接続しています</string>
+ <string name="notify_package_component_protected_title">アクティビティの起動がブロックされました</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g>は起動できないように保護されています。タップして認証後にアプリケーションを起動してください。</string>
+ <string name="notify_battery_fully_charged_title">電池の充電が完了しました</string>
+ <string name="notify_battery_fully_charged_text">電池寿命を延ばすために端末を充電器から取り外してください。</string>
+</resources>
diff --git a/core/res/res/values-kn-rIN/cm_strings.xml b/core/res/res/values-kn-rIN/cm_strings.xml
new file mode 100644
index 0000000..fcb9e94
--- /dev/null
+++ b/core/res/res/values-kn-rIN/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">ಸ್ಕ್ರೀನ್‍ಶಾಟ್</string>
+ <string name="permlab_receiveProtectedSms">ಸಂರಕ್ಷಿತ ಎಸ್ಎಂಎಸ್ ಸ್ವೀಕರಿಸಿ</string>
+ <string name="permdesc_receiveProtectedSms">ಆಪ್‍ಗೆ ಒಳಬರುವ ಸಂರಕ್ಷಿತ ಎಸ್ಎಂಎಸ್ ಸ್ವೀಕರಿಸಲು ಅನುಮತಿಸುತ್ತದೆ.</string>
+ <string name="permlab_modifyProtectedSmsList">ಸಂರಕ್ಷಿತ ಎಸ್ಎಂಎಸ್ ಪಟ್ಟಿ ಮಾರ್ಪಡನೆ</string>
+ <string name="permdesc_modifyProtectedSmsList">ಆಪ್‍ಗೆ ಸಂರಕ್ಷಿತ ಎಸ್‍ಎಂಎಸ್ ವಿಳಾಸ ಪಟ್ಟಿಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಅನುಮತಿಸುತ್ತದೆ.</string>
+ <string name="permgrouplab_security">ಭದ್ರತೆ</string>
+ <string name="permgroupdesc_security">ಸಾಧನ ಭದ್ರತೆ ಮಾಹಿತಿಗೆ ಸಂಬಂಧಿಸಿದ ಅನುಮತಿಗಳು.</string>
+ <string name="permlab_readPhoneBlacklist">ಫೋನ್ ಬ್ಲಾಕ್‍ಪಟ್ಟಿಯನ್ನು ಓದು</string>
+ <string name="permdesc_readPhoneBlacklist">ಆಪ್‍ಗೆ ಒಳಬರುವ ಕರೆಗಳನ್ನು ಅಥವಾ ಸಂದೇಶಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾದ ದೂರವಾಣಿ ಸಂಖ್ಯೆಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಓದಲು ಅನುಮತಿಸುತ್ತದೆ.</string>
+ <string name="permlab_changePhoneBlacklist">ಫೋನ್ ಬ್ಲಾಕ್‍ಪಟ್ಟಿ ಬದಲಾವಣೆ</string>
+ <string name="permdesc_changePhoneBlacklist">ಆಪ್‍ಗೆ ಒಳಬರುವ ಕರೆ ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾದ ಸಂಖ್ಯೆಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ.</string>
+ <string name="permlab_setKeyguardWallpaper">ಕೀಗಾರ್ಡ್ ವಾಲ್‍ಪೇಪರ್ ಹೊಂದಿಕೆ</string>
+ <string name="permdesc_setKeyguardWallpaper">ಒಂದು ಆಪ್‍ಗೆ ಲಾಕ್ ಪರದೆಯ ವಾಲ್‍ಪೇಪರ್ ಬದಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ.</string>
+ <string name="global_action_reboot">ರಿಬೂಟ್</string>
+ <string name="global_action_current_user">ಪ್ರಸ್ತುತ</string>
+ <string name="reboot_reboot">ರಿಬೂಟ್</string>
+ <string name="reboot_recovery">ರಿಕವರಿ</string>
+ <string name="reboot_bootloader">ಬೂಟ್‍ಲೋಡರ್</string>
+ <string name="reboot_download">ಡೌನ್‍ಲೋಡ್</string>
+ <string name="reboot_soft">ಸಾಫ್ಟ್ ರಿಬೂಟ್</string>
+ <string name="reboot_title">ರಿಬೂಟ್</string>
+ <string name="reboot_confirm" product="tablet">ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ರಿಬೂಟ್ ಆಗುವುದು.</string>
+ <string name="reboot_confirm" product="default">ನಿಮ್ಮ ಫೋನ್ ರಿಬೂಟ್ ಆಗುವುದು.</string>
+ <string name="reboot_progress">ರಿಬೂಟ್ ಆಗುತ್ತಿದೆ\u2026</string>
+ <string name="app_killed_message">ಆಪ್ ಕೊಲ್ಲಲಾಗಿದೆ</string>
+ <string name="adb_net_active_notification_title">ನೆಟ್‍ವರ್ಕ್‍ನಿಂದ ಎಡಿಬಿ ಸಕ್ರಿಯಗೊಂಡಿದೆ</string>
+ <string name="adb_both_active_notification_title">ಯುಎಸ್‍ಬಿಯಿಂದ ಎಡಿಬಿ &amp; ನೆಟ್‍ವರ್ಕ್ ಸಕ್ರಿಯಗೊಂಡಿದೆ</string>
+ <string name="adb_active_generic_notification_message">ಡೀಬಗ್ಗಿಂಗ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ.</string>
+ <string name="adb_active_custom_tile">ಎಡಿಬಿ - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">ಯುಎಸ್‍ಬಿ &amp; ನೆಟ್‍ವರ್ಕ್</string>
+ <string name="adb_active_custom_tile_usb">ಯುಎಸ್‍ಬಿ</string>
+ <string name="adb_active_custom_tile_net">ನೆಟ್‍ವರ್ಕ್</string>
+ <string name="permlab_interceptPackageLaunch">ಆಪ್ ಆರಂಭ ಪ್ರತಿಬಂಧ</string>
+ <string name="stylus_app_not_installed">%s ಸ್ಥಾಪಿತವಾಗಿಲ್ಲ</string>
+ <string name="silent_mode_priority">ಆದ್ಯತೆ</string>
+ <string name="silent_mode_none">ಶೂನ್ಯ</string>
+ <string name="subscription_change_disabled_wifi_ap">ಸಿಮ್ ಚಂದಾದಾರಿಕೆ ಬದಲಾದ ಕಾರಣ ವೈ-ಫೈ ಹಾಟ್‍ಸ್ಪಾಟನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ</string>
+ <string name="notify_turn_wifi_off_title">ವೈ-ಫೈ ಆಫ್ ಮಾಡಿ</string>
+ <string name="permlab_changePrivacyGuardState">ಗೌಪ್ಯತಾ ರಕ್ಷಕವನ್ನು ಸಕ್ರಿಯ ಅಥವ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುವಿಕೆ</string>
+ <string name="permdesc_changePrivacyGuardState">ಆಪ್‍ಗೆ ಇತರೆ ಆಪ್ ಗೌಪ್ಯತಾ ರಕ್ಷಕದ ಜೊತೆ ಚಲಿಸಲು ಅಗುತ್ತದೆಯೆ ಅಥವ ಇಲ್ಲವೇ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. ಒಂದು ಆಪ್ Privacy Guard ಜೊತೆ ಚಲಿಸುತ್ತಿದ್ದಲ್ಲಿ, ಅದಕ್ಕೆ ವಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವಿದಿಲ್ಲ, ಉದಾಹರಣೆಗೆ ಸಂಪರ್ಕಗಳು, ಕರೆ ಲಾಗ್ಸ್, ಅಥವ ಸಂದೇಶಗಳು.</string>
+ <string name="privacy_guard_notification">ಗೌಪ್ಯತಾ ರಕ್ಷಕ ಸಕ್ರಿಯ</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g>ಗೆ ಖಾಸಗಿ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ</string>
+ <string name="privacy_guard_dialog_title">ಗೌಪ್ಯತಾ ರಕ್ಷಕ</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> ನೀವು ಹೀಗೆ <xliff:g id="op">%2$s</xliff:g> ಬಯಸುವಿರಾ.</string>
+ <string name="permission_remember_choice">ನನ್ನ ಆಯ್ಕೆಯನ್ನು ನೆನಪಿಡು</string>
+ <string name="app_ops_access_camera">ಕ್ಯಾಮೆರಾ ಪ್ರವೇಶ</string>
+ <string name="app_ops_access_location">ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸುವಿಕೆ</string>
+ <string name="app_ops_access_notifications">ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದು</string>
+ <string name="app_ops_activate_vpn">ವಿಪಿಎನ್ ಸಶಕ್ತಗೊಳಿಸು</string>
+ <string name="app_ops_auto_start">ಪವರ್ ಅಪ್ ವೇಳೆ ಆರಂಭವಾಗು</string>
+ <string name="app_ops_delete_call_log">ನಿಮ್ಮ ಕರೆ ಲಾಗ್‍ನ್ನು ಅಳಿಸು</string>
+ <string name="app_ops_delete_contacts">ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಅಳಿಸು</string>
+ <string name="app_ops_delete_mms">ಎಂಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸು</string>
+ <string name="app_ops_delete_sms">ನಿಮ್ಮ ಎಸ್ಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸು</string>
+ <string name="app_ops_draw_on_top">ಟಾಪ್‍ನಲ್ಲಿ ಕಿಟಕಿಗಳನ್ನು ಬಿಡಿಸು</string>
+ <string name="app_ops_get_usage_stats">ಆಪ್ ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳನ್ನು ಪಡೆ</string>
+ <string name="app_ops_keep_device_awake">ನಿಮ್ಮ ಸಾಧನವನ್ನು ಎಚ್ಚರವಾಗಿಡುವಿಕೆ</string>
+ <string name="app_ops_make_phone_call">ದೂರವಾಣಿ ಕರೆಯನ್ನು ಮಾಡು</string>
+ <string name="app_ops_modify_calendar">ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್‍ನ್ನು ನವೀಕರಿಸು</string>
+ <string name="app_ops_modify_call_log">ಕರೆ ಲಾಗ್ ನವೀಕರಿಸು</string>
+ <string name="app_ops_modify_clipboard">ನಕಲುಫಲಕವನ್ನು ಮಾರ್ಪಡಿಸು</string>
+ <string name="app_ops_modify_contacts">ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ನವೀಕರಿಸು</string>
+ <string name="app_ops_modify_settings">ಸಿಸ್ಟಂ ಸೆಟ್ಟಿಂಗ್ಸ್ ನವೀಕರಿಸು</string>
+ <string name="app_ops_mute_unmute_microphone">ಧ್ವನಿಗ್ರಾಹಕವನ್ನು ಮೌನ/ಅಮೌನಿಸು</string>
+ <string name="app_ops_play_audio">ಆಡಿಯೋ ಪ್ಲೇಮಾಡು</string>
+ <string name="app_ops_post_notification">ಅಧಿಸೂಚನೆಯನ್ನು ಪೋಸ್ಟ್ ಮಾಡು</string>
+ <string name="app_ops_project_media">ಮಾಧ್ಯಮ ಪ್ರೊಜೆಕ್ಟ್ ಮಾಡು</string>
+ <string name="app_ops_read_calendar">ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರನ್ನು ಓದು</string>
+ <string name="app_ops_read_call_log">ಕರೆ ಲಾಗನ್ನು ಓದು</string>
+ <string name="app_ops_read_clipboard">ನಕಲುಫಲಕವನ್ನು ಓದು</string>
+ <string name="app_ops_read_contacts">ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಓದು</string>
+ <string name="app_ops_read_mms">ನಿಮ್ಮ ಎಂಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಓದು</string>
+ <string name="app_ops_read_sms">ನಿಮ್ಮ ಎಸ್ಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಓದು</string>
+ <string name="app_ops_receive_sms">ಎಸ್ಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸು</string>
+ <string name="app_ops_record_audio">ಆಡಿಯೋ ರಿಕಾರ್ಡ್ ಮಾಡು</string>
+ <string name="app_ops_send_mms">ಎಂಎಂಎಸ್ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸು</string>
+ <string name="app_ops_send_sms">ಎಸ್ಎಂಎಸ್ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸು</string>
+ <string name="app_ops_start_at_bootup">ಪವರ್ ಅಪ್ ವೇಳೆ ಆರಂಭವಾಗು</string>
+ <string name="app_ops_toast_window">ಟೋಸ್ಟ್ ಸಂದೇಶಗಳನ್ನು ಪ್ರದರ್ಶಿಸು</string>
+ <string name="app_ops_toggle_bluetooth">ಟಾಗಲ್ ಬ್ಲೂಟೂತ್</string>
+ <string name="app_ops_toggle_nfc">ಟಾಗಲ್ NFC</string>
+ <string name="app_ops_use_alarm_volume">ಅಲಾರಂ ವಾಲ್ಯೂಂ ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_audio_focus">ಆಡಿಯೋ ಫೋಕಸ್ ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_bluetooth_volume">ಬ್ಲೂಟೂತ್ ವಾಲ್ಯೂಂ ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_master_volume">ಮಾಸ್ಟರ್ ವಾಲ್ಯೂಂ ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_media_buttons">ಮಾಧ್ಯಮ ಬಟನ್‍ಗಳನ್ನು ಉಪಯೋಗಿಸು</string>
+ <string name="app_ops_use_media_volume">ಮಾಧ್ಯಮ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_notification_volume">ಅಧಿಸೂಚನೆ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_ring_volume">ರಿಂಗ್‍ಟೋನ್ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_use_vibrate">ಸ್ಪಾರ್ಶ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಉಪಯೋಗಿಸು</string>
+ <string name="app_ops_use_voice_volume">ಧ್ವನಿ ಕರೆ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು</string>
+ <string name="app_ops_write_mms">ಎಂಎಂಎಸ್ ಸಂದೇಶ ಬರೆ</string>
+ <string name="app_ops_write_sms">ಎಸ್ಎಂಎಸ್ ಸಂದೇಶ ಬರೆ</string>
+ <string name="app_ops_su">ರೂಟ್ ಪ್ರವೇಶ ಪಡೆ</string>
+ <string name="lock_to_app_toast_no_navbar">ಪರದೆಯನ್ನು ಅನ್‍ಪಿನ್‍ಮಾಡಲು, ಹಿಂದೆ ಬಟನ್‍ ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿಯಿರಿ.</string>
+ <string name="live_display_auto">ಸ್ವಯಂಚಾಲಿತ</string>
+ <string name="live_display_auto_summary">ಸೂರ್ಯಾಸ್ತ ಅಥವ ಸೂರ್ಯೋದಯದ ನಂತರ ಪರದೆಯ ಬಣ್ಣ ಉಷ್ಣಾಂಶವನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸರಿಹೊಂದಿಸು</string>
+ <string name="live_display_off">ಆಫ್</string>
+ <string name="live_display_off_summary">ಎಲ್ಲಾ ಹೊಂದಾಣಿಕೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು</string>
+ <string name="live_display_day">ದಿನ</string>
+ <string name="live_display_day_summary">ದಿನ ಸೆಟ್ಟಿಂಗ್ಸನ್ನು ಮಾತ್ರ ಉಪಯೋಗಿಸು</string>
+ <string name="live_display_night">ರಾತ್ರಿ</string>
+ <string name="live_display_night_summary">ರಾತ್ರಿ ಸೆಟ್ಟಿಂಗ್ಸನ್ನು ಮಾತ್ರ ಉಪಯೋಗಿಸು</string>
+ <string name="live_display_outdoor">ಹೊರಾಂಗಣ (ಪ್ರಕಾಶಮಾನ ಸೂರ್ಯ)</string>
+ <string name="live_display_outdoor_summary">ಹೊರಾಂಗಣ ಸೆಟ್ಟಿಂಗ್ಸನ್ನು ಮಾತ್ರ ಉಪಯೋಗಿಸು</string>
+ <string name="live_display_hint">ಲೈವ್ ಡಿಸ್ಪ್ಲೆ ನಿಮ್ಮ ಕಣ್ಣಿನ ಆಯಾಸವನ್ನು ಕಡಿಮೆಮಾಡಿ ರಾತ್ರಿ ಮಲಗಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಇದನ್ನು ಪ್ರಯತ್ನಿಸಲು ಇಲ್ಲಿ ಒತ್ತಿ!</string>
+ <string name="tethered_notification_no_device_message">ಯಾವುದೇ ಸಂಪರ್ಕಗೊಂಡ ಸಾಧನವಿಲ್ಲ</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> ಸಂಪರ್ಕಗೊಳಿಸಿದ ಸಾಧನ</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> ಸಂಪರ್ಕಗೊಳಿಸಿದ ಸಾಧನಗಳು</string>
+</resources>
diff --git a/core/res/res/values-ko/cm_strings.xml b/core/res/res/values-ko/cm_strings.xml
new file mode 100644
index 0000000..f0b963e
--- /dev/null
+++ b/core/res/res/values-ko/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">스크린샷</string>
+ <string name="permlab_receiveProtectedSms">보안 SMS 수신</string>
+ <string name="permdesc_receiveProtectedSms">앱이 들어오는 보안 SMS를 수신할 수 있도록 허용합니다.</string>
+ <string name="permlab_modifyProtectedSmsList">보안 SMS 목록 수정</string>
+ <string name="permdesc_modifyProtectedSmsList">앱이 보안 SMS 주소 목록을 수정할 수 있도록 허용합니다.</string>
+ <string name="permgrouplab_security">보안</string>
+ <string name="permgroupdesc_security">장치의 보안 정보에 관련된 권한입니다.</string>
+ <string name="permlab_readPhoneBlacklist">전화 블랙리스트 읽기</string>
+ <string name="permdesc_readPhoneBlacklist">앱이 전화 또는 메시지 수신이 차단된 전화번호들의 정보를 읽을 수 있도록 허용합니다.</string>
+ <string name="permlab_changePhoneBlacklist">전화 블랙리스트 수정</string>
+ <string name="permdesc_changePhoneBlacklist">앱이 어떤 전화번호들의 전화 또는 메시지를 차단할 것인지를 변경할 수 있도록 허용합니다.</string>
+ <string name="permlab_setKeyguardWallpaper">잠금화면 배경 설정</string>
+ <string name="permdesc_setKeyguardWallpaper">앱이 잠금화면 배경을 바꿀 수 있도록 허용합니다.</string>
+ <string name="global_action_reboot">다시 시작</string>
+ <string name="global_action_current_user">현재</string>
+ <string name="reboot_reboot">다시 시작</string>
+ <string name="reboot_recovery">복구 모드</string>
+ <string name="reboot_bootloader">부트로더</string>
+ <string name="reboot_download">다운로드</string>
+ <string name="reboot_soft">빠른 다시 시작</string>
+ <string name="reboot_title">다시 시작</string>
+ <string name="reboot_confirm" product="tablet">태블릿이 다시 시작됩니다.</string>
+ <string name="reboot_confirm" product="default">휴대전화가 다시 시작됩니다.</string>
+ <string name="reboot_progress">다시 시작하는 중\u2026</string>
+ <string name="app_killed_message">앱이 종료되었습니다</string>
+ <string name="adb_net_active_notification_title">네트워크 ADB 활성화됨</string>
+ <string name="adb_both_active_notification_title">USB 및 네트워크 ADB 활성화됨</string>
+ <string name="adb_active_generic_notification_message">디버깅을 사용하지 않으려면 터치하세요.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="Usb">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB 및 네트워크</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">네트워크</string>
+ <string name="permlab_interceptPackageLaunch">앱 실행 차단</string>
+ <string name="stylus_app_not_installed">%s이(가) 설치되지 않음</string>
+ <string name="silent_mode_priority">우선순위</string>
+ <string name="silent_mode_none">없음</string>
+ <string name="subscription_change_disabled_wifi_ap">SIM 구독 변경으로 인해 Wi-Fi 핫스팟 비활성화함</string>
+ <string name="notify_turn_wifi_off_title">Wi-Fi 끄기</string>
+ <string name="permlab_changePrivacyGuardState">프라이버시 가드 활성화 또는 비활성화</string>
+ <string name="permdesc_changePrivacyGuardState">다른 앱이 프라이버시 가드와 함께 실행될 것인지 변경할 수 있도록 앱을 허용합니다. 앱이 프라이버시 가드와 함께 실행중일 땐 연락처, 통화 기록, 메시지 등의 개인 정보에 접근할 수 없게 됩니다.</string>
+ <string name="privacy_guard_notification">프라이버시 가드 활성화</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g>은(는) 개인 데이터에 접근할 수 없습니다.</string>
+ <string name="privacy_guard_dialog_title">프라이버시 가드</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g>이(가) <xliff:g id="op">%2$s</xliff:g>을(를) 원합니다.</string>
+ <string name="permission_remember_choice">선택 사항 기억하기</string>
+ <string name="app_ops_access_camera">카메라에 액세스</string>
+ <string name="app_ops_access_location">위치 정보에 액세스</string>
+ <string name="app_ops_access_notifications">알림 읽기</string>
+ <string name="app_ops_activate_vpn">VPN 활성화</string>
+ <string name="app_ops_auto_start">전원을 켤 때 실행</string>
+ <string name="app_ops_delete_call_log">통화 기록 삭제</string>
+ <string name="app_ops_delete_contacts">연락처 삭제</string>
+ <string name="app_ops_delete_mms">MMS 메시지 삭제</string>
+ <string name="app_ops_delete_sms">SMS 메시지 삭제</string>
+ <string name="app_ops_draw_on_top">창을 맨 위에 그리기</string>
+ <string name="app_ops_get_usage_stats">앱 사용 통계 확인</string>
+ <string name="app_ops_keep_device_awake">기기 켜짐 상태 유지</string>
+ <string name="app_ops_make_phone_call">전화 걸기</string>
+ <string name="app_ops_modify_calendar">캘린더 수정</string>
+ <string name="app_ops_modify_call_log">통화 기록 수정</string>
+ <string name="app_ops_modify_clipboard">클립보드 수정</string>
+ <string name="app_ops_modify_contacts">주소록 업데이트</string>
+ <string name="app_ops_modify_settings">시스템 설정 업데이트</string>
+ <string name="app_ops_mute_unmute_microphone">마이크 켜기/끄기</string>
+ <string name="app_ops_play_audio">오디오 재생</string>
+ <string name="app_ops_post_notification">알림 게시</string>
+ <string name="app_ops_project_media">미디어 프로젝션</string>
+ <string name="app_ops_read_calendar">일정 읽기</string>
+ <string name="app_ops_read_call_log">전화 기록 읽기</string>
+ <string name="app_ops_read_clipboard">클립보드 읽기</string>
+ <string name="app_ops_read_contacts">주소록 읽기</string>
+ <string name="app_ops_read_mms">MMS 메시지 읽기</string>
+ <string name="app_ops_read_sms">SMS 메시지 읽기</string>
+ <string name="app_ops_receive_sms">SMS 메시지 받기</string>
+ <string name="app_ops_record_audio">오디오 녹음</string>
+ <string name="app_ops_send_mms">MMS 메시지 보내기</string>
+ <string name="app_ops_send_sms">SMS 메시지 보내기</string>
+ <string name="app_ops_start_at_bootup">전원을 켤 때 실행</string>
+ <string name="app_ops_toast_window">팝업 메시지 표시</string>
+ <string name="app_ops_toggle_bluetooth">블루투스 켜기/끄기</string>
+ <string name="app_ops_toggle_mobile_data">셀룰러 데이터 켜기/끄기</string>
+ <string name="app_ops_toggle_nfc">NFC 켜기/끄기</string>
+ <string name="app_ops_toggle_wifi">Wi-Fi 켜기/끄기</string>
+ <string name="app_ops_use_alarm_volume">알람 볼륨 제어</string>
+ <string name="app_ops_use_audio_focus">오디오 포커스 제어</string>
+ <string name="app_ops_use_bluetooth_volume">블루투스 볼륨 제어</string>
+ <string name="app_ops_use_master_volume">마스터 볼륨 제어</string>
+ <string name="app_ops_use_media_buttons">미디어 버튼 사용</string>
+ <string name="app_ops_use_media_volume">미디어 볼륨 제어</string>
+ <string name="app_ops_use_notification_volume">알림 볼륨 제어</string>
+ <string name="app_ops_use_ring_volume">벨소리 볼륨 제어</string>
+ <string name="app_ops_use_vibrate">터치 진동 사용</string>
+ <string name="app_ops_use_voice_volume">음성 통화 볼륨 제어</string>
+ <string name="app_ops_write_mms">MMS 메시지 작성</string>
+ <string name="app_ops_write_sms">SMS 메시지 작성</string>
+ <string name="app_ops_use_fingerprint">지문인식 사용</string>
+ <string name="app_ops_add_voicemail">음성 메일 추가</string>
+ <string name="app_ops_read_phone_state">전화 상태에 접근</string>
+ <string name="app_ops_scan_wifi">Wi-Fi 네트워크 스캔</string>
+ <string name="app_ops_change_wallpaper">배경 화면을 변경</string>
+ <string name="app_ops_assist_structure">어시스트 구조 사용</string>
+ <string name="app_ops_assist_screenshot">현재 화면을 캡쳐</string>
+ <string name="app_ops_use_body_sensors">신체 센서를 사용함</string>
+ <string name="app_ops_read_cell_broadcasts">셀 브로드캐스트 읽기</string>
+ <string name="app_ops_mock_location">내 위치를 조작</string>
+ <string name="app_ops_read_external_storage">외부 저장소 읽기</string>
+ <string name="app_ops_write_external_storage">외부 저장소에 쓰기</string>
+ <string name="app_ops_turn_on_screen">화면을 켬</string>
+ <string name="app_ops_get_accounts">기기 계정 읽기</string>
+ <string name="app_ops_wifi_change">Wi-Fi 상태 변경</string>
+ <string name="app_ops_su">루트 권한 얻기</string>
+ <string name="lock_to_app_toast_no_navbar">화면 고정을 해제하려면 뒤로 버튼을 계속 누르세요</string>
+ <string name="live_display_auto">자동</string>
+ <string name="live_display_auto_summary">일출 및 일몰 후 화면의 색 온도를 자동으로 조정</string>
+ <string name="live_display_off">끄기</string>
+ <string name="live_display_off_summary">모든 조정 사용 안 함</string>
+ <string name="live_display_day">주간</string>
+ <string name="live_display_day_summary">주간 설정만으로 사용</string>
+ <string name="live_display_night">야간</string>
+ <string name="live_display_night_summary">야간 설정만으로 사용</string>
+ <string name="live_display_outdoor">야외 (밝은 햇빛)</string>
+ <string name="live_display_outdoor_summary">야외 설정만으로 사용</string>
+ <string name="live_display_hint">LiveDisplay는 눈의 피로를 줄이고 밤에 수면을 돕습니다. 적용하려면 클릭하십시오!</string>
+ <string name="tethered_notification_no_device_message">연결된 기기 없음</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g>대의 기기가 연결되어 있습니다</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g>대의 기기가 연결되어 있습니다</string>
+ <string name="notify_package_component_protected_title">액티비티 실행 제한됨</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g>은(는) 실행이 제한되어 있습니다. 탭하여 제한을 해제하고 애플리케이션을 실행하세요.</string>
+ <string name="notify_battery_fully_charged_title">배터리가 완전히 충전됨</string>
+ <string name="notify_battery_fully_charged_text">배터리 수명을 향상시키기 위해 기기를 충전기에서 분리하세요.</string>
+</resources>
diff --git a/core/res/res/values-ku-rIQ/donottranslate-maps.xml b/core/res/res/values-ku-rIQ/donottranslate-maps.xml
new file mode 100644
index 0000000..d9f6872
--- /dev/null
+++ b/core/res/res/values-ku-rIQ/donottranslate-maps.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<resources>
+ <!-- Stub for Kurdish -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>41034435</item>
+ <item>28977556</item>
+ </integer-array>
+ <integer-array name="maps_starting_zoom">
+ <item>3</item>
+ </integer-array>
+</resources>
diff --git a/core/res/res/values-ku/cm_strings.xml b/core/res/res/values-ku/cm_strings.xml
new file mode 100644
index 0000000..f24a4f0
--- /dev/null
+++ b/core/res/res/values-ku/cm_strings.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">وێنەگرتنی ڕوونما</string>
+ <string name="permlab_receiveProtectedSms">وەرگرتنی کورتەنامەی پارێزراو</string>
+ <string name="permdesc_receiveProtectedSms">ڕێگە بە بەرنامەکە بدە کە کورتەنامە پارێزراوەکەی داهاتوو وەربگرێت.</string>
+ <string name="permlab_modifyProtectedSmsList">دەستکاریکردنی لیستی کورتەنامە پارێزراوەکان</string>
+ <string name="permdesc_modifyProtectedSmsList">ڕێگەدان بە بەرنامەکە بۆ دەستکاریکردنی لیستی کورتەنامە پارێزراوەکان.</string>
+ <string name="permgrouplab_security">ئاسایش</string>
+ <string name="permgroupdesc_security">مۆڵەت پێدان پەیوەندی زانیاری ئاسایشی ئامێرەکە.</string>
+ <string name="permlab_readPhoneBlacklist">خوێندنەوەی بلۆکی تەلەفۆن</string>
+ <string name="permdesc_readPhoneBlacklist">ڕێگەدان: بە بەرنامەیەک بۆ خوێندنەوەی زانیاریەکان دەربارەی ژمارەی تەلەفۆنەکە کە بلۆک کراوە بۆ نامەو تەلەفۆنکردنی هاتوو.</string>
+ <string name="permlab_changePhoneBlacklist">گۆڕنی تەلەفۆن لە لیستی ڕەش</string>
+ <string name="permdesc_changePhoneBlacklist">ڕێگەدان بە بەرنامەکە بۆ ئەو ژمارانەی بلۆک کراون بۆ نامەو تەلەفۆن.</string>
+ <string name="permlab_setKeyguardWallpaper">دانانی کلیلە پارێز بۆ دیوارپۆش</string>
+ <string name="permdesc_setKeyguardWallpaper">ڕێگەدان: بە بەرنامەیەک بۆ گۆڕینی قوفڵی ڕوونمای دیوارپۆش.</string>
+ <string name="global_action_reboot">دوبارە خستنەگەڕ</string>
+ <string name="global_action_current_user">ئێستا</string>
+ <string name="reboot_reboot">سه‌رله‌نوێ خستنه‌ڕێ</string>
+ <string name="reboot_recovery">ڕیکەڤەری</string>
+ <string name="reboot_bootloader">بووتلەودەر</string>
+ <string name="reboot_download">داگرتن</string>
+ <string name="reboot_soft">کارپێکردنه‌وه‌ی قوڵ</string>
+ <string name="reboot_title">ئیشپێکردنەوە</string>
+ <string name="reboot_confirm" product="tablet">سه‌رله‌نوێ خستنه‌ڕێ دەبێت.</string>
+ <string name="reboot_confirm" product="default">تەلەفۆنەکە سه‌رله‌نوێ ده‌کوژێته‌وه‌ و داده‌گیرسێته‌وه‌.</string>
+ <string name="reboot_progress">سه‌رله‌نوێ خستنه‌ڕێ\u2026</string>
+ <string name="app_killed_message">بەرنامە داخرا</string>
+ <string name="adb_net_active_notification_title">ABD سه‌روو هێڵ کارده‌کات</string>
+ <string name="adb_both_active_notification_title">ABD سه‌روو USB و هێڵ کارده‌کات</string>
+ <string name="adb_active_generic_notification_message">ئێره‌ لێبده‌ بۆ له‌کارخستنی هه‌ڵدۆزینه‌وه‌.</string>
+ <string name="stylus_app_not_installed">%s دانەمەزراوە</string>
+ <string name="permlab_changePrivacyGuardState">چالاکردن یان لەکارخستنی بەرگری تایبەتی</string>
+ <string name="permdesc_changePrivacyGuardState">ڕێگە دان بە بەرنامەکە بۆ گۆڕینی کەشوهەوای بەرنامەیەکی تر لە تایبەتی. کاتێک بەرنامەکە ئەکەوێتە کار لەگەڵ تایبەتی .هیچ ڕێگەیەکی نیە بۆ ئەوەی زانیاری تایبیەتیت بەکاربهێنێت وەکو ،ناوەکان،تەلەفۆن لۆگ یان نامە.</string>
+ <string name="privacy_guard_notification">پاسەوانی تایبەتی چالاکراوە</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="بەرنامە">%1$s</xliff:g> ناتوانێت زانیاری تایبەتی بەکاربهێنێت</string>
+ <string name="privacy_guard_dialog_title">پاسەوانی تایبەتی</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="بەرنامە">%1$s</xliff:g> حەز ئەکەی بۆ <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">بیرخستنەوەی هەڵبژاردنەکەم</string>
+ <string name="app_ops_access_camera">ڕێگەدان بەکامێرا</string>
+ <string name="app_ops_access_location">ڕێگەی ناوچەی</string>
+ <string name="app_ops_access_notifications">تێبنینیەکانت بخوێنەوە</string>
+ <string name="app_ops_activate_vpn">VPN چالاککردنی</string>
+ <string name="app_ops_auto_start">کردنەوەی لەکاتی هەڵبوونی ئامێردا</string>
+ <string name="app_ops_delete_call_log">سڕینەوەی تۆمارەکانی پەیوەندیت</string>
+ <string name="app_ops_delete_contacts">سڕینەوەی ناوەکانت</string>
+ <string name="app_ops_delete_mms">MMS سڕینەوەی پەیامە ڕەنگاڵەییەکان</string>
+ <string name="app_ops_delete_sms">SMS سڕینەوەی پەیامەکانت</string>
+ <string name="app_ops_draw_on_top">ڕاکێشانی پەنجەرەکە بۆ سەرەوە</string>
+ <string name="app_ops_get_usage_stats">هێنانی بەرنامەی ئاماری بەکارهێنان</string>
+ <string name="app_ops_keep_device_awake">دانانی ئامێرەکە بە کراوەی</string>
+ <string name="app_ops_make_phone_call">تەلەفۆن بکە</string>
+ <string name="app_ops_modify_calendar">نوێکردنه‌وه‌ی ڕۆژمێرەکەت</string>
+ <string name="app_ops_modify_call_log">نوێکردنه‌وه‌ی تۆماری تەلەفۆن</string>
+ <string name="app_ops_modify_clipboard">سڕینەوەی وێنە</string>
+ <string name="app_ops_modify_contacts">نوێکردنه‌وه‌ی ناوەکانت</string>
+ <string name="app_ops_modify_settings">نوێکردنه‌وه‌ی ڕێکخستنی سیستەم</string>
+ <string name="app_ops_mute_unmute_microphone">کپکردن/کپنەکردنی بیستۆک</string>
+ <string name="app_ops_play_audio">لێدانی دەنگ</string>
+ <string name="app_ops_post_notification">ناردنی تێبینی</string>
+ <string name="app_ops_project_media">پرۆژەی ڕەنگاڵە</string>
+ <string name="app_ops_read_calendar">خوێندنەوەی ڕۆژمێر</string>
+ <string name="app_ops_read_call_log">خوێندنەوەی تۆماری تەلەفۆن</string>
+ <string name="app_ops_read_clipboard">خوێندوەی کلیپبۆرد</string>
+ <string name="app_ops_read_contacts">خوێندنەوەی ناوەکانت</string>
+ <string name="app_ops_read_mms">خوێندنوەی نامەی MMSکانت</string>
+ <string name="app_ops_read_sms">خوێندنەوەی SMS کانت</string>
+ <string name="app_ops_receive_sms">گەیشتنی نامەی SMS</string>
+ <string name="app_ops_record_audio">تۆمارکردنی دەنگ</string>
+ <string name="app_ops_send_mms">ناردنی نامەی MMS</string>
+ <string name="app_ops_send_sms">ناردنی نامەی SMS</string>
+ <string name="app_ops_start_at_bootup">دەستپێکردنی چالاککردنی هێز</string>
+ <string name="app_ops_toast_window">پیشاندانی تێبینی تازە</string>
+ <string name="app_ops_toggle_bluetooth">گۆڕینی بلوتوس</string>
+ <string name="app_ops_toggle_nfc">گۆڕینی دۆخی NFC</string>
+ <string name="app_ops_use_alarm_volume">کۆنترۆڵی دەنگی زەنگ</string>
+ <string name="app_ops_use_audio_focus">کۆنترۆڵی تیشکۆی دەنگ</string>
+ <string name="app_ops_use_bluetooth_volume">کۆنترۆڵکردنی دەنگی بلوتوس</string>
+ <string name="app_ops_use_master_volume">کۆنترۆڵکردنی دەنگی سەرەکی</string>
+ <string name="app_ops_use_media_buttons">بەکارهێنانی دوگمەی ڕەنگاڵە</string>
+ <string name="app_ops_use_media_volume">کۆنترۆڵی دەنگی ڕەنگاڵە</string>
+ <string name="app_ops_use_notification_volume">کۆنترٶڵی دەنگی تێبنینی</string>
+ <string name="app_ops_use_ring_volume">کۆنترۆڵی دەنگی زەنگ</string>
+ <string name="app_ops_use_vibrate">بەکارهێنانی بەرپەرچدانی Haptic</string>
+ <string name="app_ops_use_voice_volume">کۆنترۆڵی دەنگی تەلەفۆن</string>
+ <string name="app_ops_write_mms">نوسنی نامەی MMS</string>
+ <string name="app_ops_write_sms">نوسینی نامەی SMS</string>
+ <string name="app_ops_su">بەدەستهێنانی ڕێگەپێدانی ڕۆت</string>
+ <string name="live_display_auto">خۆکارانه‌</string>
+ <string name="live_display_off">کوژانه‌وه‌</string>
+ <string name="live_display_off_summary">لەکارخستنی هەموو ڕێکخستنەکان</string>
+ <string name="live_display_day">ڕۆژ</string>
+ <string name="live_display_day_summary">بەکارهێنانی ڕێکخستنی ڕۆژ تەنها</string>
+ <string name="live_display_night">شەو</string>
+ <string name="live_display_night_summary">تەنها ڕێکخستنی شەو بەکاربهێنە</string>
+ <string name="live_display_outdoor">دەرەوە (ڕۆشنای خۆر)</string>
+ <string name="tethered_notification_no_device_message">ئامێر پەیوەست نەکراوە</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> ئامێر پەیوەستکراوە</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> ئامێری پەیوەستکراو</string>
+</resources>
diff --git a/core/res/res/values-ku/strings.xml b/core/res/res/values-ku/strings.xml
new file mode 100644
index 0000000..f1dc664
--- /dev/null
+++ b/core/res/res/values-ku/strings.xml
@@ -0,0 +1,1322 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="byteShort">بایت</string>
+ <string name="kilobyteShort">کیلۆبایت</string>
+ <string name="megabyteShort">مێگابایت</string>
+ <string name="gigabyteShort">گیگابایت</string>
+ <string name="terabyteShort">تێرابایت</string>
+ <string name="petabyteShort">پیکۆبایت</string>
+ <string name="untitled">&lt;بێ ناونیشان&gt;</string>
+ <string name="emptyPhoneNumber">(هیچ ژماره‌ ته‌له‌فۆنێک نییه‌)</string>
+ <string name="defaultVoiceMailAlphaTag">دەنگەپۆست</string>
+ <string name="defaultMsisdnAlphaTag">MSISDN1</string>
+ <string name="mmiError">کێشه‌ی په‌یوه‌ندی هه‌یه‌ یان کۆدی MMI ناڕاستە.</string>
+ <string name="mmiFdnError">کردارەکە تەنیا بۆ ژمارە جێگیرکراوەکان سنووربەندکراوە.</string>
+ <string name="serviceEnabled">خزمه‌تگوزارییەکە چالاککرا.</string>
+ <string name="serviceEnabledFor">خزمه‌تگوزارییەکە چالاککرا بۆ:</string>
+ <string name="serviceDisabled">خزمه‌تگوزارییەکە ناچالاککراوە.</string>
+ <string name="serviceRegistered">خۆتۆمارکردن سه‌رکه‌وتوو بوو.</string>
+ <string name="serviceErased">سڕینه‌وه‌ سه‌رکه‌وتوو بوو.</string>
+ <string name="passwordIncorrect">تێپه‌ڕەوشه‌ ناڕاستە.</string>
+ <string name="mmiComplete">کۆدی MMI تەواوە.</string>
+ <string name="badPin">(PIN)ە کۆنه‌کە کە نووسیوتە ڕاست نییە.</string>
+ <string name="badPuk">(PUK)ەکە کە نووسیوتە ڕاست نییە.</string>
+ <string name="mismatchPin">(PIN)ەکان کە نووسیوتن له‌یه‌کناچن.</string>
+ <string name="invalidPin">(PIN)ەک بنووسه‌ که‌ ٤ بۆ ٨ ژماره‌ بێت.</string>
+ <string name="invalidPuk">(PUK)ەکەیەک بنووسە کە ٨ ژمارە یان درێژتر بێت.</string>
+ <string name="needPuk">سیمکارته‌که‌ت داخراوە به‌ PUK، بۆ کردنه‌وه‌ی کۆدی PUK بنووسە.</string>
+ <string name="needPuk2">تکایه‌ PUK2 بنووسه‌ بۆ کردنەوەی سیمکارت.</string>
+ <string name="enablePin">سه‌رکه‌وتوو نه‌بوو ، تکایه‌ داخەری SIM/RUIM چالاک بکه‌.</string>
+ <string name="imei">IMEI</string>
+ <string name="meid">MEID</string>
+ <string name="ClipMmi">هاتنی پێناسه‌ی پەیوەندیکه‌ر</string>
+ <string name="ClirMmi">ڕۆیشتنی پێناسەی په‌یوه‌ندیکه‌ر</string>
+ <string name="CfMmi">ناردنەوەی په‌یوه‌ندی</string>
+ <string name="CwMmi">چاوەڕوانیی پەیوەندی</string>
+ <string name="BaMmi">نەهێشتنی پەیوەندی</string>
+ <string name="PwdMmi">گۆڕینی تێپه‌ڕەوشه‌</string>
+ <string name="PinMmi">گۆڕینی PIN</string>
+ <string name="CnipMmi">ژماره‌ی په‌یوه‌ندی ئاماده‌یە</string>
+ <string name="CnirMmi">ژماره‌ی په‌یوه‌ندی سنووربەند کراوە</string>
+ <string name="ThreeWCMmi">په‌یوه‌ندیکردنی سێ ڕێگایی</string>
+ <string name="RuacMmi">بەرپەرچ دانەوەی په‌یوه‌ندییە بێزارکەرەکان و نەخوازراوەکان</string>
+ <string name="CndMmi">گەیاندنی ژماره‌ی په‌یوه‌ندیکردن</string>
+ <string name="DndMmi">مەمشێوێنە</string>
+ <string name="CLIRDefaultOnNextCallOn">پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنووربەندکراوە. په‌یوه‌ندیی داهاتوو: سنووربەند کراوە</string>
+ <string name="CLIRDefaultOnNextCallOff">پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنووربەندکراوە. بەڵام په‌یوه‌ندیی داهاتوو: سنووربەند نەکراوە</string>
+ <string name="CLIRDefaultOffNextCallOn">پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنووربەندکراو نییه‌. بەڵام په‌یوه‌ندیی داهاتوو: سنووربەند کراوە</string>
+ <string name="CLIRDefaultOffNextCallOff">پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنوورداره نییه‌. په‌یوه‌ندیی داهاتوو: سنووردار نییه‌</string>
+ <string name="serviceNotProvisioned">خزمه‌تگوزاری به‌رده‌ست نییه‌.</string>
+ <string name="CLIRPermanent">ناتوانیت ڕێکخستنی پێناسەی په‌یوه‌ندیکه‌ر بگۆڕیت.</string>
+ <string name="RestrictedChangedTitle">دەستگەیاندنی سنووردار گۆڕدرا</string>
+ <string name="RestrictedOnData">خزمەتگوزاریی دراوە به‌ستراوه‌.</string>
+ <string name="RestrictedOnEmergency">خزمەتگوزاریی فریاکەوتن به‌ستراوه‌.</string>
+ <string name="RestrictedOnNormal">خزمەتگوزاریی ده‌نگ به‌ستراوه‌.</string>
+ <string name="RestrictedOnAllVoice">هه‌موو خزمەتگوزارییەکانی ده‌نگ به‌ستراون.</string>
+ <string name="RestrictedOnSms">خزمەتگوزاریی کورتەنامە به‌ستراوه‌.</string>
+ <string name="RestrictedOnVoiceData">خزمەتگوزارییەکانی ده‌نگ و داتا به‌ستراون.</string>
+ <string name="RestrictedOnVoiceSms">خزمەتگوزارییەکانی ده‌نگ و کورتەنامە به‌ستراون.</string>
+ <string name="RestrictedOnAll">هه‌موو خزمەتگوزارییەکانی ده‌نگ، داتا و کورتەنامە به‌ستراون.</string>
+ <string name="serviceClassVoice">ده‌نگ</string>
+ <string name="serviceClassData">داتا</string>
+ <string name="serviceClassFAX">فاکس</string>
+ <string name="serviceClassSMS">کورتەنامە</string>
+ <string name="serviceClassDataAsync">ناهاوکاتگەری</string>
+ <string name="serviceClassDataSync">هاوکاتگەری</string>
+ <string name="serviceClassPacket">گورزەی دراوە</string>
+ <string name="serviceClassPAD">نەزانراو</string>
+ <string name="roamingText0">دیارخه‌ری ڕۆمینگ هەڵکراوە</string>
+ <string name="roamingText1">دیارخه‌ری ڕۆمینگ کوژاوه‌ته‌وه‌</string>
+ <string name="roamingText2">دیارخه‌ری ڕۆمینگ چاو دادەگرێ</string>
+ <string name="roamingText3">له‌ ده‌ره‌وه‌ی گه‌ڕه‌ک</string>
+ <string name="roamingText4">له‌ ده‌ره‌وه‌ی خانوو</string>
+ <string name="roamingText5">ڕۆمینگ - سیستەمی بەباشزانراو</string>
+ <string name="roamingText6">ڕۆمینگ - سیستەمی به‌رده‌ست</string>
+ <string name="roamingText7">ڕۆمینگ - هاوپەیمانی یەکگرتوو</string>
+ <string name="roamingText8">ڕۆمینگ - هاوپەیمانی باشتر</string>
+ <string name="roamingText9">ڕۆمینگ - کارکردی تەواوی خزمەتگوزاری</string>
+ <string name="roamingText10">ڕۆمینگ - کارکردی بەشێک لە خزمەتگوزاری</string>
+ <string name="roamingText11">هێمای ڕۆمینگ هەڵکراوە</string>
+ <string name="roamingText12">هێمای ڕۆمینگ کوژاوه‌ته‌وه‌</string>
+ <string name="roamingTextSearching">گه‌ڕان به‌دوای خزمه‌تگوزاری</string>
+ <string name="cfTemplateNotForwarded"><xliff:g id="bearer_service_code">{0}</xliff:g>: پەیوەندی ئاراستە نەکراوە</string>
+ <string name="cfTemplateForwarded"><xliff:g id="bearer_service_code">{0}</xliff:g>: <xliff:g id="dialing_number">{1}</xliff:g></string>
+ <string name="cfTemplateForwardedTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: <xliff:g id="dialing_number">{1}</xliff:g> دوای <xliff:g id="time_delay">{2}</xliff:g> چرکه‌</string>
+ <string name="cfTemplateRegistered"><xliff:g id="bearer_service_code">{0}</xliff:g>: پەیوەندی ئاراستە نەکراوە</string>
+ <string name="cfTemplateRegisteredTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: پەیوەندی ئاراستە نەکراوە</string>
+ <string name="fcComplete">کۆدی تایبەت ته‌واو بوو.</string>
+ <string name="fcError">کێشه‌ی گرێدان هه‌یه‌ یان کۆدی تایبەت ناڕاسته‌.</string>
+ <string name="httpErrorOk">باشه‌</string>
+ <string name="httpError">هه‌ڵه‌یه‌ک له‌ تۆڕدا هه‌بوو.</string>
+ <string name="httpErrorLookup">نه‌یتوانی ناونیشانی ئینتەرنێتی بدۆزێته‌وه‌.</string>
+ <string name="httpErrorUnsupportedAuthScheme">پلانی پارێزپرسیی ماڵپه‌ڕ پشتگیری ناکرێت.</string>
+ <string name="httpErrorAuth">نەیتوانی پارێزپرسی تێپەڕ بکات.</string>
+ <string name="httpErrorProxyAuth">تێپەڕکردنی پارێزپرسی له‌ ڕێی ڕاژه‌کاری پرۆکسی سه‌رکه‌وتوو نه‌بوو.</string>
+ <string name="httpErrorConnect">نه‌یتوانی گرێبدرێت به‌ ڕاژه‌کاره‌وه‌.</string>
+ <string name="httpErrorIO">نه‌یتوانی گرێبدرێت به‌ ڕاژه‌کاره‌وه‌. دواتر هه‌وڵبده‌وه‌.</string>
+ <string name="httpErrorTimeout">کاتی گرێدان به‌ ڕاژه‌کاره‌وه‌ به‌سه‌ر چوو.</string>
+ <string name="httpErrorRedirectLoop">په‌ڕه‌که‌ پڕە لە ئاراستەگۆڕینی ڕاژه‌کار.</string>
+ <string name="httpErrorUnsupportedScheme">پرۆتۆكۆڵەکە پشتگیری ناکرێت.</string>
+ <string name="httpErrorFailedSslHandshake">نەیتوانی گرێدانێکی دڵنیا دابمه‌زرێنێت.</string>
+ <string name="httpErrorBadUrl">نەیتوانی په‌ڕه‌که‌ بکاته‌وه‌ لەبەر ئەوەی ناونیشانه‌که‌ ڕاست نییه‌.</string>
+ <string name="httpErrorFile">نەیتوانی دەست بگەیەنێتە فایلەکە.</string>
+ <string name="httpErrorFileNotFound">نەیتوانی فایلی داواکراو بدۆزێته‌وه‌.</string>
+ <string name="httpErrorTooManyRequests">داواکاریی زۆر خراوه‌ته‌ ڕوو. دواتر هه‌وڵبده‌وه‌.</string>
+ <string name="notification_title">هه‌ڵه‌ له‌ چوونه‌ژووره‌وه‌ بۆ <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g></string>
+ <string name="contentServiceSync">هاوکاتگەری</string>
+ <string name="contentServiceSyncNotificationTitle">هاوکاتگەری</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc">هەندێک <xliff:g id="content_type">%s</xliff:g> دەسڕێنەوە.</string>
+ <string name="low_memory" product="tablet">بیرگه‌ی تابلێت پڕە. هه‌ندێک فایل بسڕه‌وه‌ بۆ ئازادکردنی بۆشایی.</string>
+ <string name="low_memory" product="default">بیرگه‌ی تەلەفۆن پڕە. هه‌ندێک فایل بسڕه‌وه‌ بۆ ئازادکردنی بۆشایی.</string>
+ <string name="ssl_ca_cert_warning">له‌وانه‌یه‌ تۆڕه‌که‌ چاودێری کرابێت</string>
+ <string name="ssl_ca_cert_noti_by_unknown">له‌لایه‌ن به‌شی نه‌ناسراوی سێیه‌مه‌وه‌</string>
+ <string name="ssl_ca_cert_noti_managed">له‌لایه‌ن <xliff:g id="managing_domain">%s</xliff:g></string>
+ <string name="me">من</string>
+ <string name="power_dialog" product="tablet">بژارده‌کانی تابلێت</string>
+ <string name="power_dialog" product="default">بژارده‌کانی ته‌له‌فۆن</string>
+ <string name="silent_mode">دۆخی بێده‌نگ</string>
+ <string name="turn_on_radio">داگیرساندنی بێته‌ل</string>
+ <string name="turn_off_radio">کوژاندنه‌وه‌ی بێته‌ل</string>
+ <string name="screen_lock">داخەری ڕوونما</string>
+ <string name="power_off">کوژاندنه‌وه‌</string>
+ <string name="silent_mode_silent">کوژاندنه‌وه‌ی زه‌نگلێدەر</string>
+ <string name="silent_mode_vibrate">زەنگلێدەر لەسەر دۆخی لەرین</string>
+ <string name="silent_mode_ring">بەکارخستنی زه‌نگلێدەر</string>
+ <string name="shutdown_progress">کوژاندنه‌وه‌ی\u2026</string>
+ <string name="shutdown_confirm" product="tablet">تابلێته‌که‌ت ده‌کووژێته‌وه‌.</string>
+ <string name="shutdown_confirm" product="default">ته‌له‌فۆنه‌که‌ت ده‌کووژێته‌وه‌.</string>
+ <string name="shutdown_confirm_question">ده‌ته‌وێت بکوژێته‌وه‌؟</string>
+ <string name="reboot_safemode_title">دەسپێکردنەوە بۆ سەر دۆخی دڵنیاکراو</string>
+ <string name="reboot_safemode_confirm">ده‌ته‌وێت دەست پێ بکەیتەوە بۆ دۆخی دڵنیاکراو؟
+ ئه‌م کرداره‌ هه‌موو ئه‌و به‌رنامه‌ لاوه‌کییانه‌ ده‌سڕێته‌وه‌ که‌ داتمه‌زراندوون.
+ ئەوانە دەگەڕێنەوە باری خۆیان، کاتێک سەر لە نوێ دەست پێ دەکەیتەوە.</string>
+ <string name="recent_tasks_title">نوێ</string>
+ <string name="no_recent_tasks">هیچ به‌رنامه‌یەکی نوێ نییه‌.</string>
+ <string name="global_actions" product="tablet">بژارده‌کانی تابلێت</string>
+ <string name="global_actions" product="default">بژاردەکانی ته‌له‌فۆن</string>
+ <string name="global_action_lock">داخەری ڕوونما</string>
+ <string name="global_action_power_off">کوژاندنه‌وه‌</string>
+ <string name="global_action_bug_report">ڕاپۆرتی کەلێن</string>
+ <string name="bugreport_title">گرتنەوەی ڕاپۆرتی کەلێن</string>
+ <string name="bugreport_message">ئه‌م کردارە سەبارەت بە ئامێری ئێستات زانیاری کۆ ده‌کاته‌وه‌
+ و بە شێوەی پۆستی ئەلەکترۆنی دەینێرێت. ماوەیەکی زۆر کەم دەخایەنێت
+ بۆ ئامادەکردنی ڕاپۆرتەکە تا ئەوکات کە دەنێردرێت: تکایە هێور بە.</string>
+ <string name="global_action_toggle_silent_mode">دۆخی بێده‌نگ</string>
+ <string name="global_action_silent_mode_on_status">دەنگ کوژاوەیە</string>
+ <string name="global_action_silent_mode_off_status">دەنگ هەڵکراوە</string>
+ <string name="global_actions_toggle_airplane_mode">دۆخی فڕۆکە</string>
+ <string name="global_actions_airplane_mode_on_status">دۆخی فڕۆکه‌ کراوه‌یه‌</string>
+ <string name="global_actions_airplane_mode_off_status">دۆخی فڕۆکه‌ کوژاوه‌یه‌</string>
+ <string name="status_bar_notification_info_overflow">+٩٩٩</string>
+ <string name="safeMode">دۆخی دڵنیاکراو</string>
+ <string name="android_system_label">سیسته‌می ئه‌ندرۆید</string>
+ <string name="permgrouplab_calendar">ڕۆژمێر</string>
+ <string name="permgrouplab_sms">کورتەنامە</string>
+ <string name="permgrouplab_storage">بیرگه‌</string>
+ <string name="permgrouplab_microphone">بیستۆک</string>
+ <string name="permgroupdesc_microphone">تۆمارکردنی دەنگ</string>
+ <string name="permgrouplab_camera">کامێرا</string>
+ <string name="permgrouplab_phone">مۆبایل</string>
+ <string name="capability_title_canRetrieveWindowContent">ناوەرۆكى پەنجەرە بگێڕەوە</string>
+ <string name="capability_desc_canRetrieveWindowContent">ناوەرۆكى پەنجەرەيێك دەپشكنێت تۆ ن
+
+لەگەڵ كار لە يەكتان كرد.</string>
+ <string name="capability_title_canRequestTouchExploration">وێبگەر بکەرەوە بە دەست لێدان</string>
+ <string name="capability_desc_canRequestTouchExploration">برگەى بەركەوتن بەدەنگى بەرز قسە دەكرێن
+
+و شاشەكە دەتوانێت سەرنج بدەرێت بەكارهێنانى نيشانە.
+</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility">وێبى زيادكراو بەكار بخە
+
+دەشێت لێى نزيك ببێتەوە يا بچێتە ناوى</string>
+ <string name="capability_desc_canRequestEnhancedWebAccessibility">نوسراو لەوانەيە بۆ دا بمەزرێنرێن
+
+ناوەرۆكى بەرنامە ئاسان پەيدابووتر كرد.</string>
+ <string name="capability_title_canRequestFilterKeyEvents">نووسين تێبينى بكە تۆ جۆر دەن</string>
+ <string name="capability_desc_canRequestFilterKeyEvents">وەكو متمانەى زانيارى كەسى بگرەوە
+
+كارت ڕەنووس دەكات و وشەى تێپەڕين.
+</string>
+ <string name="permlab_statusBar">پەك دەخات بە يان میله‌ يان دۆخ دەگۆڕێت</string>
+ <string name="permdesc_statusBar">ڕێ دەدات بە بەرنامە تا شيشەكەى دۆخ پەك دەخات بێت يان زياد دەكات و ئايكۆنى سيستەم لا دەبات.</string>
+ <string name="permlab_statusBarService">تووڵ دۆخ
+</string>
+ <string name="permdesc_statusBarService">ڕێ دەدات بە بەرنامە تا شيشەكەى دۆخ ببێت.
+</string>
+ <string name="permlab_expandStatusBar"> شيشى دۆخى ڕووخان فراوان بكە</string>
+ <string name="permdesc_expandStatusBar">ڕێ دەدات بە بەرنامە تا فراوان بكات يان ڕووخان شيشەكەى دۆخ.
+
+
+
+
+
+
+
+
+
+
+
+
+
+</string>
+ <string name="permlab_install_shortcut">شۆتكەتس دا بمەزرێنە</string>
+ <string name="permdesc_install_shortcut">ڕێگه‌ دان بۆ زیادکردنی به‌رنامه‌
+قه‌د بڕ له‌سه‌ر ڕوونمای ماڵه‌وه‌ به‌بێ به‌کارهێنه‌ر.</string>
+ <string name="permlab_uninstall_shortcut">سڕینه‌وه‌ قه‌دبڕه‌کان</string>
+ <string name="permdesc_uninstall_shortcut">ڕێگه‌دان به‌ بارنامه‌ بۆ سڕینه‌وه‌
+قه‌دبڕی ڕوونمای ماڵه‌وه‌ به‌بێ به‌کارهێنه‌ر.</string>
+ <string name="permlab_processOutgoingCalls">ته‌له‌فۆنکردنی ده‌ره‌وه‌</string>
+ <string name="permdesc_processOutgoingCalls">ڕێگه‌ دان به‌به‌رنامه‌که‌ بۆ بینینی ژماره‌کان که‌ لێدراوهن له‌کاتی ته‌له‌فۆنی ده‌ره‌وه‌ هه‌ڵبژارده‌ی ته‌له‌فۆن بۆ ڕێگه‌ دان به‌ ته‌له‌فۆنکردنی جیاواز.</string>
+ <string name="permlab_receiveSms">گه‌شتنی ده‌قه‌ نامه‌(SMS)</string>
+ <string name="permdesc_receiveSms">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ گه‌شتنی نامه‌.ئه‌مه‌ مانانی
+ئه‌وه‌یه‌ به‌رنامه‌که‌ ئه‌توانێت نامه‌ بسڕێته‌وه‌ یان ناردنی بۆ ئامێره‌که‌ به‌ بێ پیشاندانی تۆ.</string>
+ <string name="permlab_receiveMms">گه‌شتنی ده‌قه‌ نامه‌ی(MMS)</string>
+ <string name="permdesc_receiveMms">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ گه‌شتنی نامه‌.ئه‌مه‌ مانانی
+ئه‌وه‌یه‌ به‌رنامه‌که‌ ئه‌توانێت نامه‌ بسڕێته‌وه‌ یان ناردنی بۆ ئامێره‌که‌ به‌ بێ پیشاندانی تۆ.</string>
+ <string name="permlab_readCellBroadcasts">خوێندنه‌وه‌ی هه‌موو خانه‌ی په‌خشه‌ نامه‌کان</string>
+ <string name="permlab_subscribedFeedsRead">خوێندنه‌وه‌ی پێدانی به‌شداریپێکراو</string>
+ <string name="permdesc_subscribedFeedsRead">ڕێگه‌دان به‌ به‌رنامه‌ بۆ وه‌رگرتنی زانیاری له‌باره‌ی خوێندنه‌وه‌ی پێدانی به‌شداریپێکراو.</string>
+ <string name="permdesc_sendSms">ڕێ دەدات بە بەرنامە تا نامەى ئێس ئێم ئێس بنێرێت.
+
+ئەمە لەوانەيە ببێت بە هۆى تۆمەتى چاوەروان نەكراو. بەرنامەى قيناوى لەوانەيە تێ بچن لەلايەن پارەى تۆ
+
+ناردنى نامە بەبێ دووپات كردنت.</string>
+ <string name="permlab_readSms">خوێندنه‌وه‌ی نامه‌کان(MMS یان SMS)</string>
+ <string name="permdesc_readSms" product="tablet">ڕێ دەدات بە بەرنامە تا ئێس ئێم ئێس بخوێنێتەوە
+
+نامە لەسەر كارتتى جۆر يان سيميان خەزن كرد. ئەمە ڕێ دەدەن بە بەرنامە تا هەموو بخوێنێتەوە
+
+نامەى ئێس ئێم ئێس، بێگوێدانەى ناوەرۆك يان برايانە. </string>
+ <string name="permdesc_readSms" product="default">ڕێ دەدات بە بەرنامە تا ئێس ئێم ئێس بخوێنێتەوە
+
+نامە لەسەر كارتتى تەلەفۆن يان سيميان خەزن كرد. ئەمە ڕێ دەدەن بە بەرنامە تا هەموو بخوێنێتەوە
+
+نامەى ئێس ئێم ئێس، بێگوێدانەى ناوەرۆك يان برايانە.</string>
+ <string name="permlab_receiveWapPush">گه‌شتنی نامه‌ی (WAP)</string>
+ <string name="permdesc_receiveWapPush">ڕێ دەدات بە بەرنامە تا وەر بگرێت و كردار
+
+نامەى WAP. ئەمە ڕێگەپێدان توانايەكە دەگرێتەوە تا چاودێرى بكات يان دەسڕێتەوە
+
+بۆ نامە ناردى تۆ بۆ پيشاندانى ئەوان تۆ.</string>
+ <string name="permlab_getTasks">گه‌ڕانه‌وه‌ی به‌رنامه‌ی له‌کار</string>
+ <string name="permdesc_getTasks">ڕێ دەدات بە بەرنامە تا زانيارى بگێڕێتەوە
+
+دەربارەى ئێستا و بەم دواييە ڕاكردنى ئەرك. ئەمە لەوانەيە ڕێ بدات بە بۆ بەرنامە
+
+زانيارى دەربارەى بدۆزەوە داوا كردن بەكار دێنرێن لەسەر ئامرازەكە.</string>
+ <string name="permlab_reorderTasks">تۆمارکردنی به‌رنامه‌ی کراوه‌</string>
+ <string name="permdesc_reorderTasks">ڕێگه‌ دان به‌ به‌رنامه‌که‌ بۆ گۆڕینی ئه‌رک بۆ سه‌رو پاشه‌وه‌ی پشته‌گه‌ڵاڵه‌. به‌رنامه‌که‌ بێ تۆ ئه‌یکات.</string>
+ <string name="permlab_enableCarMode">چالاککردنی باری سه‌یاره‌</string>
+ <string name="permdesc_enableCarMode">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ چالاککردنی باری سه‌یاره‌.</string>
+ <string name="permlab_killBackgroundProcesses">داخستنی به‌رنامه‌ی تر</string>
+ <string name="permdesc_killBackgroundProcesses">ڕێ دەدات بە بەرنامە تا كۆتايى پێ بهێنێت
+
+كردارى زەمينەى بەرنامەى ديكە. ئەمە لەوانەيە ببێتە هۆى بەرنامەى ديكە تا ڕا بگرن
+
+ڕاكردن. </string>
+ <string name="permlab_systemAlertWindow">پیشاندان لە سەروی بەرنامەکانی ترەوە</string>
+ <string name="permdesc_systemAlertWindow">ڕێگە بە بەرنامەکە دەدا کە تێکەڵی روکاری بەرنامەکانی تر بێت.وە ئەوشتەی کەدەیبینیت بگۆرێت</string>
+ <string name="permlab_persistentActivity">وا له‌ به‌رنامه‌که‌ بکرێت هه‌میشه‌ کرابێته‌وه‌</string>
+ <string name="permdesc_persistentActivity" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ به‌شکردنی خۆی له ناو بیرگەی. ئه‌مه‌ له‌وانه‌یه‌ بیرگەییه‌که‌ت سنوردار بکات بۆ به‌رنامه‌کانی تر که‌ تابلێته‌که‌ت خاو ده‌کاته‌وه‌.</string>
+ <string name="permdesc_persistentActivity" product="default">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ به‌شکردنی خۆی له ناو بیرگەی. ئه‌مه‌ له‌وانه‌یه‌ بیرگەییه‌که‌ت سنوردار بکات بۆ به‌رنامه‌کانی تر که‌ مۆبایله‌که‌ت خاو ده‌کاته‌وه‌.</string>
+ <string name="permlab_getPackageSize">مامه‌ڵه‌کردن له‌گه‌ڵ قه‌باره‌ی به‌کارنه‌هێنراو</string>
+ <string name="permdesc_getPackageSize">ڕێگه‌دان به‌ به‌رنامه‌ بۆ وه‌رگرتنی کۆد ، زانیاری ، و قه‌باره‌ی فایله‌ زیاده‌کان</string>
+ <string name="permlab_writeSettings">گۆڕینی رێکخستنەکانی سیستەم</string>
+ <string name="permdesc_writeSettings">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ گۆڕینی زانیاری سیسته‌م.به‌رنامه‌ به‌دخووه‌کان بۆ تێکدانی سیسته‌م به‌کاریده‌هێنن ڕێگه‌ به‌ هه‌موو به‌رنامه‌یه‌ک مه‌ده‌.</string>
+ <string name="permlab_receiveBootCompleted">کارکردن له‌گه‌ڵ داگیرساندن</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خۆکارانه‌ ده‌ستپێکردن له‌گه‌ڵ داگیرساندنی تابلێته‌که‌ت. به‌ڵام له‌وانه‌یه‌ هۆکارێک بێت بۆ خاوبوونه‌وه‌ی داگیرساندن وه‌ خاوکردنه‌وه‌ی تابلێتکه‌.</string>
+ <string name="permdesc_receiveBootCompleted" product="default">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خۆکارانه‌ ده‌ستپێکردن له‌گه‌ڵ داگیرساندنی مۆبایله‌که‌ت. به‌ڵام له‌وانه‌یه‌ هۆکارێک بێت بۆ خاوبوونه‌وه‌ی داگیرساندن وه‌ خاوکردنه‌وه‌ی مۆبایله‌که‌.</string>
+ <string name="permlab_broadcastSticky">ناردنی په‌خشی لکێنراو</string>
+ <string name="permdesc_broadcastSticky" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ ناردنی په‌خشی لکێندراو، که‌ ده‌مێنێته‌وه‌ دوای ته‌واوبونی په‌خشیش. له‌وانه‌یه‌ ببێته‌ هۆی سه‌رفکردنی زۆرێک له‌ بیرگه‌ و خاوکردنه‌وه‌ی تابلێت.
+    </string>
+ <string name="permdesc_broadcastSticky" product="default">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ ناردنی په‌خشی لکێندراو، که‌ ده‌مێنێته‌وه‌ دوای ته‌واوبونی په‌خشیش. له‌وانه‌یه‌ ببێته‌ هۆی سه‌رفکردنی زۆرێک له‌ بیرگه‌ و خاوکردنه‌وه‌ی مۆبایل.</string>
+ <string name="permlab_readContacts">خوێندنه‌وه‌ی په‌یوه‌ندێكانت</string>
+ <string name="permdesc_readContacts" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خوێندنه‌وه‌ی زانیاری له‌باره‌ی په‌یوه‌ندییه‌کانت له‌ناو تابلێته‌که‌ته‌، که‌ فریکوەنسی له‌گه‌ڵه‌ بۆ ته‌له‌فۆنکراوه‌کان، ئیمێلکراوه‌کان، کۆمه‌ڵایه‌تییه‌کان له‌ چه‌نده‌ها ڕێگای تره‌وه‌.ده‌سته‌ڵاته‌که‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ که‌ په‌یوه‌ندییه‌کانت پاشه‌که‌وت بکات له‌گه‌ڵ زانیارییه‌کانیان.به‌ڵام وریای به‌رنامه‌ به‌دخووه‌کان به‌ بۆ مه‌به‌ستی خراپ به‌کارده‌هێنن.</string>
+ <string name="permdesc_readContacts" product="default">ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خوێندنه‌وه‌ی زانیاری له‌باره‌ی په‌یوه‌ندییه‌کانت له‌ناو مۆبایله‌که‌ت. که‌ فریکوەنسی له‌گه‌ڵه‌ بۆ ته‌له‌فۆنکراوه‌کان، ئیمێلکراوه‌کان، کۆمه‌ڵایه‌تییه‌کان له‌ چه‌نده‌ها ڕێگای تره‌وه‌.ده‌سته‌ڵاته‌که‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ که‌ په‌یوه‌ندییه‌کانت پاشه‌که‌وت بکات له‌گه‌ڵ زانیارییه‌کانیان.به‌ڵام وریای به‌رنامه‌ به‌دخووه‌کان به‌ بۆ مه‌به‌ستی خراپ به‌کارده‌هێنن.</string>
+ <string name="permlab_writeContacts">گۆڕانکاری لە ژمارەی پەیوەندیەکانتدا بکە</string>
+ <string name="permdesc_writeContacts" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی زانیاری له‌باره‌ی په‌یوه‌ندییه‌ پاشه‌که‌وتکراوه‌کان له‌ تابلێته‌که‌ت، که‌ فریکوه‌نسی تێدایه‌ په‌یوه‌ندیت پێوه‌کردوون،ئیمێل،یان هه‌ر شتێکی تری کۆمه‌ڵایه‌تی، ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ داتاکانت بسڕێته‌وه‌.</string>
+ <string name="permdesc_writeContacts" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی زانیاری له‌باره‌ی په‌یوه‌ندییه‌ پاشه‌که‌وتکراوه‌کان له‌ مۆبایله‌که‌ت، که‌ فریکوه‌نسی تێدایه‌ په‌یوه‌ندیت پێوه‌کردوون،ئیمێل،یان هه‌ر شتێکی تری کۆمه‌ڵایه‌تی، ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ داتاکانت بسڕێته‌وه‌.</string>
+ <string name="permlab_readCallLog">خوێندنه‌وه‌ی ته‌له‌فۆنی تۆمارکراو</string>
+ <string name="permdesc_readCallLog" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی تۆماری په‌یوه‌ندییه‌کان، که‌ زانیاری تێدایه‌ له‌باره‌ی په‌یوه‌ندی هاتوو وه‌ ڕۆشتوو.ئه‌م ده‌سته‌لاته‌ ڕێگه به‌ به‌رنامه‌که‌ ده‌دات بۆ خه‌زن کردنی تۆماری په‌یوه‌ندییه‌کانت.وه‌ به‌رنامه‌ به‌دخووه‌کان بۆ مه‌به‌ستی بڵاوکردنه‌وه‌یان به‌کاریده‌هێنن به‌بێ زانیاری تۆ.</string>
+ <string name="permdesc_readCallLog" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی تۆماری په‌یوه‌ندییه‌کان، که‌ زانیاری تێدایه‌ له‌باره‌ی په‌یوه‌ندی هاتوو وه‌ ڕۆشتوو.ئه‌م ده‌سته‌لاته‌ ڕێگه به‌ به‌رنامه‌که‌ ده‌دات بۆ خه‌زن کردنی تۆماری په‌یوه‌ندییه‌کانت.وه‌ به‌رنامه‌ به‌دخووه‌کان بۆ مه‌به‌ستی بڵاوکردنه‌وه‌یان به‌کاریده‌هێنن به‌بێ زانیاری تۆ.</string>
+ <string name="permlab_writeCallLog">نوسینی تۆماری په‌یوه‌ندییه‌کان</string>
+ <string name="permdesc_writeCallLog" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی تۆماری په‌یوه‌ندییه‌کانت.که‌ زانیاری له‌باره‌ی په‌یوه‌ندی هاتوو و وه‌ ڕۆشتووی تێدایه‌.به‌رنامه‌ به‌دخووه‌کان به‌کاری ئه‌هێنن بۆ سڕینه‌وه‌ی تۆماره‌کان.</string>
+ <string name="permdesc_writeCallLog" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی تۆماری په‌یوه‌ندییه‌کانت.که‌ زانیاری له‌باره‌ی په‌یوه‌ندی هاتوو و وه‌ ڕۆشتووی تێدایه‌.به‌رنامه‌ به‌دخووه‌کان به‌کاری ئه‌هێنن بۆ سڕینه‌وه‌ی تۆماره‌کان.</string>
+ <string name="permlab_readCalendar">خوێندنه‌وه‌ی ڕووداوه‌کانی ڕۆژژمێر بۆ زانیاری شاراوه‌</string>
+ <string name="permdesc_readCalendar" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی هه‌موو ڕووداوه‌کانی ناو ڕۆژژمێره‌کان له‌ ئامێره‌که‌ت، وه‌ک هاوڕێکان و شوانه‌کان. ئه‌مه‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ده‌دات بۆ به‌شداریپێکردنی یان پاشه‌که‌وتکردنی زانیاری ڕۆژژمێره‌که‌ت وریابه‌.</string>
+ <string name="permdesc_readCalendar" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی هه‌موو ڕووداوه‌کانی ناو ڕۆژژمێره‌کان له‌ ئامێره‌که‌ت، وه‌ک هاوڕێکان و شوانه‌کان. ئه‌مه‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ده‌دات بۆ به‌شداریپێکردنی یان پاشه‌که‌وتکردنی زانیاری ڕۆژژمێره‌که‌ت وریابه‌.</string>
+ <string name="permlab_writeCalendar">زیادکردن یان گۆڕینی ڕووداو له‌ناو ڕۆژژمێر و ناردنی ئیمێل بۆ میوانه‌کان به‌بێ زانیاری له‌ باره‌ی دروستکه‌ره‌که‌ی</string>
+ <string name="permlab_accessLocationExtraCommands">ده‌سته‌ڵاتی شوێنی زیاتر بۆ فرمانی دابینکردن</string>
+ <string name="permlab_accessFineLocation">شوێنی ورد(GPS و دامه‌زراو له‌سه‌ر خه‌ت)</string>
+ <string name="permdesc_accessFineLocation">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌ستکه‌وتنی شوێنی ته‌واوی تۆ به‌ GPS یان خه‌ته‌که‌ت وه‌ک وایه‌رلێس و هێڵ.خزمه‌تگوزاری شوێن پێویسته‌ کاربکات بۆ ئه‌وه‌ی به‌رنامه‌کان شوێن بدۆزنه‌وه‌.به‌رنامه‌کان ده‌توانن بزانن له‌ کوێیت به‌ GPS ، ئه‌م کاره‌ باتری مۆبایله‌که‌ت که‌م ده‌کات.</string>
+ <string name="permlab_accessCoarseLocation">شوێنی نزیک(له‌سه‌ر خه‌ت)</string>
+ <string name="permdesc_accessCoarseLocation">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌ستکه‌وتنی شوێنی نزیکی تۆ به‌ GPS یان خه‌ته‌که‌ت وه‌ک وایه‌رلێس و هێڵ.خزمه‌تگوزاری شوێن پێویسته‌ کاربکات بۆ ئه‌وه‌ی به‌رنامه‌کان شوێن بدۆزنه‌وه‌.به‌رنامه‌کان ده‌توانن بزانن له‌ کوێیت به‌ GPS ، ئه‌م کاره‌ باتری مۆبایله‌که‌ت که‌م ده‌کات.</string>
+ <string name="permlab_modifyAudioSettings">گۆڕینی ڕێکخستنه‌کانی ده‌نگ</string>
+ <string name="permdesc_modifyAudioSettings">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی ڕێکخستنی ده‌نگی گشتی وه‌ک ده‌نگی بڵنگۆ به‌کاردێت بۆ ده‌رچه‌.</string>
+ <string name="permlab_recordAudio">تۆمارکردنی دەنگ</string>
+ <string name="permdesc_recordAudio">ڕێگه‌دان به‌ به‌رنامه‌ بۆ تۆمارکردنی ده‌نگ له‌گه‌ڵ مایکرۆفۆنه‌که‌. ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ هه‌رکاتێک بیه‌وێت ده‌نگ تۆماربکات.</string>
+ <string name="permlab_camera">گرتنی وێنه‌ یان ڤیدیۆ</string>
+ <string name="permdesc_camera">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گرتنی وێنه‌ و ڤیدیۆ له‌گه‌ڵ کامێراکه‌، ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ئه‌دات کامێرا به‌کاربهێنێ هه‌رکات بیه‌وێت.</string>
+ <string name="permlab_vibrate">سه‌رپه‌رشتیکردنی له‌رین</string>
+ <string name="permdesc_vibrate">ڕێگه‌دان به‌ به‌رنامه‌ بۆ سه‌رپه‌رشتی کردنی له‌رینه‌وه‌.</string>
+ <string name="permlab_flashlight">سه‌رپه‌رشتیکردنی ڕووناکی فلاش</string>
+ <string name="permdesc_flashlight">ڕێگه‌دان به‌ به‌رنامه‌ بۆ سه‌رپه‌رشتیکردنی ڕووناکی فلاش.</string>
+ <string name="permlab_callPhone">په‌یوه‌ندی کردنی ژماره‌کان ڕاسته‌وخۆیی</string>
+ <string name="permdesc_callPhone">ڕێگه‌دان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردن به‌ ژماره‌وه‌ به‌بێ زانینی تۆ.له‌وانه‌یه‌ ئه‌نجامه‌که‌ی خراپ بێت بۆ په‌یوه‌ندی کردن.
+تێبینی:ئه‌مه‌ ڕێگه‌ نادات به‌ به‌رنامه‌که‌ په‌یوه‌ندی به‌ ڕوداوی له‌ناکاو و کتوپڕ بکات.
+به‌رنامه‌ خراپه‌کان به‌کاریده‌هێنن بۆ سه‌رفکردنی باڵانسه‌کانت.</string>
+ <string name="permlab_readPhoneState">خوێندنه‌وه‌ی باری ئامێر و ناسنامه‌</string>
+ <string name="permdesc_readPhoneState">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌سته‌ڵاتکردنی خزمه‌ته‌کانی ئامێر.ئه‌مه‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ئه‌دات بۆ دیاریکردنی ژماره‌ی مۆبایل و ID ئامێر، کاتێک که‌ په‌یوه‌ندی له‌کاردایه‌ ، یان ژماره‌یه‌کی دووره‌ده‌ست په‌یوه‌ندییه‌ بۆ په‌یوه‌ندی.</string>
+ <string name="permlab_wakeLock" product="tablet">ڕێگری کردن له‌ تابلێت بۆ نوستن</string>
+ <string name="permlab_wakeLock" product="default">ڕێگری کردن له‌ مۆبایل بۆ نوستن</string>
+ <string name="permdesc_wakeLock" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێگری کردن له‌ تابلێت بۆ نوستن.</string>
+ <string name="permdesc_wakeLock" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێگری کردن له‌ مۆبایله‌که‌ت بۆ نوستن.</string>
+ <string name="permlab_transmitIr">گوێزه‌ره‌وه‌ی خوارسوور</string>
+ <string name="permdesc_transmitIr" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گواستنه‌وه‌ی خوارسور.</string>
+ <string name="permdesc_transmitIr" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گواستنه‌وه‌ی خوارسور.</string>
+ <string name="permlab_setWallpaper">دانانی دیوارپۆش</string>
+ <string name="permdesc_setWallpaper">ڕێگەدانی بەرنامە بۆ دانانی دیوارپۆشی سیستەم.</string>
+ <string name="permlab_setWallpaperHints">گونجاندنی قەبارەی دیوارپۆش</string>
+ <string name="permdesc_setWallpaperHints">ڕێگه‌دان به‌ به‌رنامه‌ بۆ دانانی قه‌باره‌ی سه‌رڕوونما.</string>
+ <string name="permlab_setTimeZone">کاتی ناوچەیی رێکبخە</string>
+ <string name="permdesc_setTimeZone" product="tablet">ڕێگە بە نمواڵەکە بدە کاتی ناوچەیی تاتەبژمێرەکە بگۆرێت.</string>
+ <string name="permdesc_setTimeZone" product="default">ڕێگە بە نمواڵەکە بدە کاتی ناوچەیی تەلەفونەکە بگۆرێت.</string>
+ <string name="permlab_getAccounts">هەژمارەکان لە سەر ئامێرەکە بدۆزەرەوە</string>
+ <string name="permdesc_getAccounts" product="tablet">ڕیگە بە نمواڵەکە بدە لیستی هەژمارە ناسراوەکان بەدەستبخات لەلایەن تاتەبژمیرەکەوە. ئەمە لەوانەیە هەریەکێ لە هەژمارەکان بگریتەوە کە لەلایەن نەرمەواڵا دابەزینراوەکانەوە دروست کرابێت.</string>
+ <string name="permdesc_getAccounts" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ به‌ده‌ستهێنانی لیستی هه‌موو هه‌ژماره‌کان له‌لایه‌ن ئامێره‌وه‌ ناسراون. له‌وانه‌یه‌ ئه‌مه‌ هه‌موو هه‌ژمارێکی تیابێت که‌ له‌لایه‌ن به‌رنامه‌کانه‌وه‌ دروستت کردووه‌.</string>
+ <string name="permlab_accessNetworkState">بینینی په‌یوه‌ندییه‌کانی خه‌ت</string>
+ <string name="permdesc_accessNetworkState">ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی زانیاری له‌باره‌ی په‌یوه‌ندی خه‌ت وه‌ک چ خه‌تێک هه‌یه‌ و چی په‌یوه‌ندیپێوه‌کراوه‌.</string>
+ <string name="permlab_createNetworkSockets">پڕاوپڕ ده‌سته‌ڵاتی خه‌ت</string>
+ <string name="permdesc_createNetworkSockets">ڕێگه‌دان به‌ به‌رنامه‌ بۆ دروستکردنی زانیاری خه‌ت و به‌کارهێنانی پرۆتۆکۆڵ.وه‌ وێبگه‌ره‌که‌ و به‌رنامه‌ی تر که‌ مانات ده‌داتێ وه‌ک ناردنی داتا بۆ ئینته‌رنێط.ئه‌م ده‌سته‌ڵاته‌ پێویست نییه‌ بۆ ناردنی داتا بۆ ئینته‌رنێت.</string>
+ <string name="permlab_changeNetworkState">گۆڕینی په‌یوه‌ندی خه‌ت</string>
+ <string name="permdesc_changeNetworkState">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی باری په‌یوه‌ندی تۆڕ.</string>
+ <string name="permlab_changeTetherState">گۆڕینی په‌یوه‌ندی به‌شداریپێکراو</string>
+ <string name="permdesc_changeTetherState">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی باری په‌یوه‌ندی به‌شداریپێکراوی تۆڕ.</string>
+ <string name="permlab_accessWifiState">بینینی په‌یوه‌ندی وایه‌رلێس</string>
+ <string name="permdesc_accessWifiState">ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی زانیاری له‌باره‌ی وایه‌رلێس،وه‌ک ئایا وایه‌رلێس کارده‌کات یان ناوی وایه‌رلیسی په‌یوه‌ندی پێکراو.</string>
+ <string name="permlab_changeWifiState">په‌یوه‌ندی یان پچڕان له‌ وایه‌رلێسه‌وه‌</string>
+ <string name="permdesc_changeWifiState">ڕێگه‌پێدان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردن یان په‌یوه‌ندی پچڕان له‌ ده‌سته‌ڵاتی وایه‌رلێسه‌وه‌ وه‌ گۆڕینی ئامیر بۆ وایه‌رلێس.</string>
+ <string name="permlab_changeWifiMulticastState">ڕێگه‌دان بۆ وایه‌رلێس 2 قبوڵبکات</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌کان بۆ وه‌رگرتنی پاکه‌تی په‌یوه‌ندی بۆ هه‌موو ئامێره‌کان له‌ وایه‌رلێسه‌وه‌ بۆ ناونیشانی دوانی.نه‌ک ته‌نیا بۆ تابلێته‌که‌ت.بۆ زۆر هیزی تر به‌کاردێت نه‌ک ته‌نیا دوانی.</string>
+ <string name="permdesc_changeWifiMulticastState" product="default">ڕێگه‌دان به‌ به‌رنامه‌کان بۆ وه‌رگرتنی پاکه‌تی په‌یوه‌ندی بۆ هه‌موو ئامێره‌کان له‌ وایه‌رلێسه‌وه‌ بۆ ناونیشانی دوانی.نه‌ک ته‌نیا بۆ ئامێره‌که‌ت.بۆ زۆر هیزی تر به‌کاردێت نه‌ک ته‌نیا دوانی.</string>
+ <string name="permlab_bluetoothAdmin">چوونه‌ ناو ڕێکخستنه‌کانی بلوتوس</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێکخستنی بلوتوسی ناوه‌کی تابلێت.وه‌ دۆزینه‌وه‌ و ناساندنی دووره‌ ئامێر.</string>
+ <string name="permdesc_bluetoothAdmin" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێکخستنی بلوتوسی ناوه‌کی مۆبایل.وه‌ دۆزینه‌وه‌ و ناساندنی دووره‌ ئامێر.</string>
+ <string name="permlab_accessWimaxState">په‌یوه‌ندی یان پچڕان له‌ وایماکسه‌وه‌</string>
+ <string name="permdesc_accessWimaxState">ڕێگه‌دان به‌ به‌رنامه‌ بۆ بڕیاردان که‌ی وایماکس کار بکات و زانیاری له‌باره‌ی وایماکس که‌ په‌یوه‌ندی پێوه‌کراوه‌. </string>
+ <string name="permlab_changeWimaxState">گۆڕینی باری وایماکس</string>
+ <string name="permdesc_changeWimaxState" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردنی تابلێت یان پچڕانی تابلێت له‌ وایماکسه‌وه‌.</string>
+ <string name="permdesc_changeWimaxState" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردنی مۆبایل یان پچڕانی مۆبایل له‌ وایماکسه‌وه‌.</string>
+ <string name="permlab_bluetooth">ناساندن له‌گه‌ڵ ئامێری بلوتوس</string>
+ <string name="permdesc_bluetooth" product="tablet">ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی ڕێکخستنی بلوتوس له‌سه‌ر تابلێت، وه‌ک قبوڵکردن و دروستکردنی په‌یوه‌ندی له‌گه‌ڵ ناسرێنراوه‌کان.</string>
+ <string name="permdesc_bluetooth" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی ڕێکخستنی بلوتوس له‌سه‌ر مۆبایله‌که‌ت. وه‌ک قبوڵکردن و دروستکردنی په‌یوه‌ندی له‌گه‌ڵ ناسرێنراوه‌کان.</string>
+ <string name="permlab_nfc">سه‌رپه‌رشتیکردنی په‌یوه‌ندییه‌ نزیکه‌کان.</string>
+ <string name="permdesc_nfc">رێگە بە بەرنامەکە دەدات کە کۆنترۆلی پەیوەندی لەرێگەی Near Field Communicationەوە بکات</string>
+ <string name="permlab_disableKeyguard">ناچالاککردنی داخەری ڕوونما</string>
+ <string name="permdesc_disableKeyguard">ڕێگە بە بەرنامەکە دەدا کە قوفلی دوکمەکان و وشە نهێنیەکەنیان لەکار بخا .بۆ نمونە مۆبایلەکەت لە کاتی هاتنی پەیوەندی ،قوفڵەکە بۆ ماوەیەکی کاتی لەکار دەخا بۆ ئەوەی بتوانی وەڵام بدەیتەوە</string>
+ <string name="permlab_readSyncSettings">خوێندنەوەی زانیاریەکەنی هاوتاکردن</string>
+ <string name="permdesc_readSyncSettings">ڕیگە بە بەرنامەکە دەدا کە زانیاری دەربارەی هاوتاکردن بخوێنێتەوە.بۆ نمونە ئەمە دیاری دەکەت کە ئایا بەرنامەی Pepole لەگەڵ هیچ هەژمارێک هاوتا کراوە یان نە</string>
+ <string name="permlab_writeSyncSettings">هاوتاکردن بکوژێنەوە یان داگیرسێنە</string>
+ <string name="permdesc_writeSyncSettings">ڕێگە بە بەرنامەکە دەدا کە دەستکاری رێکخستنی هاوتاکردن بکات.بۆ نمونە ئەمە دەتوانریت بۆ هاوتاکردنی بەرنامەی pepole لەگەڵ هەژمارێک بەکاربێت</string>
+ <string name="permlab_readSyncStats">خوێندنه‌وه‌ی هاوتاکردنی ئامارکردنه‌کان</string>
+ <string name="permdesc_readSyncStats">ڕێگه‌دان به‌ به‌رنامه‌یه‌ک بۆ هاوتاکردنی ئامار بۆ هه‌ژمارێک، وه‌ک مێژووی هاوتاکردنی ڕووداوه‌کان وه‌ چه‌ند داتا هاوتاکراوه‌. </string>
+ <string name="permlab_sdcardRead" product="nosdcard">خوێندنه‌وه‌ی به‌شه‌کانی ناو بیرگه‌ی USB.</string>
+ <string name="permlab_sdcardRead" product="default">خوێندنه‌وه‌ی پێکهاته‌ی ناو بیرگه‌ی ناوه‌کی</string>
+ <string name="permdesc_sdcardRead" product="nosdcard">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی پێکهاته‌ی ناو بیرگه‌ی USB.</string>
+ <string name="permdesc_sdcardRead" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی پێکهاته‌ی ناو بیرگه‌ی ناوه‌کی.</string>
+ <string name="permlab_sdcardWrite" product="nosdcard">گۆڕین یان سڕینه‌وه‌ی پێکهاته‌ی بیرگه‌ی USB</string>
+ <string name="permlab_sdcardWrite" product="default">گۆڕین یان سڕینه‌وه‌ی پێکهاته‌ی بیرگه‌ی ناوه‌کی</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard">ڕێگه‌دان به‌ به‌رنامه‌ بۆ نوسینی بیرگه‌ی USB.</string>
+ <string name="permdesc_sdcardWrite" product="default">ڕێگه‌دان به‌ به‌رنامه‌ بۆ نوسینی بیرگه‌ی ناوه‌کی.</string>
+ <string name="permlab_readNetworkUsageHistory">خوێندنه‌وه‌ی تۆماری به‌کارهێنانی تۆڕ</string>
+ <string name="permdesc_readNetworkUsageHistory">ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی تۆماری به‌کارهێنانی تۆڕ بۆ تۆڕێکی تایبه‌ت و به‌رنامه‌.</string>
+ <string name="permlab_manageNetworkPolicy">به‌ڕێوه‌بردنی ڕه‌وگه‌ی تۆڕ</string>
+ <string name="permdesc_manageNetworkPolicy">ڕێگه‌دان به‌ به‌رنامه‌ بۆ به‌ڕێوه‌بردنی ڕه‌وگه‌ی تۆڕ و یاسایی تایبه‌تی به‌رنامه‌.</string>
+ <string name="permlab_modifyNetworkAccounting">گۆڕینی به‌کارهێنانی هەژماری تۆڕ</string>
+ <string name="permdesc_modifyNetworkAccounting">ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی به‌کارهێنانی هەژماری تۆڕ.بۆ به‌رنامه‌ی ئاسایی به‌کارنایه‌ت.</string>
+ <string name="permlab_accessNotifications">ده‌سته‌ڵاتی تێبینییه‌کان</string>
+ <string name="permdesc_accessNotifications">ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌سته‌لاتی وه‌رگرتن و کارپێکردن و پاککردنه‌وه‌ی ئاگادارکردنه‌وه‌کان.وه‌ک پۆسته‌کانی به‌رنامه‌کان.</string>
+ <string name="permlab_bindNotificationListenerService">گوێ نەدان بە خزمەتگوزاری بیسەری تێبینییەکان</string>
+ <string name="permdesc_bindNotificationListenerService">ڕێگە بە هەڵگر بە بۆ لەکار خستنی دۆخی ئاست-بەرزی خزمەتگوزاری بیسەری تێبینییەکان. هیچکات پێویست نابێت بۆ بەرنامە ئاساییەکان.</string>
+ <string name="permlab_invokeCarrierSetup">داواکاری ڕێپێدان بۆ بەرنامەی ڕێکبەندەکانی ئۆپەراتۆر</string>
+ <string name="permdesc_invokeCarrierSetup">ڕێگە بە هەڵگر بە بۆ داواکاری ڕێپێدان بۆ بەرنامەی ڕێکبەندەکانی ئۆپەراتۆر. بۆ بەرنامە ئاساییەکان هیچکات پێویست نابێت.</string>
+ <string name="permlab_accessNetworkConditions">گوێدان بە تێبینییەکانی ناو بار و دۆخی تۆڕ</string>
+ <string name="permdesc_accessNetworkConditions">ڕێگە بە بەرنامەیەک بدە بۆ گوێدان بە تێبینییەکانی ناو بار و دۆخی تۆڕ. بۆ بەرنامە ئاساییەکان هیچکات پێویست ناکات.</string>
+ <string name="policylab_limitPassword">دانانی یاسایی وشه‌ی نهێنی</string>
+ <string name="policylab_watchLogin">هەوڵەکانی چالاککردنی پێشانگا تۆماربکە</string>
+ <string name="policydesc_watchLogin" product="tablet">ژمارەی نهێنوشە هەڵەکان تۆمار بکە
+ کە ئەنووسرێن کاتی چالاککردنی پێشانگا، تابلێتەکە دابخە یان هەموو زانیارییەکانی
+ ناو تابلێت بسڕەوە ئەگەر نهێنوشەی هەڵە زۆر جار نووسراوە.</string>
+ <string name="policydesc_watchLogin" product="default">ژمارەی نهێنوشە هەڵەکان تۆمار بکە
+ کە ئەنووسرێن کاتی چالاککردنی پێشانگا، مۆبایلەکە دابخە یان هەموو زانیارییەکانی
+ ناو مۆبایل بسڕەوە ئەگەر نهێنوشەی هەڵە زۆر جار نووسراوە.</string>
+ <string name="policylab_forceLock">قوفڵی سه‌رڕوونما</string>
+ <string name="policydesc_forceLock">چاودێری پێسانگە بکە کە چۆن و کەی دادەخرێت.</string>
+ <string name="policylab_wipeData">سڕینەوەی هەموو دراو</string>
+ <string name="policydesc_wipeData" product="tablet">هەموو زانیارییەکانی تابلێتەکە بسڕەوە بێ نیگەرانی لە ڕێکخستنەوەی داتاکانی کارگە.</string>
+ <string name="policydesc_wipeData" product="default">هەموو زانیارییەکانی مۆبایلەکە بسڕەوە بێ نیگەرانی لە ڕێکخستنەوەی داتاکانی کارگە.</string>
+ <string name="policylab_setGlobalProxy">دانانی پرۆکسی جیهانی بۆ ئامێرەکەت</string>
+ <string name="policylab_encryptedStorage">نهێنیکردنی بیرگە</string>
+ <string name="policydesc_encryptedStorage">پێویستە کە بەرنامەی هەڵگیراو نهێنی بکرێت.</string>
+ <string name="policylab_disableCamera">لەکارخستنی کامیراکان</string>
+ <string name="policydesc_disableCamera">رێگرتن لە بەکارهێنانی هەمو کامیرەکان</string>
+ <string-array name="phoneTypes">
+ <item>ماڵ</item>
+ <item>موبایل</item>
+ <item>کار</item>
+ <item>کاری فاکس</item>
+ <item>ماڵی فاکس</item>
+ <item>پەڕە</item>
+ <item>دیکە</item>
+ <item>دروستکراو</item>
+ </string-array>
+ <string-array name="emailAddressTypes">
+ <item>ماڵ</item>
+ <item>کار</item>
+ <item>دیکە</item>
+ <item>دروستکراو</item>
+ </string-array>
+ <string-array name="postalAddressTypes">
+ <item>ماڵ</item>
+ <item>کار</item>
+ <item>دیکە</item>
+ <item>دروستکراو</item>
+ </string-array>
+ <string-array name="imAddressTypes">
+ <item>ماڵ</item>
+ <item>کار</item>
+ <item>دیکە</item>
+ <item>دروستکراو</item>
+ </string-array>
+ <string-array name="organizationTypes">
+ <item>کار</item>
+ <item>دیکە</item>
+ <item>دروستکراو</item>
+ </string-array>
+ <string-array name="imProtocols">
+ <item>ئامانج</item>
+ <item>Windows Live</item>
+ <item>یاهوو</item>
+ <item>سکایپ</item>
+ <item>QQ</item>
+ <item>Google Talk</item>
+ <item>ICQ</item>
+ <item>Jabber</item>
+ </string-array>
+ <string name="phoneTypeCustom">دروستکراو</string>
+ <string name="phoneTypeHome">ماڵ</string>
+ <string name="phoneTypeMobile">موبایل</string>
+ <string name="phoneTypeWork">کار</string>
+ <string name="phoneTypeFaxWork">کاری فاکس</string>
+ <string name="phoneTypeFaxHome">ماڵی فاکس</string>
+ <string name="phoneTypePager">Pager</string>
+ <string name="phoneTypeOther">دیکە</string>
+ <string name="phoneTypeCallback">Callback</string>
+ <string name="phoneTypeCar">ئۆتۆمۆبیل</string>
+ <string name="phoneTypeCompanyMain">کۆمپانیای سەرەکی</string>
+ <string name="phoneTypeIsdn">ISDN</string>
+ <string name="phoneTypeMain">سەرەکی</string>
+ <string name="phoneTypeOtherFax">فاکسی دیکە</string>
+ <string name="phoneTypeRadio">Radio</string>
+ <string name="phoneTypeTelex">تێلێکس</string>
+ <string name="phoneTypeTtyTdd">TTY TDD</string>
+ <string name="phoneTypeWorkMobile">کاری مۆبایل</string>
+ <string name="phoneTypeWorkPager">Work Pager</string>
+ <string name="phoneTypeAssistant">یاریدەدەر</string>
+ <string name="phoneTypeMms">MMS</string>
+ <string name="eventTypeCustom">تایبەت</string>
+ <string name="eventTypeBirthday">ڕۆژی لە دایک بوون</string>
+ <string name="eventTypeAnniversary">یادکردنەوە</string>
+ <string name="eventTypeOther">جۆری تر</string>
+ <string name="emailTypeCustom">تایبەت</string>
+ <string name="emailTypeHome">ماڵەوە</string>
+ <string name="emailTypeWork">کار</string>
+ <string name="emailTypeOther">جۆری تر</string>
+ <string name="emailTypeMobile">مۆبایل</string>
+ <string name="postalTypeCustom">تایبەت</string>
+ <string name="postalTypeHome">ماڵەوە</string>
+ <string name="postalTypeWork">کار</string>
+ <string name="postalTypeOther">دیکە</string>
+ <string name="imTypeCustom">ده‌ستکرد</string>
+ <string name="imTypeHome">ماڵه‌وه‌</string>
+ <string name="imTypeWork">کار</string>
+ <string name="imTypeOther">دیکە</string>
+ <string name="imProtocolCustom">دەستکرد</string>
+ <string name="imProtocolAim">AIM</string>
+ <string name="imProtocolMsn">Windows Live</string>
+ <string name="imProtocolYahoo">یاهوو</string>
+ <string name="imProtocolSkype">سکایپ</string>
+ <string name="imProtocolQq">QQ</string>
+ <string name="imProtocolGoogleTalk">Hangouts</string>
+ <string name="imProtocolIcq">ICQ</string>
+ <string name="imProtocolJabber">Jabber</string>
+ <string name="imProtocolNetMeeting">NetMeeting</string>
+ <string name="orgTypeWork">کار</string>
+ <string name="orgTypeOther">دیکە</string>
+ <string name="orgTypeCustom">دەستکرد</string>
+ <string name="relationTypeCustom">دەستکرد</string>
+ <string name="relationTypeAssistant">یاریدەدەر</string>
+ <string name="relationTypeBrother">برا</string>
+ <string name="relationTypeChild">مناڵ</string>
+ <string name="relationTypeDomesticPartner">هاوبەشی خۆماڵی</string>
+ <string name="relationTypeFather">باوک</string>
+ <string name="relationTypeFriend">هاوڕێ</string>
+ <string name="relationTypeManager">بەڕێوەبەر</string>
+ <string name="relationTypeMother">دایک</string>
+ <string name="relationTypeParent">باوان</string>
+ <string name="relationTypePartner">هاوڕێ</string>
+ <string name="relationTypeReferredBy">ئاماژەبۆکراوە لەلایەن</string>
+ <string name="relationTypeRelative">خزم</string>
+ <string name="relationTypeSister">خوشک</string>
+ <string name="relationTypeSpouse">هاوسەر</string>
+ <string name="sipAddressTypeCustom">دەستکرد</string>
+ <string name="sipAddressTypeHome">ماڵەوە</string>
+ <string name="sipAddressTypeWork">کار</string>
+ <string name="sipAddressTypeOther">دیکە</string>
+ <string name="quick_contacts_not_available">هیچ به‌رنامه‌یه‌ک نه‌دۆزرایه‌وه‌ بۆ بینینی ئه‌م په‌یوه‌ندییه‌.</string>
+ <string name="keyguard_password_enter_pin_code">نوسینی PIN کۆد</string>
+ <string name="keyguard_password_enter_puk_code">نووسینی PUK لەگەڵ PIN کۆدی نوێ</string>
+ <string name="keyguard_password_enter_puk_prompt">PUK کۆد</string>
+ <string name="keyguard_password_enter_pin_prompt">PIN کۆدی نوێ</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">دەست لێدان بۆ نووسینی تێپه‌ڕوشه‌</font></string>
+ <string name="keyguard_password_enter_password_code">نوسینی تێپەڕە وشە بۆ کردنه‌وه‌</string>
+ <string name="keyguard_password_enter_pin_password_code">PIN بنووسه‌ بۆ کردنه‌وه‌</string>
+ <string name="keyguard_password_wrong_pin_code">کۆدی PIN هەڵەیە.</string>
+ <string name="keyguard_label_text">بۆ کردنه‌وه‌، پەنجە بنێ بە لیست و پاشان 0.</string>
+ <string name="emergency_call_dialog_number_for_display">ژمارەی فریاگوزاری</string>
+ <string name="lockscreen_carrier_default">خزمەتگوزاری نیە.</string>
+ <string name="lockscreen_screen_locked">شاشە قفلدراوە.</string>
+ <string name="lockscreen_instructions_when_pattern_enabled">پەنجە بنێ بە لیست بۆ چالاککردنی یان دانانی تەلەفۆنی فریاگوزاری.</string>
+ <string name="lockscreen_instructions_when_pattern_disabled">پەنجە بنێ بە لیست بۆ کردنەوە.</string>
+ <string name="lockscreen_pattern_instructions">شێوەکە راکێشە بۆ چالاککردن</string>
+ <string name="lockscreen_return_to_call">گەڕانەوە بۆ تەلەفۆن</string>
+ <string name="lockscreen_pattern_correct">ڕاست!</string>
+ <string name="lockscreen_pattern_wrong">دوبارە هەوڵبدەرەوە</string>
+ <string name="lockscreen_password_wrong">دووباره‌ هەوڵ بدەوە</string>
+ <string name="faceunlock_multiple_failures">چالاککردنی قوفڵ بە ڕوخسار هەوڵ زۆر دراوە</string>
+ <string name="lockscreen_missing_sim_message_short">سیمکارتی تیا نیە</string>
+ <string name="lockscreen_missing_sim_message" product="tablet">سیمکارت نیە لە تاتەبژمێر.</string>
+ <string name="lockscreen_missing_sim_message" product="default">سیمکارت نیە لە تەلەفۆن.</string>
+ <string name="lockscreen_missing_sim_instructions">سیمکارتی تیا بکە.</string>
+ <string name="lockscreen_missing_sim_instructions_long">سیمکارتەکە تیایە نیە یان نایخوێنێتەوە. سیمکارتی تێبکە.</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short">سیمکارتەکە بەکارنایەت.</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions">سیمکارتەکە لە کارخرا .\n پەیوەندی بکە بە کۆمپانیای بێ تەلەوە بۆ سیمێکی تر.</string>
+ <string name="emergency_calls_only" msgid="2485604591272668370">ته‌نها په‌یوه‌ندی كتوپڕ</string>
+ <string name="lockscreen_network_locked_message">تۆڕ قوفڵکراوە</string>
+ <string name="lockscreen_sim_puk_locked_message">سیمکارتەکە PUK-قوفڵکراوە.</string>
+ <string name="lockscreen_sim_puk_locked_instructions">بینینی تێبینی بەکارهێنەر یان پەیوەندی بکە بە خزمەتگوزاری یارمەتیدەرەوە.</string>
+ <string name="lockscreen_sim_locked_message">سیمکارتەکە داخراوه‌.</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message">کردنەوەی سیمکارت\u2026</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message">
+ تۆ قوفڵی کێشانەکەت بە هەڵە لێداوە <xliff:g id="number">%d</xliff:g> جار.
+ \n\nدوبارە هەوڵبدەروەە <xliff:g id="number">%d</xliff:g> دوەم.
+    .
+ </string>
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message">
+ بەهەڵە چەند جارێک تێپەڕە وشەت لێداوە <xliff:g id="number">%d</xliff:g> جار.
+ \n\nدوبارە هەوڵبدەرەوە <xliff:g id="number">%d</xliff:g> دوەم.
+    .
+ </string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message">
+ چەند جارێک بە هەڵە PIN نوسیوە <xliff:g id="number">%d</xliff:g> times.
+ \n\nدوبارە هەوڵبدەرەوە <xliff:g id="number">%d</xliff:g> دوەمجار.
+    .
+ </string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet">
+ بەهەڵە هەوڵی چالاککردنی کێشانەکەت داوە بۆ چالاککردن <xliff:g id="number">%d</xliff:g> times.
+ After <xliff:g id="number">%d</xliff:g>زۆر هەوڵدان زیاتر ئەوە پرسیارت لێ ئەکەت بە بەکارهیانی هەژمارەکەت بچیتە ژورەوە.\n\n
+ Try again in <xliff:g id="number">%d</xliff:g> دوەم.
+    .
+ </string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default">
+ بەهەڵە هەوڵی چالاککردنی کێشانەکەت داوە بۆ چالاککردن <xliff:g id="number">%d</xliff:g> times.
+ After <xliff:g id="number">%d</xliff:g>زۆر هەوڵدان زیاتر ئەوە پرسیارت لێ ئەکەت بە بەکارهیانی هەژمارەکەت بچیتە ژورەوە.\n\n
+ Try again in <xliff:g id="number">%d</xliff:g> دوەم.
+    .
+ </string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet">
+ چەند جارێک هەوڵی کردنەوەی تاتەبژمێرەکەت داوە بە‌ەلە <xliff:g id="number">%d</xliff:g> times.
+ After <xliff:g id="number">%d</xliff:g> بەهەڵە لێی بدەیتەوە ئەوە تاتەبژمێرەکەت ئەچێتەوە باری بنەڕەت و هەموو داتاکان و فایلەکان ئەسڕێتەوە.
+    .
+ </string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default">
+ چەند جارێک هەوڵی چالاککردنی تاتەبژمێرەکەت داوە بە‌ەلە <xliff:g id="number">%d</xliff:g> times. After <xliff:g id="number">%d</xliff:g> بەهەڵە لێی بدەیتەوە ئەوە تاتەبژمێرەکەت ئەچێتەوە باری بنەڕەت و هەموو داتاکان و فایلەکان ئەسڕێتەوە.
+ </string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tablet">
+ تۆ بەهەڵە هەوڵت داوە تاتە بژمێرەکە بکەیتەوە <xliff:g id="number">%d</xliff:g> times.
+ Tزۆر هەڵە لێدانی فایلەکان ئەسڕێتەوە بۆ باری بنەڕەتی ئەچێتەوە.
+    .
+ </string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default">
+ بەهەڵە هەوڵت داوە بۆ چالاککردنی تەلەفۆنەکەت <xliff:g id="number">%d</xliff:g> times.
+ تەلەفۆنەکە ئێستا ئەجیتەوە باری بنەڕەتی.
+    .
+ </string>
+ <string name="lockscreen_too_many_failed_attempts_countdown">دوبارە هەوڵبدەرەوە <xliff:g id="number">%d</xliff:g> دووەم.</string>
+ <string name="lockscreen_forgot_pattern_button_text">بیرچونی کێشانەکە?</string>
+ <string name="lockscreen_glogin_forgot_pattern">کردنەوەی هەژمارەکە</string>
+ <string name="lockscreen_glogin_too_many_attempts">زۆر هەوڵت داوە قوفڵە کێشان دانێیت</string>
+ <string name="lockscreen_glogin_instructions">بۆ کردنەوە.بچۆ ژورەوە بە هەژماری Googleەکەت.</string>
+ <string name="lockscreen_glogin_username_hint">ناو(ئیمەیڵ)</string>
+ <string name="lockscreen_glogin_password_hint">تێپەڕەوشە</string>
+ <string name="lockscreen_glogin_submit_button">چونەژورەوە</string>
+ <string name="lockscreen_glogin_invalid_input">ناو لە کارە نیە یان تێپەڕە وشە.</string>
+ <string name="lockscreen_glogin_account_recovery_hint">ناو یان تێپەڕە وشەکەت بیرچوە؟\?\nVisit <b>google.com/هەمار/recovery</b>.</string>
+ <string name="lockscreen_glogin_checking_password">پشکنین\u2026</string>
+ <string name="lockscreen_unlock_label">چالاککردن</string>
+ <string name="lockscreen_sound_on_label">چالاککردنی دەنگ</string>
+ <string name="lockscreen_sound_off_label">ناچالاککردنی دەنگ</string>
+ <string name="lockscreen_access_pattern_start">قوفڵ کێشان دەستی پێکرد</string>
+ <string name="lockscreen_access_pattern_cleared">کێشانەکە پاکرایەوە</string>
+ <string name="lockscreen_access_pattern_cell_added">خانە زیادکرا</string>
+ <string name="lockscreen_access_pattern_detected">کێشانەکە تەواوکرا</string>
+ <string name="lockscreen_access_pattern_area" msgid="">ناوچەی کێشان.</string>
+ <string name="keyguard_accessibility_widget_changed">%1$s. وێدج%2$d of %3$d.</string>
+ <string name="keyguard_accessibility_add_widget">زیادکردنی کورته‌وێنه‌.</string>
+ <string name="keyguard_accessibility_widget_empty_slot">بەتاڵ</string>
+ <string name="keyguard_accessibility_unlock_area_expanded">کردنەوی ناوچە بڵاوکرایەوە.</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed">ناوچەی چالاککردن لەناوچوون.</string>
+ <string name="keyguard_accessibility_widget"><xliff:g id="کورته‌وێنه‌_index">%1$s</xliff:g> widget.</string>
+ <string name="keyguard_accessibility_user_selector">هەڵبژاردەی بەکارهێنەر</string>
+ <string name="keyguard_accessibility_status">ئاست</string>
+ <string name="keyguard_accessibility_camera">کامێرا</string>
+ <string name="keygaurd_accessibility_media_controls">کۆنترۆڵی ڕاگه‌یێنه‌کان</string>
+ <string name="keyguard_accessibility_widget_reorder_start">دوبارە کورته‌وێنه‌ەکە داوابکە.</string>
+ <string name="keyguard_accessibility_widget_reorder_end">داواکردنی وێدجەکان کۆتایهات.</string>
+ <string name="keyguard_accessibility_widget_deleted">کورته‌وێنه‌ <xliff:g id="widget_index">%1$s</xliff:g> سڕایەوە.</string>
+ <string name="keyguard_accessibility_expand_lock_area">بڵاوکردنەوەی ناوچەی کردنەوە.</string>
+ <string name="keyguard_accessibility_slide_unlock">کردنەوە بە لادان.</string>
+ <string name="keyguard_accessibility_pattern_unlock">کردنه‌وه‌ بە گه‌یاندن.</string>
+ <string name="keyguard_accessibility_face_unlock">چالاککردن بە ڕووخسار.</string>
+ <string name="keyguard_accessibility_pin_unlock">کردنەوە بە کۆد.</string>
+ <string name="keyguard_accessibility_password_unlock">کردنەوە بە تێپەڕەوشە.</string>
+ <string name="keyguard_accessibility_pattern_area">ناوچەی کێشان.</string>
+ <string name="keyguard_accessibility_slide_area">ناوچەی لادان.</string>
+ <string name="password_keyboard_label_symbol_key">\?123</string>
+ <string name="password_keyboard_label_alpha_key">ABC</string>
+ <string name="password_keyboard_label_alt_key">ALT</string>
+ <string name="granularity_label_character">کارەکتەر</string>
+ <string name="granularity_label_word">وشە</string>
+ <string name="granularity_label_link">بەستەرە</string>
+ <string name="granularity_label_line">هێڵ</string>
+ <string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
+ <string name="hour_cap_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="PM">%p</xliff:g>"</string>
+ <string name="factorytest_failed">گەڕانەوە بۆ باری ئاسایی سەرنەکەوت</string>
+ <string name="factorytest_not_system">چالاکی بۆ باری بنەڕەتی
+تەنها پاڵپشتی ئەوانە دەکات کە دامەزراون لە سیستەم/بەرنامە.</string>
+ <string name="factorytest_no_action">هیچ گورزەیەک نەدۆرایەوە کە
+ فرمانی تاقیکاری کارگە لە خۆ بگرێت.</string>
+ <string name="factorytest_reboot">دووباره‌ داگیرساندنه‌وه‌</string>
+ <string name="js_dialog_title">پەڕەکە لە \"<xliff:g id="title">%s</xliff:g>\" ئەڵێت:</string>
+ <string name="js_dialog_title_default">جاڤاسکریپت</string>
+ <string name="js_dialog_before_unload_title">دڵنیاکردنەوەی ڕێدۆزەر</string>
+ <string name="js_dialog_before_unload_positive_button">جێهێشتنی ئەم پەڕەیە</string>
+ <string name="js_dialog_before_unload_negative_button">مانەوە لەسەر ئەم پەڕەیە</string>
+ <string name="js_dialog_before_unload"><xliff:g id="message">%s</xliff:g>\n\nتۆى دڵنيان تۆ دەوێتان تا دوور لە ئەمە لاپەڕەوە بەناودا بڕوات؟ ?</string>
+ <string name="save_password_label">دلنیاکردنەوە</string>
+ <string name="double_tap_toast">سەر: دوجار -لێدان بۆ زوم نزیک و دەرەوە.</string>
+ <string name="autofill_this_form">خۆکارپڕ</string>
+ <string name="setup_autofill">دانانی خۆکارپڕ</string>
+ <string name="autofill_address_name_separator">\u0020</string>
+ <string name="autofill_address_summary_name_format">$1$2$3</string>
+ <string name="autofill_address_summary_separator">,\u0020</string>
+ <string name="autofill_address_summary_format">$1$2$3</string>
+ <string name="autofill_attention_ignored_re">سەرنجدان|attn</string>
+ <string name="autofill_region_ignored_re">province|region|other<!-- es -->|provincia<!-- pt-BR, pt-PT -->|bairro|suburb</string>
+ <string name="autofill_company_re">company|business|organization|organisation|department<!-- de-DE -->|firma|firmenname<!-- es -->|empresa<!-- fr-FR -->|societe|société<!-- it-IT -->|ragione.?sociale<!-- ja-JP -->|会社<!-- ru -->|название.?компании<!-- zh-CN -->|单位|公司</string>
+ <string name="autofill_address_line_1_re">address.?line|address1|addr1|street<!-- de-DE -->|strasse|straße|hausnummer|housenumber<!-- en-GB -->|house.?name<!-- es -->|direccion|dirección<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所1<!-- pt-BR, pt-PT -->|morada|endereço<!-- ru -->|Адрес<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_1_label_re">ناونیشان<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_2_re">ناونیشان.?line2|address2|addr2|street|suite|unit<!-- de-DE -->|adresszusatz|ergänzende.?angaben<!-- es -->|direccion2|colonia|adicional<!-- fr-FR -->|addresssuppl|complementnom|appartement<!-- it-IT -->|indirizzo2<!-- ja-JP -->|住所2</string>
+ <string name="autofill_address_line_3_re">ناونیشان.?line3|address3|addr3|street|line3<!-- es -->|municipio<!-- fr-FR -->|batiment|residence<!-- it-IT -->|indirizzo3</string>
+ <string name="autofill_country_re">وڵات|ناوچه‌<!-- ja-JP -->|国<!-- zh-CN -->|国家</string>
+ <string name="autofill_zip_code_re">zip|postal|post code|pcode|^1z$<!-- de-DE -->|postleitzahl<!-- es -->|cp<!-- fr-FR -->|cdp<!-- it-IT -->|cap<!-- ja-JP -->|郵便番号<!-- pt-BR, pt-PT -->|codigo|codpos|cep<!-- ru -->|Почтовый.?Индекс<!--zh-CN -->|邮政编码|邮编<!-- zh-TW -->|郵遞區號</string>
+ <string name="autofill_zip_4_re">zip|^-$|post2<!-- pt-BR, pt-PT -->|codpos2</string>
+ <string name="autofill_city_re">city|town<!-- de-DE -->|ort|stadt<!-- en-AU -->|suburb<!-- es -->|ciudad|provincia|localidad|poblacion<!-- fr-FR -->|ville|commune<!-- it-IT -->|localita<!-- ja-JP -->|市区町村<!-- pt-BR, pt-PT -->|cidade<!-- ru -->|Город<!-- zh-CN -->|市<!-- zh-TW -->|分區</string>
+ <string name="autofill_state_re">state|county|region|province<!-- de-DE -->|land<!-- en-UK -->|county|principality<!-- ja-JP -->|都道府県<!-- pt-BR, pt-PT -->|estado|provincia<!-- ru -->|область<!-- zh-CN -->|省<!-- zh-TW -->|地區</string>
+ <string name="autofill_address_type_same_as_re">وەکو هەمان</string>
+ <string name="autofill_address_type_use_my_re">بەکارهێنانی</string>
+ <string name="autofill_billing_designator_re">گەڵاڵە</string>
+ <string name="autofill_shipping_designator_re">ناردن</string>
+ <string name="autofill_email_re">e.?mail<!-- ja-JP -->|メールアドレス<!-- ru -->|Электронной.?Почты<!-- zh-CN -->|邮件|邮箱<!-- zh-TW -->|電郵地址</string>
+ <string name="autofill_username_re">user.?name|user.?id<!-- de-DE -->|vollständiger.?name<!-- zh-CN -->|用户名</string>
+ <string name="autofill_name_re">^name|full.?name|your.?name|customer.?name|firstandlastname<!-- es -->|nombre.*y.*apellidos<!-- fr-FR -->|^nom<!-- ja-JP -->|お名前|氏名<!-- pt-BR, pt-PT -->|^nome<!-- zh-CN -->|姓名</string>
+ <string name="autofill_name_specific_re">^name<!-- fr-FR -->|^nom<!-- pt-BR, pt-PT -->|^nome</string>
+ <string name="autofill_first_name_re">irst.*name|initials|fname|first$<!-- de-DE -->|vorname<!-- es -->|nombre<!-- fr-FR -->|forename|prénom|prenom<!-- ja-JP -->|名<!-- pt-BR, pt-PT -->|nome<!-- ru -->|Имя</string>
+ <string name="autofill_middle_initial_re">ةاوەند.*initial|m\\.i\\.|mi$</string>
+ <string name="autofill_middle_name_re">ناوی ناوەنجی.*ناو|mname|ناوەند$<!-- es -->|apellido.?materno|کۆتای ناو</string>
+ <string name="autofill_last_name_re">last.*name|lname|surname|last$<!-- de-DE -->|nachname<!-- es -->|apellidos<!-- fr-FR -->|famille|^nom<!-- it-IT -->|cognome<!-- ja-JP -->|姓<!-- pt-BR, pt-PT -->|morada|apelidos|surename|sobrenome<!-- ru -->|Фамилия</string>
+ <string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfono<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string>
+ <string name="autofill_area_code_re">ناوچە.*کۆد|acode|ناوچە</string>
+ <string name="autofill_phone_prefix_re">prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
+ <string name="autofill_phone_suffix_re">پاشگر</string>
+ <string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string>
+ <string name="autofill_name_on_card_re">card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|karteninhaber<!-- es -->|nombre.*tarjeta<!-- fr-FR -->|nom.*carte<!-- it-IT -->|nome.*cart<!-- ja-JP -->|名前<!-- ru -->|Имя.*карты<!-- zh-CN -->|信用卡开户名|开户名|持卡人姓名<!-- zh-TW -->|持卡人姓名</string>
+ <string name="autofill_name_on_card_contextual_re">ناو</string>
+ <string name="autofill_card_cvc_re">گونجاندن|کارتidentification|cvn|security code|cvv code|cvc</string>
+ <string name="autofill_card_number_re">ژمارە|کارت.?#|card.?no|ccnum<!-- de-DE -->|nummer<!-- es -->|credito|numero|número<!-- fr-FR -->|numéro<!-- ja-JP -->|カード番号<!-- ru -->|Номер.*карты<!-- zh-CN -->|信用卡号|信用卡号码<!-- zh-TW -->|信用卡卡號</string>
+ <string name="autofill_expiration_month_re">بەسەرچوون|exp.*مانگ|نمونە.*ڕۆژ|ccmonth<!-- de-DE -->|gueltig|gültig|monat<!-- es -->|fecha<!-- fr-FR -->|date.*exp<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|لەکارە<!-- ru -->|Срок действия карты<!-- zh-CN -->|月</string>
+ <string name="autofill_expiration_date_re">exp|^/|year<!-- de-DE -->|ablaufdatum|gueltig|gültig|yahr<!-- es -->|fecha<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|年|有效期</string>
+ <string name="autofill_card_ignored_re">^کارت</string>
+ <string name="autofill_fax_re">فاکس<!-- fr-FR -->|télécopie|telecopie<!-- ja-JP -->|ファックス<!-- ru -->|факс<!-- zh-CN -->|传真<!-- zh-TW -->|傳真</string>
+ <string name="autofill_country_code_re">وڵات.*کۆد|ccode|_cc</string>
+ <string name="autofill_area_code_notext_re">^\\($</string>
+ <string name="autofill_phone_prefix_separator_re">^-$|^\\)$</string>
+ <string name="autofill_phone_suffix_separator_re">^-$</string>
+ <string name="autofill_province">پارێزگا</string>
+ <string name="autofill_postal_code">کۆدی پۆستان</string>
+ <string name="autofill_state">دەوڵەت</string>
+ <string name="autofill_zip_code">کۆدی پۆستە</string>
+ <string name="autofill_county">وڵات</string>
+ <string name="autofill_island">دوورگە</string>
+ <string name="autofill_district">ناوچە</string>
+ <string name="autofill_department">بەش</string>
+ <string name="autofill_prefecture">ولایەت</string>
+ <string name="autofill_parish">پاریس</string>
+ <string name="autofill_area">ناوچە</string>
+ <string name="autofill_emirate">میرنشین</string>
+ <string name="permlab_readHistoryBookmarks">خوێندنەوەی وێبنیشانکەرەکە و مێژوو</string>
+ <string name="permdesc_readHistoryBookmarks">رێگە بە بەرنامە بە بۆ خوێندنەوەی
+ مێژووی هەموو ئەو وێبپەڕانەی کە وێبگەڕەکەت سەردانی کردوون، لەگەڵ هەموو وێبپەڕە
+ هیماکراوەکان. تێبینی: ئەم ڕێدانە لەوە ئەچێ پابەند نەبێت بە وێبگەڕە یاریدەدەرەکانەوە
+ یان ئەو بەرنامانەی کە توانایی گەڕانی وێبیان هەبێت.</string>
+ <string name="permlab_writeHistoryBookmarks">نوسینی په‌رتوکنیشانکه‌ری وێبگه‌ر و مێژو</string>
+ <string name="permlab_setAlarm">دانانی زەنگ</string>
+ <string name="permlab_addVoicemail">زیادکردنی نامەی دەنگی</string>
+ <string name="permdesc_addVoicemail">ڕێگەدان بە بەرنامەکە بۆ زیادکردنی نامەکان
+بۆ سندوقی دەنگە نامە.</string>
+ <string name="permlab_writeGeolocationPermissions">لابردنی تازەکردنەوەی شوێنی جوگرافی وێبگەر</string>
+ <string name="permdesc_writeGeolocationPermissions">ڕێ دەدات بە بەرنامە تا بگۆڕێت
+
+ڕێگەپێدانى شوێنی جوگرافی براوزە. بەرنامەى ڤایرۆسی
+
+لەوانەيە ئەمە بەكار بهێنێت تا ڕێ بدات بە بۆ ناردنى وێبسايتى زانياريى شوێن هەرەمەكى.</string>
+ <string name="save_password_message">ئایا دەتەوێت وێبگەڕەکەت ئەم نهێنووشەیە بە یادت بهێنێتەوە؟</string>
+ <string name="save_password_notnow">ئێستا نا</string>
+ <string name="save_password_remember">وەبیرهاتنەوە</string>
+ <string name="save_password_never">هەرگیز</string>
+ <string name="open_permission_deny">تۆ ڕێگەت نیە بۆ چالاککردنی ئەم پەڕەیە.</string>
+ <string name="text_copied">دەقەکە لەبەریگیرایەوە بۆ پارێزەر.</string>
+ <string name="more_item_label">زیاتر</string>
+ <string name="prepend_shortcut_label">پێڕست+</string>
+ <string name="menu_space_shortcut_label">بۆشایی</string>
+ <string name="menu_enter_shortcut_label">دانان</string>
+ <string name="menu_delete_shortcut_label">سڕینەوە</string>
+ <string name="search_go">گەڕان</string>
+ <string name="searchview_description_search">گەڕان</string>
+ <string name="searchview_description_query">داوای گەڕان</string>
+ <string name="searchview_description_clear">پاکردنەوەی داوا</string>
+ <string name="searchview_description_submit">ناردنی داوا</string>
+ <string name="searchview_description_voice">گەڕانی دەنگی</string>
+ <string name="enable_explore_by_touch_warning_title">چالاککردنی گەڕان بە دەستلێدان</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet">
+ <xliff:g id="accessibility_service_name">%1$s</xliff:g>بوێ تا لەلايەن دەست لێدان سەرنج بدات.
+
+كاتێك لەلايەن دەست لێدان بەكار دەخرێت، تۆ دەتوانن ببيستن يان باسكردنى دەبينن ئەوەى كەى لەژێر
+
+پەنجەت يان نيشانە ئەنجام دەدات تا لەگەڵ حەبەكە كار لە يەك بكەن.</string>
+ <string name="enable_explore_by_touch_warning_message" product="default">
+ <xliff:g id="accessibility_service_name">%1$s</xliff:g>بوێ تا لەلايەن دەست لێدان سەرنج بدات.
+
+كاتێك لەلايەن دەست لێدان بەكار دەخرێت، تۆ دەتوانن ببيستن يان باسكردنى دەبينن ئەوەى كەى لەژێر
+
+پەنجەت يان نيشانە ئەنجام دەدات تا لەگەڵ حەبەكە كار لە يەك بكەن.</string>
+ <string name="oneMonthDurationPast">1 مانگ لەمەوپێش</string>
+ <string name="beforeOneMonthDurationPast">لە پێش 1 مانگ لەمەپێش</string>
+ <string name="last_month">مانگی دوایین</string>
+ <string name="older">بەتەمەنتر</string>
+ <string name="preposition_for_date">لەسەر<xliff:g id="date" example="May 29">%s</xliff:g></string>
+ <string name="preposition_for_time">لەسەر<xliff:g id="time" example="2:33 am">%s</xliff:g></string>
+ <string name="preposition_for_year">لەناو<xliff:g id="year" example="2003">%s</xliff:g></string>
+ <string name="day">رۆژ</string>
+ <string name="days">رۆژەکان</string>
+ <string name="hour">کاژێر</string>
+ <string name="hours">کاژێرەکان</string>
+ <string name="minute">خولەک</string>
+ <string name="minutes">خولەکەکان</string>
+ <string name="second">چرکە</string>
+ <string name="seconds">چرکەکان</string>
+ <string name="week">هەفتە</string>
+ <string name="weeks">هەفتەکان</string>
+ <string name="year">ساڵ</string>
+ <string name="years">ساڵەکان</string>
+ <string name="VideoView_error_title">کێشەی ڤیدیۆ</string>
+ <string name="VideoView_error_text_invalid_progressive_playback">ڤیدیۆکە لەکارە نیە لەسەر ئەم ئامێرە.</string>
+ <string name="VideoView_error_text_unknown">ناتوانرێت ئەم ڤیدیۆیە لێدرێت</string>
+ <string name="VideoView_error_button">باشه‌</string>
+ <string name="relative_time">"<xliff:g id="date" example="4 hours ago">%1$s</xliff:g>, <xliff:g id="time" example="11:00 am">%2$s</xliff:g>"</string>
+ <string name="noon">"نیوەڕۆ"</string>
+ <string name="Noon">"نیوەڕۆ"</string>
+ <string name="midnight">"نیوەشەو"</string>
+ <string name="Midnight">"نیوەشەو"</string>
+ <string name="elapsed_time_short_format_mm_ss"><xliff:g id="minutes" example="1">%1$02d</xliff:g>:<xliff:g id="seconds" example="23">%2$02d</xliff:g></string>
+ <string name="elapsed_time_short_format_h_mm_ss"><xliff:g id="hours" example="1">%1$d</xliff:g>:<xliff:g id="minutes" example="43">%2$02d</xliff:g>:<xliff:g id="seconds" example="33">%3$02d</xliff:g></string>
+ <string name="selectAll">دیاریکردنی هەموو</string>
+ <string name="cut">بڕین</string>
+ <string name="copy">لەبەرگرتنەوە</string>
+ <string name="paste">لكاندن</string>
+ <string name="replace">لەبریدانان\u2026</string>
+ <string name="delete">سڕینه‌وه‌</string>
+ <string name="copyUrl">لەبەرگرتنەوەURL</string>
+ <string name="selectTextMode">هەڵبژاردنی دەق</string>
+ <string name="textSelectionCABTitle">دەقی دیاریکراو</string>
+ <string name="addToDictionary">زیادبکە بۆ فەرهەنگ</string>
+ <string name="deleteText">سڕینه‌وه‌</string>
+ <string name="inputMethod">تێكردن ڕێگە</string>
+ <string name="editTextMenuTitle">چالاکی دەق</string>
+ <string name="low_internal_storage_view_title">بیرگەی بۆشایی خەریکە نامێنێت</string>
+ <string name="low_internal_storage_view_text">هەمان کرداری سیستەم لەوانەیە ئیش نەکات</string>
+ <string name="app_running_notification_title"><xliff:g id="app_name">%1$s</xliff:g>
+ لە کارە</string>
+ <string name="app_running_notification_text">دەستلێدان بۆ زانیاری زیاتر
+یان بەرنامەکە بوەستێنە.</string>
+ <string name="ok">باشه‌</string>
+ <string name="cancel">هەڵوەشاندنەوە</string>
+ <string name="yes">باشه‌</string>
+ <string name="no">هەڵوەشاندنەوە</string>
+ <string name="dialog_alert_title">ئاگاداری</string>
+ <string name="loading">دامەزراندنی\u2026</string>
+ <string name="capital_on">چالاککردن</string>
+ <string name="capital_off">کووژاوە</string>
+ <string name="whichApplication">تەواوکردنی بەکارهێنانی چالاکیەکە</string>
+ <string name="alwaysUse">بەکارهێنانی بنەڕەت بۆ ئەم چالاکیە.</string>
+ <string name="clearDefaultHintMsg">پاکردنەوەی بنەڕەت لە ڕێکخستنی سیستەم وgt; Apps وgt; دابەزی.</string>
+ <string name="chooseActivity">چالاکیەک هەڵبژێرە</string>
+ <string name="chooseUsbActivity">هەڵبژاردنی بەرنامەیک بۆ ئامێری USB</string>
+ <string name="noApplications">‌هیچ بەرنامەیەک ناتوانێت ڕۆڵی ئەم چالاکیە ببینێت.</string>
+ <string name="aerr_application">بەداخەوە, <xliff:g id="application">%1$s</xliff:g>وەستا.</string>
+ <string name="aerr_process">بەداخەوە پرۆسەکە <xliff:g id="process">%1$s</xliff:g> وەستا.</string>
+ <string name="anr_activity_application"><xliff:g id="بەرنامە">%2$s</xliff:g> وەڵام نادانتەوە.\n\nئەتەوێت دایخەیت?</string>
+ <string name="anr_activity_process">چالاکی<xliff:g id="activity">%1$s</xliff:g> وەڵام ناداتەوە.\n\nئەتەوێت دایخەیت?</string>
+ <string name="anr_application_process"><xliff:g id="application">%1$s</xliff:g> وەڵام ناداتەوە ئەتەوێت دایخەیت?</string>
+ <string name="anr_process">پرۆسەکە<xliff:g id="پرۆسەکە">%1$s</xliff:g>وەڵام نادرێتەوە .\n\nئەتەوێت دایخەیت?</string>
+ <string name="force_close">باشه‌</string>
+ <string name="report">ڕاپۆرت</string>
+ <string name="wait">چاوەڕێ</string>
+ <string name="webpage_unresponsive">ئەم پەڕەیە کارا نەماوە.\n\nئایا دەتەوێ دایبخەی؟</string>
+ <string name="launch_warning_title">بەرنامە گواسترایەوە</string>
+ <string name="launch_warning_replace"><xliff:g id="app_name">%1$s</xliff:g> ئێستا له‌کاره‌.</string>
+ <string name="launch_warning_original"><xliff:g id="app_name">%1$s</xliff:g> لە بنەڕەتدا دەستپێکرابوو.</string>
+ <string name="screen_compat_mode_scale">پێوانە</string>
+ <string name="screen_compat_mode_show">هەمیشە پیشانبدە</string>
+ <string name="screen_compat_mode_hint">سەر لەنوێ ئەمە چالاک بکەوە لە ڕێکبەندەکانی سیستەم وgt; بەرنامەکان وgt; دابەزێندراوەکان.</string>
+ <string name="smv_application">بەرنامەی <xliff:g id="application">%1$s</xliff:g>
+ (ئەرکی <xliff:g id="process">%2$s</xliff:g>) بە شێوەی خۆسەپاو لە دۆخێکی دژواری پاراستن سەرپێچی کردووە.</string>
+ <string name="smv_process">ئەرکی <xliff:g id="process">%1$s</xliff:g> has
+ بە شێوەی خۆسەپاو لە دۆخێکی دژواری پاراستن سەرپێچی کردووە.</string>
+ <string name="android_upgrading_title">ئەندرۆید لە نوێکاریدایە\u2026</string>
+ <string name="android_upgrading_apk">باشینەسازی بەرنامە
+ <xliff:g id="number" example="123">%1$d</xliff:g> ی
+ <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
+ <string name="android_upgrading_starting_apps">دەستپێکردنی بەرنامەکان.</string>
+ <string name="android_upgrading_complete">تەواوبوونی بووت.</string>
+ <string name="heavy_weight_notification"><xliff:g id="app">%1$s</xliff:g> کارکردن</string>
+ <string name="heavy_weight_notification_detail">لێدە بۆ گۆڕین بۆ بەرنامە</string>
+ <string name="heavy_weight_switcher_title">گۆڕینی بەرنامەکان؟</string>
+ <string name="heavy_weight_switcher_text">بەرنامەیەکی دیکە لە کارادایە
+ کە ئەبێ بوەستێندرێت پێش ئەوەی کە دانەیەکی نوێ دەستپێبکەیت.</string>
+ <string name="old_app_action">گەڕانەوە بۆ <xliff:g id="old_app">%1$s</xliff:g></string>
+ <string name="old_app_description">بەرنامەی نوێ دەست پێ مەکە.</string>
+ <string name="new_app_action">دەستپێکردنی <xliff:g id="old_app">%1$s</xliff:g></string>
+ <string name="new_app_description">بەرنامە کۆنەکە بوەستێنە بێ پاشەکەوتکردن.</string>
+ <string name="sendText">فرمانێک هەڵبژێرە بۆ نووسراوە</string>
+ <string name="volume_ringtone">قەبارەی دەنگی زەنگ لێدەر</string>
+ <string name="volume_music">ده‌نگی ڕاگه‌یێنه‌کان</string>
+ <string name="volume_music_hint_playing_through_bluetooth">لێدان لەڕێگەی بلوتوسەوە</string>
+ <string name="volume_music_hint_silent_ringtone_selected">دانانی زەنگی بێدەنگ دانرا</string>
+ <string name="volume_call">دەنگی تەلەفۆنی هاتوو</string>
+ <string name="volume_bluetooth_call">دەنگی تەلەفۆن لە ڕیگەی بلوتوسەوە</string>
+ <string name="volume_alarm">ده‌نگی بیرخه‌ره‌وه‌</string>
+ <string name="volume_notification">ده‌نگی تێبینی</string>
+ <string name="volume_unknown">دەنگ</string>
+ <string name="volume_icon_description_bluetooth">ده‌نگی بلوتوس</string>
+ <string name="volume_icon_description_ringer">دەنگی زەنگ</string>
+ <string name="volume_icon_description_incall">دەنگی تەلەفۆن</string>
+ <string name="volume_icon_description_media">ده‌نگی ڕاگه‌یێنه‌کان</string>
+ <string name="volume_icon_description_notification">ده‌نگی تێبینی</string>
+ <string name="ringtone_default">زەنگی بنەڕەتی</string>
+ <string name="ringtone_default_with_actual">زەنگی بنەڕەتی (<xliff:g id="actual_ringtone">%1$s</xliff:g>)</string>
+ <string name="ringtone_silent">هیچ</string>
+ <string name="ringtone_picker_title">دەنگی زەنگ</string>
+ <string name="ringtone_unknown">زەنگی نەناسراو</string>
+ <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
+ <string name="wifi_watchdog_network_disabled">ناتوانرێت پەیوەستبکرێت بە Wi-Fiەوە</string>
+ <string name="wifi_watchdog_network_disabled_detailed">هێڵی \u0020 ئینته‌رنێتێکی لاوازی هه‌یه‌.</string>
+ <string name="wifi_p2p_dialog_title">Wi-Fi ڕاستەوخۆ</string>
+ <string name="wifi_p2p_turnon_message">دەستپێکردنی Wi-Fi. ئەمە Wi-Fi /هۆتسپۆت ئەکوژێنێتەوە.</string>
+ <string name="wifi_p2p_failed_message">ناتوانرێت Wi-Fi یەکسەر بکەوێتە کار.</string>
+ <string name="wifi_p2p_enabled_notification_title">Wi-Fi ڕاستەوخۆ لە کارە</string>
+ <string name="wifi_p2p_enabled_notification_message">سوین بۆ ڕێکخستن</string>
+ <string name="accept">پەسەند کردن</string>
+ <string name="decline">ڕەتکردنەوە</string>
+ <string name="wifi_p2p_invitation_sent_title">بانگەشەکردنەکە نێردرا</string>
+ <string name="wifi_p2p_invitation_to_connect_title">بانگەشەکردن بۆ پەیوەندکردن</string>
+ <string name="wifi_p2p_from_message">لە: </string>
+ <string name="wifi_p2p_to_message">بۆ: </string>
+ <string name="wifi_p2p_enter_pin_message">PINی پێویست بنووسە: </string>
+ <string name="wifi_p2p_show_pin_message">PIN: </string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet">تابلێت بۆ ماوەی کاتی پەیوەندی Wi-Fi ئەپچڕێنێت کاتێک بەستراوەتەوە بە <xliff:g id="device_name">%1$s</xliff:g></string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default">تەلەفۆن بۆ ماوەی کاتی پەیوەندی Wi-Fi ئەپچڕێنێت کاتێک بەستراوەتەوە بە <xliff:g id="device_name">%1$s</xliff:g></string>
+ <string name="select_character">تێخستنی نووسە</string>
+ <string name="sms_control_title">ناردنی کورتە نامە</string>
+ <string name="sms_control_message">وlt;bوgt;<xliff:g id="app_name">%1$s</xliff:g>وlt;/bوgt; خەریکە ژمارەیەکی زۆر کورتە نامە دەنێرێت. ئایا دەتەوێت ڕێگە بەم بەرنامە بدەیت بۆ ناردنی کورتەنامەکان؟</string>
+ <string name="sms_control_yes">رێدان</string>
+ <string name="sms_control_no">نکوڵی</string>
+ <string name="sms_short_code_confirm_message">وlt;bوgt;<xliff:g id="app_name">%1$s</xliff:g>وlt;/bوgt; داخوازی ناردنی کورتە نامەی بۆ وlt;bوgt;<xliff:g id="dest_address">%2$s</xliff:g>وlt;/bوgt;.</string>
+ <string name="sms_short_code_confirm_allow">ناردن</string>
+ <string name="sms_short_code_confirm_deny">هەڵوەشاندنەوە</string>
+ <string name="sms_short_code_remember_choice">بیرم بهێنەوە هەڵبژاردەکەم</string>
+ <string name="sms_short_code_remember_undo_instruction">ئەتوانی ئەمە دواتر بگۆڕیت لە ڕێکخستن\u00A0وgt;\u00A0Apps\"</string>
+ <string name="sms_short_code_confirm_always_allow">هەمیشە ڕێگە بدە</string>
+ <string name="sms_short_code_confirm_never_allow">هەرگیز ڕێگە مەدە</string>
+ <string name="sim_removed_title">سیمکارتەکە دەرکرا</string>
+ <string name="sim_done_button">ئه‌نجام درا</string>
+ <string name="sim_added_title">سیمکارتەکە زیادکرا</string>
+ <string name="sim_restart_button">لەنۆکردنەوە</string>
+ <string name="time_picker_dialog_title">دیاریکردنی کات</string>
+ <string name="date_picker_dialog_title">دیاریکردنی ڕۆژ</string>
+ <string name="date_time_set">دانان</string>
+ <string name="date_time_done">کراو</string>
+ <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff33b5e5">تازە: </font></string>
+ <string name="perms_description_app">ئامادەکرا لەلایەن <xliff:g id="app_name">%1$s</xliff:g>.</string>
+ <string name="no_permissions">هیچ یارمەتیەک داوانەکراوە</string>
+ <string name="perm_costs_money">ئەمە پێ ئەچێت پارەت لێبسێنێت</string>
+ <string name="usb_storage_activity_title">بارستەی USB بیرگە</string>
+ <string name="usb_storage_title">USB په‌یوه‌ست کرا</string>
+ <string name="usb_storage_message" product="nosdcard">تۆ بەستراویتەوە بە کۆمپیوتەرەکەت بە USB. دوگمەی خوارەوە لێدە ئەگەر تۆ دەتەوێت فیلەکانت کۆپی بکەی لە نێوان کۆمپیوتەر و بیرگەی USB ئەندرۆیدەکەت.</string>
+ <string name="usb_storage_message" product="default">تۆ بەستراویتەوە بە کۆمپیوتەرەکەت بە USB. دوگمەی خوارەوە لێدە ئەگەر تۆ دەتەوێت فیلەکانت کۆپی بکەی لە نێوان کۆمپیوتەر و بیرگەی هەڵگرتنی ئەندرۆیدەکەت.</string>
+ <string name="usb_storage_button_mount">هەڵکردنی بیرگه‌ی USB</string>
+ <string name="usb_storage_error_message" product="nosdcard">هەڵەیەک هەیە لە بەکار هێنانی بیرگەی USB بۆ بیرگه‌ی USB.</string>
+ <string name="usb_storage_error_message" product="default">هەڵەیەک هەیە لە بەکار هێنانی بیرگەی هەڵگرتنی بۆ بیرگه‌ی USB.</string>
+ <string name="usb_storage_notification_title">USB بەسترایەوە</string>
+ <string name="usb_storage_notification_message">دەست لێدە بۆ کۆپی کردنی فایلەکان بۆ/لە ناو کۆمپیوتەرەکەتدا.</string>
+ <string name="usb_storage_stop_notification_title">کوژاندنەوەی بیرگه‌ی USB</string>
+ <string name="usb_storage_stop_notification_message">دەست لێدە بۆ کوژاندنەوەی بیرگه‌ی USB.</string>
+ <string name="usb_storage_stop_title">بیرگەی USB لە کارادایە</string>
+ <string name="usb_storage_stop_message" product="nosdcard">پێش ئەوەی بیرگەی USB بکووژێنیتەوە، بیرگەی USB ئەندرۆیدەکەت لە ناو کۆمپیوتەرەکەت (\"بهێنەدەر\") دەربکێشە.</string>
+ <string name="usb_storage_stop_message" product="default">پێش ئەوەی بیرگەی USB بکووژێنیتەوە، بیرگەی کارتی هەڵگرتنی ئەندرۆیدەکەت لە ناو کۆمپیوتەرەکەت (\"بهێنەدەر\") دەربکێشە.</string>
+ <string name="usb_storage_stop_button_mount">کوژاندنەوەی کۆگای USB</string>
+ <string name="usb_storage_stop_error_message">هەڵەیەک ڕوویدا کاتی کووژاندنەوەی بیرگه‌ی USB. بزانە بیرگەی USB و هەڵگرتنی دەرهێنراون، پاشان دووبارە هەوڵبدەوە.</string>
+ <string name="dlg_confirm_kill_storage_users_title">هەڵکردنی کۆگای USB</string>
+ <string name="dlg_confirm_kill_storage_users_text">ئەگەر بیرگه‌ی USB هەڵبکەیت، هەندێک بەرنامە کە لە ئێستادا بەکاریان ئەهێنی ئەوێستن و لەوە ئەچێ بەردەستیش نەبن تاکو بیرگه‌ی USB دەکوژێنیتەوە.</string>
+ <string name="dlg_error_title">سەرکەوتو نەبوو USB فرمانی</string>
+ <string name="dlg_ok">باشه‌</string>
+ <string name="usb_accessory_notification_title">USB په‌یوه‌ست کرا وەک یاریدەدەری</string>
+ <string name="adb_active_notification_title">‌هەڵەدۆزینەوەی USB بەستراوەتەوە</string>
+ <string name="adb_active_notification_message">دەست لێدە بۆ ناچالاککردنی هەڵەدۆزینەوەی USB.</string>
+ <string name="hardware">رەقەکاڵا</string>
+ <string name="select_keyboard_layout_notification_title">چۆری تەختەکلیل دیاریبکە</string>
+ <string name="select_keyboard_layout_notification_message">پەنجەی پێدا بنێ بۆ دیاریکردنی تەختەکلیل.</string>
+ <string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="candidates_style"><u>دەستنیشانکراوەکان</u></string>
+ <string name="ext_media_status_checking">پشکنین\u2026</string>
+ <string name="activity_list_empty">هیچ چلاکییەکی لەیەک چوو نەدۆزرایەوە.</string>
+ <string name="permlab_route_media_output">ڕێپیشاندەری بەرهەمی میدیا بە</string>
+ <string name="permdesc_route_media_output">ڕێگە بە بەرنامەیەک بدە تاکو ڕێپیشاندەری بەرهەمی میدیا بکات بۆ دیکەی ئامێرە دەرەکییەکان.</string>
+ <string name="tutorial_double_tap_to_zoom_message_short">دووجار دەست لێدە بۆ چاودێری گەورەکردنەوە</string>
+ <string name="gadget_host_error_inflating">ناتوانرێت کورتە وێنۆچک‌ زیادبکرێت.</string>
+ <string name="ime_action_go">بڕۆ</string>
+ <string name="ime_action_search">گه‌ڕان</string>
+ <string name="ime_action_send">ناردن</string>
+ <string name="ime_action_next">دواتر</string>
+ <string name="ime_action_done">کراو</string>
+ <string name="ime_action_previous">پێشوو</string>
+ <string name="ime_action_default">بەجێهێنان</string>
+ <string name="dial_number_using">ژمارە بگرە\nبە بەکارهێنانی <xliff:g id="number" example="555">%s</xliff:g></string>
+ <string name="create_contact_using">دروستکردنی ناو\nبەهۆی <xliff:g id="number" example="555">%s</xliff:g></string>
+ <string name="grant_credentials_permission_message_header">یەک یان چەند بەرنامەی ناوبراو داوای ڕێگەپێدان ئەکەن بۆ دەسی پێ گەیشتنی ئەژمێرەکەت، ئێستا و لە داهاتوودا.</string>
+ <string name="grant_credentials_permission_message_footer">ئەتەوێ ڕێگە بدەیت بەم داواکارییە؟</string>
+ <string name="grant_permissions_header_text">داواکردنی ڕێگەپێدان</string>
+ <string name="allow">رێگەدان</string>
+ <string name="deny">نکۆڵی</string>
+ <string name="permission_request_notification_title">داواکردنی مۆڵەت پێدان</string>
+ <string name="permission_request_notification_with_subtitle">داواکردنی مۆڵەت پێدان \nfor account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g>.</string>
+ <string name="input_method_binding_label">شێوازی نوسین</string>
+ <string name="sync_binding_label">هاوکاتکردن</string>
+ <string name="accessibility_binding_label">توانای ده‌ستپێگه‌شتن</string>
+ <string name="wallpaper_binding_label">وێنەی سەرشاشە</string>
+ <string name="chooser_wallpaper">گۆڕینی دیوارپۆش</string>
+ <string name="notification_listener_binding_label">گوێگری تێبینییەکان</string>
+ <string name="vpn_title">VPN چالاکرا</string>
+ <string name="vpn_title_long">VPN چالاکراو لەلایەن <xliff:g id="app" example="FooVPN client">%s</xliff:g></string>
+ <string name="vpn_text">دەست لێدە بۆ بەڕێوەبردنی تۆڕەکە.</string>
+ <string name="vpn_text_long">گرێدراوە بە <xliff:g id="session" example="office">%s</xliff:g>. دەست لێدە بۆ بەڕێوەبردنی تۆڕەکە.</string>
+ <string name="vpn_lockdown_connecting">\"VPN\"ی هەردەم چالاک گرێدەدرێت\u2026</string>
+ <string name="vpn_lockdown_connected">\"VPN\"ی هەردەم چالاک گرێدرا</string>
+ <string name="vpn_lockdown_error">\"VPN\"ی هەردەم چالاک هەڵەی دا</string>
+ <string name="vpn_lockdown_config">دەست لێدان بۆ سازدان</string>
+ <string name="upload_file">هەڵبژاردنی پەڕگە</string>
+ <string name="no_file_chosen">هیچ فایلێک دەستنیشان نەکراوە</string>
+ <string name="reset">ڕێکخستنەوە</string>
+ <string name="submit">پێشکەشکردن</string>
+ <string name="car_mode_disable_notification_title">دۆخی ئۆتۆمۆبیل چالاک کرا</string>
+ <string name="car_mode_disable_notification_message">دەست لێدان بۆ ده‌رچوون لە دۆخی ئۆتۆمۆبیل.</string>
+ <string name="tethered_notification_title">چالاککردن و به‌ستنه‌وه‌ی hotspot</string>
+ <string name="tethered_notification_message">دەست لێدان بۆ جێگیركردن.</string>
+ <string name="back_button_label">گەڕانەوە</string>
+ <string name="next_button_label">دواتر</string>
+ <string name="skip_button_label">تێپەڕاندن</string>
+ <string name="no_matches">هیچ ئەنجامێک نیە</string>
+ <string name="find_on_page">دۆزینەوە لە پەڕە</string>
+ <string name="action_mode_done">تەواو</string>
+ <string name="progress_erasing" product="nosdcard">سڕینەوەی بیرگەیUSB\u2026</string>
+ <string name="progress_erasing" product="default">سڕینەوەی بیرگەی دەرەکی\u2026</string>
+ <string name="share">هاوبه‌شیکردن</string>
+ <string name="find">دۆزینەوە</string>
+ <string name="websearch">بەدواگەڕانی وێب</string>
+ <string name="find_next">دۆزینەوەی داهاتوو</string>
+ <string name="find_previous">دۆزینەوەی پێشوو</string>
+ <string name="gpsNotifTicker">داواکردنی شوێن لە <xliff:g id="name">%s</xliff:g></string>
+ <string name="gpsNotifTitle">داواکردنی شوێن</string>
+ <string name="gpsNotifMessage">داواکراوە لەلایەن<xliff:g id="name">%1$s</xliff:g> (<xliff:g id="service" example="SUPL-service">%2$s</xliff:g>)</string>
+ <string name="gpsVerifYes">بەڵێ</string>
+ <string name="gpsVerifNo">نەخێر</string>
+ <string name="sync_too_many_deletes">سڕینەوەی سنوور زیاد لە پێویست</string>
+ <string name="sync_too_many_deletes_desc">بە ژماردە <xliff:g id="number_of_deleted_items">%1$d</xliff:g> بڕگەی سڕیاو هەیە بۆ <xliff:g id="type_of_sync">%2$s</xliff:g>, ئەژمێری <xliff:g id="account_name">%3$s</xliff:g>. دەتهەوێ چی بکەی؟</string>
+ <string name="sync_really_delete">سڕینەوەی بڕگەکان</string>
+ <string name="sync_undo_deletes">هه‌ڵوه‌شاندنه‌وەی سڕینەوەکان</string>
+ <string name="sync_do_nothing">هیچ مەکە بۆ ئێستا</string>
+ <string name="choose_account_label">هەژمارێک هەڵبژێرە</string>
+ <string name="add_account_label">"زیادکردنی هەژمار"</string>
+ <string name="add_account_button_label">دانانی هەژمار</string>
+ <string name="number_picker_increment_button">زیادکردن</string>
+ <string name="number_picker_decrement_button">کەمکردن</string>
+ <string name="number_picker_increment_scroll_mode"><xliff:g id="value" example="3">%s</xliff:g> دەستلێدە و بوەستە.</string>
+ <string name="number_picker_increment_scroll_action">لادان سەرۆ بۆ کەمکردن و بۆ خوارۆ بۆ زیادکردن.</string>
+ <string name="time_picker_increment_minute_button">زۆربوونی خولەک</string>
+ <string name="time_picker_decrement_minute_button">کەمبوونەوەی خولەک</string>
+ <string name="time_picker_increment_hour_button">زۆربوونی کاژێر</string>
+ <string name="time_picker_decrement_hour_button">کەمبوونەوەی کاژێر</string>
+ <string name="time_picker_increment_set_pm_button">دانای ئێوارە</string>
+ <string name="time_picker_decrement_set_am_button">دانای بەیانی</string>
+ <string name="date_picker_increment_month_button">زۆربوونی مانگ</string>
+ <string name="date_picker_decrement_month_button">کەمبوونەوەی مانگ</string>
+ <string name="date_picker_increment_day_button">زۆربوونی رۆژ</string>
+ <string name="date_picker_decrement_day_button">کەمبوونەوەی رۆژ</string>
+ <string name="date_picker_increment_year_button">زۆربوونی ساڵ</string>
+ <string name="date_picker_decrement_year_button">کەمبوونەوەی ساڵ</string>
+ <string name="keyboardview_keycode_alt">Alt</string>
+ <string name="keyboardview_keycode_cancel">پاشگەزبونەوە</string>
+ <string name="keyboardview_keycode_delete">تاقیکردنەوەی ئەژمێر</string>
+ <string name="keyboardview_keycode_done">ئه‌نجام درا</string>
+ <string name="keyboardview_keycode_mode_change">گۆڕینی جۆر</string>
+ <string name="keyboardview_keycode_shift">شوێنگۆڕین</string>
+ <string name="keyboardview_keycode_enter">دانان</string>
+ <string name="activitychooserview_choose_application">داخستنی بەرنامەیەک</string>
+ <string name="activitychooserview_choose_application_error">نەتوانرا دەستپێبکات <xliff:g id="application_name" example="Acme">%s</xliff:g></string>
+ <string name="shareactionprovider_share_with">بەشداری لەگەڵ</string>
+ <string name="shareactionprovider_share_with_application">بەشداری لەگەڵ <xliff:g id="application_name" example="Bluetooth">%s</xliff:g></string>
+ <string name="content_description_sliding_handle">"لادانی دەستی. دەستلێدانوamp; هەڵگرتن."</string>
+ <string name="description_target_unlock_tablet">لایدە بۆ چالاککردن.</string>
+ <string name="keyboard_headset_required_to_hear_password">بیستۆک ببەستەوە بۆ بیستنی دەنگی کلیلەکان کاتی نوسینی نهێنوشە.</string>
+ <string name="keyboard_password_character_no_headset">خاڵ.</string>
+ <string name="action_bar_home_description">بڕۆ بۆ ماڵەوە</string>
+ <string name="action_bar_up_description">بڕۆ بۆ سەرەوە</string>
+ <string name="action_menu_overflow_description">بەربژاردەی زیاتر</string>
+ <string name="action_bar_home_description_format">%1$s, %2$s</string>
+ <string name="action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>
+ <string name="storage_internal">بیرگەی ناوەکی</string>
+ <string name="storage_sd_card">بیرەگەی دەرەکی</string>
+ <string name="storage_usb">هەڵگری USB</string>
+ <string name="data_usage_warning_title">ئاگادارکردنەوەی بەکارهێنانی داتا</string>
+ <string name="data_usage_warning_body">دەست لێدە بۆ بینینی بەکارهێنانەکان و ڕێکبەندەکان.</string>
+ <string name="data_usage_3g_limit_snoozed_title">2G-3G زانیاری سنوردار به‌سه‌رچوو</string>
+ <string name="data_usage_4g_limit_snoozed_title">زانیاری سنورداری 4G به‌سه‌رچوو</string>
+ <string name="data_usage_wifi_limit_snoozed_title">Wi-Fi زانیاری سنور به‌سه‌رچو</string>
+ <string name="data_usage_limit_snoozed_body"><xliff:g id="size" example="3.8GB">%s</xliff:g> سنورداری دیاریکراو.</string>
+ <string name="data_usage_restricted_title">زانیاری پشتەگەڵاڵە سنوردارکرا</string>
+ <string name="data_usage_restricted_body">دەستلێدان بۆ سڕینەوەی سنوردارکردن.</string>
+ <string name="ssl_certificate">بڕوانامه‌ی پاراستن</string>
+ <string name="ssl_certificate_is_valid">بروانامەکە تەواو نیە.</string>
+ <string name="issued_to">بڵاوکراوە بۆ:</string>
+ <string name="common_name">ناوی هاوبەش:</string>
+ <string name="org_name">ڕێکخراو:</string>
+ <string name="org_unit">یه‌که‌ی ڕێکخراوی:</string>
+ <string name="issued_by">بڵاوکراوە لەلایەن:</string>
+ <string name="validity_period">له‌کاره‌:</string>
+ <string name="issued_on">ده‌رچوه‌ له‌:</string>
+ <string name="expires_on">بەسەردەچێ لە:</string>
+ <string name="serial_number">زنجیرە ژمارە:</string>
+ <string name="fingerprints">په‌نجه‌مۆر:</string>
+ <string name="sha256_fingerprint">SHA-256 په‌نجه‌مۆر:</string>
+ <string name="sha1_fingerprint">SHA-1 په‌نجه‌مۆر:</string>
+ <string name="activity_chooser_view_see_all">هەموو ببينە</string>
+ <string name="activity_chooser_view_dialog_title_default">هەڵبژاردنی چالاکی</string>
+ <string name="share_action_provider_share_with">هاوبەشی بکە بە ناوی</string>
+ <string name="list_delimeter">", "</string>
+ <string name="sending">ناردن\u2026</string>
+ <string name="launchBrowserDefault">چالاککردنی وێبگەر؟</string>
+ <string name="SetupCallDefault">پەیوەندی وەردەگرێت؟</string>
+ <string name="activity_resolver_use_always">هەمیشە</string>
+ <string name="activity_resolver_use_once">ته‌نیا یه‌کجار</string>
+ <string name="default_audio_route_name" product="tablet">تابلێت</string>
+ <string name="default_audio_route_name" product="default">مۆبایل</string>
+ <string name="default_audio_route_name_headphones">بیستۆک</string>
+ <string name="default_audio_route_name_dock_speakers">بڵندگۆی له‌نگه‌ر</string>
+ <string name="default_media_route_name_hdmi">HDMI</string>
+ <string name="default_audio_route_category_name">سیستەم</string>
+ <string name="bluetooth_a2dp_audio_route_name">ده‌نگی بلوتوس</string>
+ <string name="wireless_display_route_description">نیشاندانی وایه‌رلێسی</string>
+ <string name="media_route_chooser_title">په‌یوه‌ندی کردن به‌ ئامێر</string>
+ <string name="media_route_chooser_title_for_remote_display">ڕێگه‌گرتنی ڕوونما بۆ ئامێر</string>
+ <string name="media_route_chooser_searching">گه‌ڕان به‌دوای ئامێر\u2026</string>
+ <string name="media_route_chooser_extended_settings">ڕێکخستنه‌کان</string>
+ <string name="media_route_controller_disconnect">په‌یوه‌ندی پچڕان</string>
+ <string name="media_route_status_scanning">پشکنین...</string>
+ <string name="media_route_status_connecting">په‌یوه‌ندیكردن...</string>
+ <string name="media_route_status_available">ئاماده‌</string>
+ <string name="media_route_status_not_available">ئاماده‌ نیه‌</string>
+ <string name="media_route_status_in_use">سەرقاڵە</string>
+ <string name="display_manager_built_in_display_name">دروست کراو-لە شاشە</string>
+ <string name="display_manager_hdmi_display_name">شاشەی HDMI</string>
+ <string name="display_manager_overlay_display_name">دادەپۆشى #<xliff:g id="id">%1$d</xliff:g></string>
+ <string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string>
+ <string name="display_manager_overlay_display_secure_suffix">, پارێزراو</string>
+ <string name="kg_forgot_pattern_button_text">بیرچونی کێشانەکە</string>
+ <string name="kg_wrong_pattern">کێشان هەڵە</string>
+ <string name="kg_wrong_password">تێپەڕەوشەی هەڵە</string>
+ <string name="kg_wrong_pin">PIN هەڵەیە</string>
+ <string name="kg_too_many_failed_attempts_countdown">دوبارە هەوڵبدەرەوە <xliff:g id="number">%1$d</xliff:g> چرکە.</string>
+ <string name="kg_pattern_instructions">قوفڵی کێشان بکێشە</string>
+ <string name="kg_sim_pin_instructions">دانانی کۆدی سیمکارت</string>
+ <string name="kg_pin_instructions">PIN بنوسە</string>
+ <string name="kg_password_instructions">نهێنوشە بنوسە</string>
+ <string name="kg_puk_enter_puk_hint">سیمکارتەکە لە کارکەوتوە ئێستا.PUK لێ بدە بۆ بەردەوام بوون. بۆ وردەکاری زیاتر پەیوەندی بکە بە ئۆپەراتۆر.</string>
+ <string name="kg_puk_enter_pin_hint">کۆدێکی PIN بەخواستی خۆت دابنێ</string>
+ <string name="kg_enter_confirm_pin_hint">کۆدی PIN دوپاتکەرەوە</string>
+ <string name="kg_sim_unlock_progress_dialog_message">کردنەوەی سیمکارت\u2026</string>
+ <string name="kg_password_wrong_pin_code">کۆدی PIN ناڕاستە.</string>
+ <string name="kg_invalid_sim_pin_hint">(PIN)ەک بنووسه‌ که‌ ٤ بۆ ٨ ژماره‌ بێت.</string>
+ <string name="kg_invalid_puk">دوبارە کۆدی PUK دروست تێبنووسەوە. هەوڵدانە دوبارەکراوەکان بۆ هەمیشە سیمکارتەکەت لاچالاک ئەکات.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">کۆدەکانی PIN لە یەکتر ناچن</string>
+ <string name="kg_login_too_many_attempts">هەوڵی کێشانی ئێجگار زۆری شێوەئاسا</string>
+ <string name="kg_login_instructions">بۆ کردنەوە، بە هەژماری گوگڵ بچۆ ژووره‌وه‌.</string>
+ <string name="kg_login_username_hint">ناوی بەکارهێنەر (ئیمەیڵ)</string>
+ <string name="kg_login_password_hint">تێپەڕەوشە</string>
+ <string name="kg_login_submit_button">چوونەژوورەوە</string>
+ <string name="kg_login_invalid_input">ناو یان تێپه‌ڕوشه‌ ڕاست نییه‌.</string>
+ <string name="kg_login_account_recovery_hint">ناو یان تێپەڕەوشەت لە بیرچووە\?\nVisit <b>google.com/accounts/recovery</b>.</string>
+ <string name="kg_login_checking_password">تاقیکردنەوەی ئەژمێر\u2026</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">
+ بە هەڵە <xliff:g id="number">%d</xliff:g> جار PIN ت نووسیوە.
+ \n\nله‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا سەرلەنوێ هەوڵبدەوە.
+
+    .
+ </string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">
+ بەهەڵە <xliff:g id="number">%d</xliff:g> جار تێپەڕەوشەت لێداوە.
+ \n\nله‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا سەرلەنوێ هەوڵبدەوە.
+
+    .
+ </string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">
+ تۆ بە ناڕاست <xliff:g id="number">%d</xliff:g> جار چنراوی کردنەوەت کێشاوە.
+ \n\nلە <xliff:g id="number">%d</xliff:g> چرکەدا سەرلەنوێ هەوڵبدەوە.
+ </string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet">
+ تۆ بە ناڕاست <xliff:g id="number">%d</xliff:g> times جار هەوڵی کردنەوەی تابلێته‌که‌ت داوە.
+ پاش <xliff:g id="number">%d</xliff:g> هه‌وڵی سه‌رنه‌که‌وتووی زیاتر،
+ تابلێته‌که‌ ڕێکدەخرێتەوە بۆ بنەڕەتی کارگە هەروەها هه‌موو دراوەکانی به‌کارهێنه‌ر بزر دەبن.
+
+
+    .
+ </string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default">
+ تۆ بە ناڕاست <xliff:g id="number">%d</xliff:g> times جار هەوڵی کردنەوەی مۆبایلەکەت داوە.
+ پاش <xliff:g id="number">%d</xliff:g> هه‌وڵی سه‌رنه‌که‌وتووی زیاتر،
+ مۆبایلەکە ڕێکدەخرێتەوە بۆ بنەڕەتی کارگە هەروەها هه‌موو دراوەکانی به‌کارهێنه‌ر بزر دەبن.
+
+
+    .
+ </string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet">
+ تۆ بە ناڕاست <xliff:g id="number">%d</xliff:g> جار هەوڵی کردنەوەی تابلێتەکەت داوە.
+ تابلێتەکە ڕێکدەسرێتەوە بۆ بنەڕەتی کارگە.
+ </string>
+ <string name="kg_failed_attempts_now_wiping" product="default">
+ تۆ بە ناڕاست <xliff:g id="number">%d</xliff:g> جار هەوڵی کردنەوەی مۆبایلەکەت داوە.
+ مۆبایلەکە ڕێکدەسرێتەوە بۆ بنەڕەتی کارگە.
+ </string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">
+ تۆ بەهەڵە شیوازی کردنەوەت <xliff:g id="number">%d</xliff:g> جار کێشاوە.
+ دوای <xliff:g id="number">%d</xliff:g> جاری دیکە هەوڵدانی هەڵە,
+ داوای ئەژمێری ئیمێڵەکەت لێئەکرێت بۆ کردنەوەی تابلێتەکەت.\n\n
+ دوبارە هەوڵبدەوە لە <xliff:g id="number">%d</xliff:g> چرکەی دیکەدا.
+ </string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">
+ تۆ بەهەڵە شیوازی کردنەوەت <xliff:g id="number">%d</xliff:g> جار کێشاوە.
+ دوای <xliff:g id="number">%d</xliff:g> جاری دیکە هەوڵدانی هەڵە,
+ داوای ئەژمێری ئیمێڵەکەت لێئەکرێت بۆ کردنەوەی مۆبایلەکەت.\n\n
+ دوبارە هەوڵبدەوە لە <xliff:g id="number">%d</xliff:g> چرکەی دیکەدا.
+ </string>
+ <string name="kg_text_message_separator" product="default">" \u2014 "</string>
+ <string name="kg_reordering_delete_drop_target_text">سڕینەوە</string>
+ <string name="continue_to_enable_accessibility">دو قامکت ڕاگرە لەکاتی کێشان بۆ خوارەوە بۆ چالاککردنی خزمەتگوزاری بەئاسانی بەدەست گەیشتن.</string>
+ <string name="accessibility_enabled">خزمەتگوزاری بەئاسانی بەدەست گەیشتن چالاککرا.</string>
+ <string name="enable_accessibility_canceled">توانای ده‌ستپێگه‌شتن پاشگەزبووەوە.</string>
+ <string name="user_switched">بەکارهێنەری ئێستا <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string>
+ <string name="owner_name" msgid="3879126011135546571">خاوەن</string>
+ <string name="error_message_title">هەڵە</string>
+ <string name="app_not_found">هیچ نەرمەواڵایەک نەدۆزرایەوە تاکو ئەم کردارە لەخۆ بگرێت</string>
+ <string name="revoke">‌هەڵوەشاندنەوه</string>
+ <string name="mediasize_iso_a0">ISO A0</string>
+ <string name="mediasize_iso_a1">ISO A1</string>
+ <string name="mediasize_iso_a2">ISO A2</string>
+ <string name="mediasize_iso_a3">ISO A3</string>
+ <string name="mediasize_iso_a4">ISO A4</string>
+ <string name="mediasize_iso_a5">ISO A5</string>
+ <string name="mediasize_iso_a6">ISO A6</string>
+ <string name="mediasize_iso_a7">ISO A7</string>
+ <string name="mediasize_iso_a8">ISO A8</string>
+ <string name="mediasize_iso_a9">ISO A9</string>
+ <string name="mediasize_iso_a10">ISO A10</string>
+ <string name="mediasize_iso_b0">ISO B0</string>
+ <string name="mediasize_iso_b1">ISO B1</string>
+ <string name="mediasize_iso_b2">ISO B2</string>
+ <string name="mediasize_iso_b3">ISO B3</string>
+ <string name="mediasize_iso_b4">ISO B4</string>
+ <string name="mediasize_iso_b5">ISO B5</string>
+ <string name="mediasize_iso_b6">ISO B6</string>
+ <string name="mediasize_iso_b7">ISO B7</string>
+ <string name="mediasize_iso_b8">ISO B8</string>
+ <string name="mediasize_iso_b9">ISO B9</string>
+ <string name="mediasize_iso_b10">ISO B10</string>
+ <string name="mediasize_iso_c0">ISO C0</string>
+ <string name="mediasize_iso_c1">ISO C1</string>
+ <string name="mediasize_iso_c2">ISO C2</string>
+ <string name="mediasize_iso_c3">ISO C3</string>
+ <string name="mediasize_iso_c4">ISO C4</string>
+ <string name="mediasize_iso_c5">ISO C5</string>
+ <string name="mediasize_iso_c6">ISO C6</string>
+ <string name="mediasize_iso_c7">ISO C7</string>
+ <string name="mediasize_iso_c8">ISO C8</string>
+ <string name="mediasize_iso_c9">ISO C9</string>
+ <string name="mediasize_iso_c10">ISO C10</string>
+ <string name="mediasize_na_letter">نامە</string>
+ <string name="mediasize_na_gvrnmt_letter">نامەی حکومی</string>
+ <string name="mediasize_na_legal">یاسا</string>
+ <string name="mediasize_na_junior_legal">یاسایی پەیوەند</string>
+ <string name="mediasize_na_ledger">دەفتەری تێبینی</string>
+ <string name="mediasize_na_tabloid">پڕوێنە</string>
+ <string name="mediasize_na_index_3x5">Index Card 3x5</string>
+ <string name="mediasize_na_index_4x6">Index Card 4x6</string>
+ <string name="mediasize_na_index_5x8">Index Card 5x8</string>
+ <string name="mediasize_na_monarch">Monarch</string>
+ <string name="mediasize_na_quarto">Quarto</string>
+ <string name="mediasize_na_foolscap">Foolscap</string>
+ <string name="mediasize_chinese_roc_8k">ROC 8K</string>
+ <string name="mediasize_chinese_roc_16k">ROC 16K</string>
+ <string name="mediasize_chinese_prc_1">PRC 1</string>
+ <string name="mediasize_chinese_prc_2">PRC 2</string>
+ <string name="mediasize_chinese_prc_3">PRC 3</string>
+ <string name="mediasize_chinese_prc_4">PRC 4</string>
+ <string name="mediasize_chinese_prc_5">PRC 5</string>
+ <string name="mediasize_chinese_prc_6">PRC 6</string>
+ <string name="mediasize_chinese_prc_7">PRC 7</string>
+ <string name="mediasize_chinese_prc_8">PRC 8</string>
+ <string name="mediasize_chinese_prc_9">PRC 9</string>
+ <string name="mediasize_chinese_prc_10">PRC 10</string>
+ <string name="mediasize_chinese_prc_16k">PRC 16K</string>
+ <string name="mediasize_chinese_om_pa_kai">Pa Kai</string>
+ <string name="mediasize_chinese_om_dai_pa_kai">Dai Pa Kai</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai">Jurro Ku Kai</string>
+ <string name="mediasize_japanese_jis_b10">JIS B10</string>
+ <string name="mediasize_japanese_jis_b9">JIS B9</string>
+ <string name="mediasize_japanese_jis_b8">JIS B8</string>
+ <string name="mediasize_japanese_jis_b7">JIS B7</string>
+ <string name="mediasize_japanese_jis_b6">JIS B6</string>
+ <string name="mediasize_japanese_jis_b5">JIS B5</string>
+ <string name="mediasize_japanese_jis_b4">JIS B4</string>
+ <string name="mediasize_japanese_jis_b3">JIS B3</string>
+ <string name="mediasize_japanese_jis_b2">JIS B2</string>
+ <string name="mediasize_japanese_jis_b1">JIS B1</string>
+ <string name="mediasize_japanese_jis_b0">JIS B0</string>
+ <string name="mediasize_japanese_jis_exec">JIS Exec</string>
+ <string name="mediasize_japanese_chou4">Chou4</string>
+ <string name="mediasize_japanese_chou3">Chou3</string>
+ <string name="mediasize_japanese_chou2">Chou2</string>
+ <string name="mediasize_japanese_hagaki">Hagaki </string>
+ <string name="mediasize_japanese_oufuku">Oufuku </string>
+ <string name="mediasize_japanese_kahu">Kahu</string>
+ <string name="mediasize_japanese_kaku2">Kaku2</string>
+ <string name="mediasize_japanese_you4">You4</string>
+ <string name="mediasize_unknown_portrait">روخسار نەناسراو</string>
+ <string name="mediasize_unknown_landscape">شێوە ئاسۆی نەناسراو</string>
+ <string name="write_fail_reason_cancelled">پاشگەزبووەوە</string>
+ <string name="write_fail_reason_cannot_write">هەڵە لە نووسینی ناوەڕۆک</string>
+ <string name="reason_unknown">نەناسراو</string>
+ <string name="reason_service_unavailable">خزمەتگوزاری چاپکەر نا چالاکە</string>
+ <string name="print_service_installed_title"><xliff:g id="name" example="Cloud Print">%s</xliff:g> خزمەتگوزاری دامەزرا</string>
+ <string name="print_service_installed_message">لێدان بۆ چالاککردن</string>
+ <string name="restr_pin_enter_admin_pin">PIN ‌بەڕێوەبەرێكى ئامراز بنووسە</string>
+ <string name="restr_pin_enter_pin">PIN بنووسە</string>
+ <string name="restr_pin_incorrect">نادرووست</string>
+ <string name="restr_pin_enter_old_pin">PIN هەنووکە</string>
+ <string name="restr_pin_enter_new_pin">PIN نوێ</string>
+ <string name="restr_pin_confirm_pin">پشتڕاستکردنەوەی PIN نوێ</string>
+ <string name="restr_pin_create_pin">PIN دروست بکە بۆ گۆڕینی بەسترانەوەکان</string>
+ <string name="restr_pin_error_doesnt_match">PIN ناگونجێت. دوبارە هەوڵبدەرەوە.</string>
+ <string name="restr_pin_error_too_short">PIN زۆر کورتە. ئەبێ لانیکەم 4 ژمارە بێت.</string>
+ <string name="restr_pin_try_later">دواتر دووبارە هەوڵبدە</string>
+ <string name="zen_mode_feature_name">مەمشێوێنە</string>
+ <string name="floating_toolbar_open_overflow_description">بەربژاردەی زیاتر</string>
+</resources>
diff --git a/core/res/res/values-lb-rLU/donottranslate-maps.xml b/core/res/res/values-lb-rLU/donottranslate-maps.xml
new file mode 100644
index 0000000..18c1eb5
--- /dev/null
+++ b/core/res/res/values-lb-rLU/donottranslate-maps.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod 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.
+-->
+<resources>
+ <!-- Stub for Luxembourgish -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>50854509</item>
+ <item>4376678</item>
+ </integer-array>
+ <integer-array name="maps_starting_zoom">
+ <item>5</item>
+ </integer-array>
+</resources>
diff --git a/core/res/res/values-lb/cm_strings.xml b/core/res/res/values-lb/cm_strings.xml
new file mode 100644
index 0000000..5e8dbdf
--- /dev/null
+++ b/core/res/res/values-lb/cm_strings.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Schiermfoto</string>
+ <string name="permlab_receiveProtectedSms">Geschützten SMSen empfänken</string>
+ <string name="permdesc_receiveProtectedSms">Erlaabt der App, erakommend geschützten SMS z\'empfänken.</string>
+ <string name="permlab_modifyProtectedSmsList">Lëscht vun de geschützten SMSen änneren</string>
+ <string name="permdesc_modifyProtectedSmsList">Erlaabt der App, d\'Lëscht vun de geschützten SMS-Adressen z\'änneren.</string>
+ <string name="permgrouplab_security">Sécherheet</string>
+ <string name="permgroupdesc_security">Berechtegungen déi mat der Sécherheet vum Apparat ze dinn hunn.</string>
+ <string name="permlab_readPhoneBlacklist">Schwaarz Lëscht ausliesen</string>
+ <string name="permdesc_readPhoneBlacklist">Erlaabt der App, Informatiounen iwwer blockéiert Telefonsnummere fir erakommend Uriff oder Messagen ze liesen.</string>
+ <string name="permlab_changePhoneBlacklist">Schwaarz Lëscht änneren</string>
+ <string name="permdesc_changePhoneBlacklist">Erlaabt der App, d\'blockéiert Telefonsnummere fir erakommend Uriff oder Messagen z\'änneren.</string>
+ <string name="permlab_setKeyguardWallpaper">Hannergrondbild vum Spärschierm setzen</string>
+ <string name="permdesc_setKeyguardWallpaper">Erlaabt der App, d\'Hannergrondbild vum Spärschierm z\'änneren.</string>
+ <string name="global_action_reboot">Nei starten</string>
+ <string name="global_action_current_user">Aktuell</string>
+ <string name="reboot_reboot">Nei starten</string>
+ <string name="reboot_recovery">Recuperatioun</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Eroflueden</string>
+ <string name="reboot_soft">Séieren Neistart</string>
+ <string name="reboot_title">Nei starten</string>
+ <string name="reboot_confirm" product="tablet">Däin Tablet gëtt nei gestart.</string>
+ <string name="reboot_confirm" product="default">Däin Telefon gëtt nei gestart.</string>
+ <string name="reboot_progress">Gëtt nei gestart\u2026</string>
+ <string name="app_killed_message">App zougemaach</string>
+ <string name="adb_net_active_notification_title">ADB iwwer Netzwierk aktivéiert</string>
+ <string name="adb_both_active_notification_title">ADB iwwer USB an Netzwierk aktivéiert</string>
+ <string name="adb_active_generic_notification_message">Drécke fir Debugging ze desaktivéieren.</string>
+ <string name="adb_active_custom_tile">ADB: <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB an Netzwierk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Netzwierk</string>
+ <string name="permlab_interceptPackageLaunch">App-Start offänken</string>
+ <string name="stylus_app_not_installed">%s ass net installéiert</string>
+ <string name="silent_mode_priority">Prioritéit</string>
+ <string name="silent_mode_none">Keen</string>
+ <string name="subscription_change_disabled_wifi_ap">WLAN-Zougrëffspunkt gouf opgrond vun Ännerunge am SIM-Abonnement desaktivéiert</string>
+ <string name="notify_turn_wifi_off_title">WLAN ausschalten</string>
+ <string name="permlab_changePrivacyGuardState">Privatsphärschutz aktivéieren oder desaktivéieren</string>
+ <string name="permdesc_changePrivacyGuardState">Erlaabt der App, z\'änneren ob eng aner App mam Privatsphärschutz leeft. Wann eng App mam Privatsphärschutz leeft, huet se keen Accès op perséinlech Date wéi Kontakter, Uruffprotokoller oder Messagen.</string>
+ <string name="privacy_guard_notification">Privatsphärschutz aktiv</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> huet keen Accès op perséinlech Daten</string>
+ <string name="privacy_guard_dialog_title">Privatsphärschutz</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> wëll <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Mäi Choix verhalen</string>
+ <string name="app_ops_access_camera">op d\'Kamera zougräifen</string>
+ <string name="app_ops_access_location">op de Standuert zougräifen</string>
+ <string name="app_ops_access_notifications">op d\'Notifikatiounen zougräifen</string>
+ <string name="app_ops_activate_vpn">E VPN aktivéieren</string>
+ <string name="app_ops_auto_start">Automatesch starten</string>
+ <string name="app_ops_delete_call_log">Den Uruffhistorique läschen</string>
+ <string name="app_ops_delete_contacts">Kontakter läschen</string>
+ <string name="app_ops_delete_mms">MMS-Messagë läschen</string>
+ <string name="app_ops_delete_sms">SMS-Messagë läschen</string>
+ <string name="app_ops_draw_on_top">Virun aneren Appen ablenden</string>
+ <string name="app_ops_get_usage_stats">App-Benotzungsstatistiken ausliesen</string>
+ <string name="app_ops_keep_device_awake">de Rouzoustand desaktivéieren</string>
+ <string name="app_ops_make_phone_call">en Telefonsuruff maachen</string>
+ <string name="app_ops_modify_calendar">de Kalenner änneren</string>
+ <string name="app_ops_modify_call_log">d\'Urufflëscht änneren</string>
+ <string name="app_ops_modify_clipboard">d\'Tëschenoflag änneren</string>
+ <string name="app_ops_modify_contacts">d\'Kontakter änneren</string>
+ <string name="app_ops_modify_settings">d\'Systemastellungen änneren</string>
+ <string name="app_ops_mute_unmute_microphone">Mikro aus-/uschalten</string>
+ <string name="app_ops_play_audio">Toun ofspillen</string>
+ <string name="app_ops_post_notification">eng Notifikatioun erstellen</string>
+ <string name="app_ops_project_media">Projektioun vu Medieninhalter</string>
+ <string name="app_ops_read_calendar">de Kalenner liesen</string>
+ <string name="app_ops_read_call_log">d\'Urufflëscht liesen</string>
+ <string name="app_ops_read_clipboard">d\'Tëschenoflag liesen</string>
+ <string name="app_ops_read_contacts">d\'Kontakter liesen</string>
+ <string name="app_ops_read_mms">MMS-Messagë liesen</string>
+ <string name="app_ops_read_sms">SMS-Messagë liesen</string>
+ <string name="app_ops_receive_sms">en SMS-Message empfänken</string>
+ <string name="app_ops_record_audio">Toun ophuelen</string>
+ <string name="app_ops_send_mms">en MMS-Message schécken</string>
+ <string name="app_ops_send_sms">eng SMS-Message schécken</string>
+ <string name="app_ops_start_at_bootup">automatesch starten</string>
+ <string name="app_ops_toast_window">Kuerzzäit-Notifikatiounen uweisen</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth un-/ausschalten</string>
+ <string name="app_ops_toggle_nfc">NFC un-/ausschalten</string>
+ <string name="app_ops_toggle_wifi">WLAN un-/ausschalten</string>
+ <string name="app_ops_use_alarm_volume">d\'Lautstäerkt vum Wecker änneren</string>
+ <string name="app_ops_use_audio_focus">den Tounfokus änneren</string>
+ <string name="app_ops_use_bluetooth_volume">d\'Bluetooth-Lautstäerkt änneren</string>
+ <string name="app_ops_use_master_volume">d\'Gesamtlautstäerkt änneren</string>
+ <string name="app_ops_use_media_buttons">d\'Medieknäppercher benotzen</string>
+ <string name="app_ops_use_media_volume">d\'Medielautstäerkt änneren</string>
+ <string name="app_ops_use_notification_volume">d\'Notifikatiounslautstäerkt änneren</string>
+ <string name="app_ops_use_ring_volume">d\'Schelllautstäerkt änneren</string>
+ <string name="app_ops_use_vibrate">de Vibratiounsalarm steieren</string>
+ <string name="app_ops_use_voice_volume">d\'Sproochlautstäerkt änneren</string>
+ <string name="app_ops_write_mms">eng MMS schreiwen</string>
+ <string name="app_ops_write_sms">eng SMS schreiwen</string>
+ <string name="app_ops_su">Root-Accès kréien</string>
+ <string name="lock_to_app_toast_no_navbar">Fir dëse Schierm lasszeléisen, dréck den Zréck-Knäppchen an hal e gedréckt.</string>
+ <string name="live_display_auto">Automatesch</string>
+ <string name="live_display_auto_summary">Faarftemperatur automatesch dem Sonnenënnergank a Sonnenopgank upassen</string>
+ <string name="live_display_off">Aus</string>
+ <string name="live_display_off_summary">All Upassungen desaktivéieren</string>
+ <string name="live_display_day">Dag</string>
+ <string name="live_display_day_summary">Just Dagesmodus benotzen</string>
+ <string name="live_display_night">Nuecht</string>
+ <string name="live_display_night_summary">Just Nuetsmodus benotzen</string>
+ <string name="live_display_outdoor">Baussen (hell Sonn)</string>
+ <string name="live_display_outdoor_summary">Just Baussemodus benotzen</string>
+ <string name="live_display_hint">LiveDisplay ka géint Iwwerustrengung vun den Aen a beim Schlofen an der Nuecht hëllefen. Dréck hei, fir et auszeprobéieren!</string>
+ <string name="tethered_notification_no_device_message">Kee connectéierten Apparat</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> connectéierten Apparat</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> connectéiert Apparater</string>
+</resources>
diff --git a/core/res/res/values-lb/strings.xml b/core/res/res/values-lb/strings.xml
new file mode 100644
index 0000000..9122965
--- /dev/null
+++ b/core/res/res/values-lb/strings.xml
@@ -0,0 +1,1326 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="byteShort">B</string>
+ <string name="kilobyteShort">kB</string>
+ <string name="megabyteShort">MB</string>
+ <string name="gigabyteShort">GB</string>
+ <string name="terabyteShort">TB</string>
+ <string name="petabyteShort">PB</string>
+ <string name="durationDays"><xliff:g id="days">%1$d</xliff:g> Deeg</string>
+ <string name="durationDayHours"><xliff:g id="days">%1$d</xliff:g> Dag <xliff:g id="hours">%2$d</xliff:g> St.</string>
+ <string name="durationDayHour"><xliff:g id="days">%1$d</xliff:g> Dag <xliff:g id="hours">%2$d</xliff:g> St.</string>
+ <string name="durationHours"><xliff:g id="hours">%1$d</xliff:g> St.</string>
+ <string name="durationHourMinutes"><xliff:g id="hours">%1$d</xliff:g> St. <xliff:g id="minutes">%2$d</xliff:g> Min.</string>
+ <string name="durationHourMinute"><xliff:g id="hours">%1$d</xliff:g> St. <xliff:g id="minutes">%2$d</xliff:g> Min.</string>
+ <string name="durationMinutes"><xliff:g id="minutes">%1$d</xliff:g> Min.</string>
+ <string name="durationMinute"><xliff:g id="minutes">%1$d</xliff:g> Min.</string>
+ <string name="durationMinuteSeconds"><xliff:g id="minutes">%1$d</xliff:g> Min. <xliff:g id="seconds">%2$d</xliff:g> Sek.</string>
+ <string name="durationMinuteSecond"><xliff:g id="minutes">%1$d</xliff:g> Min. <xliff:g id="seconds">%2$d</xliff:g> Sek.</string>
+ <string name="durationSeconds"><xliff:g id="seconds">%1$d</xliff:g> Sek.</string>
+ <string name="durationSecond"><xliff:g id="seconds">%1$d</xliff:g> Sek.</string>
+ <string name="untitled">&lt;Ouni Titel&gt;</string>
+ <string name="emptyPhoneNumber">(Keng Telefonsnummer)</string>
+ <string name="unknownName">Onbekannt</string>
+ <string name="defaultVoiceMailAlphaTag">Sproochopnam</string>
+ <string name="defaultMsisdnAlphaTag">MSISDN1</string>
+ <string name="mmiError">Connectiounsproblem oder ongëltegen MMI-Code.</string>
+ <string name="mmiFdnError">De Virgank ass just fir deng zougeloosse Ruffnummer méiglech.</string>
+ <string name="serviceEnabled">Service gouf aktivéiert.</string>
+ <string name="serviceEnabledFor">Service gouf aktivéiert fir:</string>
+ <string name="serviceDisabled">Service gouf desaktivéiert.</string>
+ <string name="serviceRegistered">Registréierung war erfollegräich.</string>
+ <string name="serviceErased">Ausläsche war erfollegräich.</string>
+ <string name="passwordIncorrect">Inkorrekt Passwuert.</string>
+ <string name="mmiComplete">MMI komplett.</string>
+ <string name="badPin">Déi al PIN, déi s du aginn hues, ass net korrekt.</string>
+ <string name="badPuk">De PUK, deen s du aginn hues, ass net korrekt.</string>
+ <string name="mismatchPin">D\'PINen, déi s du aginn hues, stëmmen net iwwereneen.</string>
+ <string name="invalidPin">Gëff e PIN an, deen tëscht 4 an 8 Zifferen huet.</string>
+ <string name="invalidPuk">Gëff e PUK an, deen 8 oder méi Zifferen huet.</string>
+ <string name="needPuk">Deng SIM-Kaart ass PUK-gespaart. Gëff de PUK-Code an, fir en z\'entspären.</string>
+ <string name="needPuk2">Gëff de PUK2 vun der SIM-Kaart an, fir se z\'entspären.</string>
+ <string name="enablePin">Feeler. Aktivéier d\'SIM-/RUIM-Spär.</string>
+ <string name="imei">IMEI</string>
+ <string name="meid">MEID</string>
+ <string name="ClipMmi">Erakommend Uruffer-ID</string>
+ <string name="ClirMmi">Erausgoend Uruffer-ID</string>
+ <string name="ColpMmi">ID vun der verbonnener Leitung</string>
+ <string name="ColrMmi">Aschränkunge fir d\'ID vun der verbonnener Leitung</string>
+ <string name="CfMmi">Gespréich-Weiderleedung</string>
+ <string name="CwMmi">Gespréich pauséiert</string>
+ <string name="BaMmi">Uruffspär</string>
+ <string name="PwdMmi">Passwuert-Ännerung</string>
+ <string name="PinMmi">PIN-Ännerung</string>
+ <string name="CnipMmi">Ruffnummer disponibel</string>
+ <string name="CnirMmi">Rufnummer begrenzt</string>
+ <string name="ThreeWCMmi">Dräierkonferenz</string>
+ <string name="RuacMmi">Refus vun onerwënschten Uriff</string>
+ <string name="CndMmi">Iwwermëttlung fir Ruffnummeren</string>
+ <string name="DndMmi">Net stéieren</string>
+ <string name="CLIRDefaultOnNextCallOn">D\'Uruffer-ID ass standardméisseg ageschränkt. Nächsten Uruff: Ageschränkt</string>
+ <string name="CLIRDefaultOnNextCallOff">D\'Uruffer-ID ass standardméisseg ageschränkt. Nächsten Uruff: Net ageschränkt</string>
+ <string name="CLIRDefaultOffNextCallOn">D\'Uruffer-ID ass standardméisseg net ageschränkt. Nächsten Uruff: Ageschränkt</string>
+ <string name="CLIRDefaultOffNextCallOff">D\'Uruffer-ID ass standardméisseg net ageschränkt. Nächsten Uruff: Net ageschränkt</string>
+ <string name="serviceNotProvisioned">Service net ageriicht.</string>
+ <string name="CLIRPermanent">D\'Astellung fir d\'Uruffer-ID kann net geännert ginn.</string>
+ <string name="RestrictedChangedTitle">Begrenzten Zougrëff geännert</string>
+ <string name="RestrictedOnData">Dateservice ass gespaart.</string>
+ <string name="RestrictedOnEmergency">Noutruff ass gespaart.</string>
+ <string name="RestrictedOnNormal">Sproochservice ass gespaart.</string>
+ <string name="RestrictedOnAllVoice">All Stëmmservicer si gespaart.</string>
+ <string name="RestrictedOnSms">SMS-Service ass gespaart.</string>
+ <string name="RestrictedOnVoiceData">Sprooch-/Dateservicer si gespaart.</string>
+ <string name="RestrictedOnVoiceSms">Sprooch-/SMS-Servicer si gespaart.</string>
+ <string name="RestrictedOnAll">Alle Sprooch-/Date-/SMS-Servicer si gespaart.</string>
+ <string name="peerTtyModeFull">Peer huet TTY-Modus \"Vollstänneg\" ugefrot</string>
+ <string name="peerTtyModeHco">Peer huet TTY-Modus \"HCO\" ugefrot</string>
+ <string name="peerTtyModeVco">Peer huet TTY-Modus \"VCO\" ugefrot</string>
+ <string name="peerTtyModeOff">Peer huet TTY-Modus \"Aus\" ugefrot</string>
+ <string name="serviceClassVoice">Stëmm</string>
+ <string name="serviceClassData">Daten</string>
+ <string name="serviceClassFAX">FAX</string>
+ <string name="serviceClassSMS">SMS</string>
+ <string name="serviceClassDataAsync">Async</string>
+ <string name="serviceClassDataSync">Sync</string>
+ <string name="serviceClassPacket">Pak</string>
+ <string name="serviceClassPAD">PAD</string>
+ <string name="roamingText0">Roaming-Anzeig un</string>
+ <string name="roamingText1">Roaming-Anzeig aus</string>
+ <string name="roamingText2">Roaming-Anzeig blénkend</string>
+ <string name="roamingText3">Aus der Noperschaft eraus</string>
+ <string name="roamingText4">Aus dem Gebai eraus</string>
+ <string name="roamingText5">Roaming - Preferéierte System</string>
+ <string name="roamingText6">Roaming - Disponibele System</string>
+ <string name="roamingText7">Roaming - Allianzpartner</string>
+ <string name="roamingText8">Roaming - Premiumpartner</string>
+ <string name="roamingText9">Roaming - Voll Déngschtleeschtungsfunktionalitéit</string>
+ <string name="roamingText10">Roaming - Partiell Déngschtleeschtungsfunktionalitéit</string>
+ <string name="roamingText11">Roaming-Banner Un</string>
+ <string name="roamingText12">Roaming-Banner Aus</string>
+ <string name="roamingTextSearching">E Service gëtt gesicht</string>
+ <string name="cfTemplateNotForwarded"><xliff:g id="bearer_service_code">{0}</xliff:g>: Net weidergeleet</string>
+ <string name="cfTemplateForwarded"><xliff:g id="bearer_service_code">{0}</xliff:g>: <xliff:g id="dialing_number">{1}</xliff:g></string>
+ <string name="cfTemplateForwardedTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: <xliff:g id="dialing_number">{1}</xliff:g> no <xliff:g id="time_delay">{2}</xliff:g> Sekonnen</string>
+ <string name="cfTemplateRegistered"><xliff:g id="bearer_service_code">{0}</xliff:g>: Net weidergeleet</string>
+ <string name="cfTemplateRegisteredTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: Net weidergeleet</string>
+ <string name="fcComplete">Funktiounscode ofgeschloss.</string>
+ <string name="fcError">Connectiounsproblem oder ongëltege Funktiounscode.</string>
+ <string name="httpErrorOk">OK</string>
+ <string name="httpError">Et gouf en Netzwierkfeeler.</string>
+ <string name="httpErrorLookup">URL gouf net fonnt.</string>
+ <string name="httpErrorUnsupportedAuthScheme">Den Authentifizéierungsschema vun der Säit ass net ënnerstëtzt.</string>
+ <string name="httpErrorAuth">Konnt net authentifizéieren.</string>
+ <string name="httpErrorProxyAuth">D\'Authentifizéierung iwwer de Proxy Server war net erfollegräich.</string>
+ <string name="httpErrorConnect">Konnt keng Connectioun mam Server hierstellen.</string>
+ <string name="httpErrorIO">Konnt net mam Server kommunikéieren. Probéier méi spéit nees.</string>
+ <string name="httpErrorTimeout">Zäitiwwerschreidung bei der Connectioun mam Server.</string>
+ <string name="httpErrorRedirectLoop">D\'Säit huet zevill Serverweiderleedungen.</string>
+ <string name="httpErrorUnsupportedScheme">De Protokoll ass net ënnerstëtzt.</string>
+ <string name="httpErrorFailedSslHandshake">Konnt keng sécher Connectioun hierstellen.</string>
+ <string name="httpErrorBadUrl">Konnt d\'Säit net opmaache well d\'URL net gëlteg ass.</string>
+ <string name="httpErrorFile">Konnt net op de Fichier zougräifen.</string>
+ <string name="httpErrorFileNotFound">Konnt den ugefrote Fichier net fannen.</string>
+ <string name="httpErrorTooManyRequests">Et ginn ze vill Ufroe beaarbecht. Probéier méi spéit nees.</string>
+ <string name="notification_title">Feeler bei der Umeldung fir <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g></string>
+ <string name="contentServiceSync">Sync</string>
+ <string name="contentServiceSyncNotificationTitle">Sync</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc">Ze vill <xliff:g id="content_type">%s</xliff:g> geläscht.</string>
+ <string name="low_memory" product="tablet">Den Tabletsspäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn.</string>
+ <string name="low_memory" product="watch">Den Auerespäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn.</string>
+ <string name="low_memory" product="tv">Den Tëleespäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn.</string>
+ <string name="low_memory" product="default">Den Telefonsspäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn.</string>
+ <string name="ssl_ca_cert_warning">D\'Netzwierk kéint iwwerwaacht sinn</string>
+ <string name="ssl_ca_cert_noti_by_unknown">Vun engem onbekannten Drëtten</string>
+ <string name="ssl_ca_cert_noti_by_administrator">Vum Administrateur vun dengem Aarbechtsprofil</string>
+ <string name="ssl_ca_cert_noti_managed">Vu(n) <xliff:g id="managing_domain">%s</xliff:g></string>
+ <string name="work_profile_deleted">Aarbechtsprofil geläscht</string>
+ <string name="work_profile_deleted_description">Aarbechtsprofil geläscht well d\'Admin-App feelt.</string>
+ <string name="work_profile_deleted_details">D\'Admin-App fir den Aarbechtsprofil feelt oder ass futti. Dowéinst gouf däin Aarbechtsprofil an all d\'Daten déi dozougehéiere geläscht. Kontaktéier däin Administrateur fir Hëllef ze kréien.</string>
+ <string name="factory_reset_warning">Däin Apparat gëtt geläscht</string>
+ <string name="factory_reset_message">D\'Admin-App kann net benotzt ginn, well se futti ass oder Komponente feelen. D\'Daten op dengem Apparat ginn elo geläscht. Kontaktéier däin Administrateur fir Hëllef ze kréien.</string>
+ <string name="me">Ech</string>
+ <string name="power_dialog" product="tablet">Tabletoptiounen</string>
+ <string name="power_dialog" product="tv">Tëleesoptiounen</string>
+ <string name="power_dialog" product="default">Telefonsoptiounen</string>
+ <string name="silent_mode">Stëlle Modus</string>
+ <string name="turn_on_radio">Funk umaachen</string>
+ <string name="turn_off_radio">Funk ausmaachen</string>
+ <string name="screen_lock">Schiermspär</string>
+ <string name="power_off">Ausmaachen</string>
+ <string name="silent_mode_silent">Schelltoun aus</string>
+ <string name="silent_mode_vibrate">Schellmodus \"Vibratioun\"</string>
+ <string name="silent_mode_ring">Schelltoun un</string>
+ <string name="shutdown_progress">Gëtt ausgemaach\u2026</string>
+ <string name="shutdown_confirm" product="tablet">Däin Tablet gëtt ausgemaach.</string>
+ <string name="shutdown_confirm" product="tv">Deng Tëlee schallt sech aus.</string>
+ <string name="shutdown_confirm" product="watch">Deng Auer schalt sech aus.</string>
+ <string name="shutdown_confirm" product="default">Däin Telefon gëtt ausgemaach.</string>
+ <string name="shutdown_confirm_question">Wëlls du den Apparat ausmaachen?</string>
+ <string name="reboot_safemode_title">An de séchere Modus wiesselen</string>
+ <string name="reboot_safemode_confirm">Wëlls du an de séchere Modus wiesselen? Doduerch ginn all d\'Appe vun Drëttubidder desaktivéiert, déi s du installéiert hues. Se ginn no engem weideren Neistart awer nees hiergestallt.</string>
+ <string name="recent_tasks_title">Rezent</string>
+ <string name="no_recent_tasks">Keng rezent Appen.</string>
+ <string name="global_actions" product="tablet">Tabletoptiounen</string>
+ <string name="global_actions" product="tv">Tëleesoptiounen</string>
+ <string name="global_actions" product="default">Telefonsoptiounen</string>
+ <string name="global_action_lock">Schiermspär</string>
+ <string name="global_action_power_off">Ausmaachen</string>
+ <string name="global_action_bug_report">Feelerbericht</string>
+ <string name="bugreport_title">Feelerbericht maachen</string>
+ <string name="bugreport_message">Bei dësem Feelerbericht ginn Daten iwwer den aktuelle Status vum Apparat erfaasst an als E-Mail verschéckt. Vum Start vum Bericht bis bei d\'Verschécke kann et ee Moment daueren; ee Moment Gedold.</string>
+ <string name="global_action_toggle_silent_mode">Stëlle Modus</string>
+ <string name="global_action_silent_mode_on_status">Den Toun ass AUS</string>
+ <string name="global_action_silent_mode_off_status">Den Toun ass UN</string>
+ <string name="global_actions_toggle_airplane_mode">Fligermodus</string>
+ <string name="global_actions_airplane_mode_on_status">Fligermodus ass UN</string>
+ <string name="global_actions_airplane_mode_off_status">Fligermodus ass AUS</string>
+ <string name="global_action_settings">Astellungen</string>
+ <string name="global_action_lockdown">Elo spären</string>
+ <string name="status_bar_notification_info_overflow">999+</string>
+ <string name="safeMode">Séchere Modus</string>
+ <string name="android_system_label">Android-System</string>
+ <string name="managed_profile_label">Aarbecht</string>
+ <string name="permgrouplab_calendar">Kalenner</string>
+ <string name="permgrouplab_sms">SMS</string>
+ <string name="permgrouplab_storage">Späicher</string>
+ <string name="permgrouplab_microphone">Mikro</string>
+ <string name="permgroupdesc_microphone">Toun ophuelen</string>
+ <string name="permgrouplab_camera">Fotoapparat</string>
+ <string name="permgrouplab_phone">Telefon</string>
+ <string name="capability_title_canRetrieveWindowContent">Fënsterinhalter ofruffen</string>
+ <string name="capability_desc_canRetrieveWindowContent">D\'Inhalter vun der Fënster mat där s du interagéiers ginn ofgeruff.</string>
+ <string name="capability_title_canRequestTouchExploration">\"Drécken an Entdecken\" aktivéieren</string>
+ <string name="capability_desc_canRequestTouchExploration">Beréiert Elementer gi virgelies an de Schierm ka mat Gesten entdeckt ginn.</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility">Verbessert Web-Benotzbarkeet uschalten</string>
+ <string name="capability_desc_canRequestEnhancedWebAccessibility">Skripter kënnen installéiert ginn, fir den Zougrëff op App-Inhalter ze vereinfachen.</string>
+ <string name="capability_title_canRequestFilterKeyEvents">Text observéieren deen s du agëss</string>
+ <string name="capability_desc_canRequestFilterKeyEvents">Huet perséinlech Date wéi Kreditkaartennummeren a Passwierder als Inhalt.</string>
+ <string name="permlab_statusBar">Statusläischt desaktivéieren oder änneren</string>
+ <string name="permdesc_statusBar">Erlaabt der App, d\'Statusläischt ze desaktivéieren oder System-Symbolbiller dobäizesetzen oder ze läschen.</string>
+ <string name="permlab_statusBarService">Statusläischt</string>
+ <string name="permdesc_statusBarService">Erlaabt der App, d\'Statusläischt ze sinn.</string>
+ <string name="permlab_expandStatusBar">Statusläischt op-/zouklappen</string>
+ <string name="permdesc_expandStatusBar">Erlaabt der App, d\'Statusläischt aus- oder zesummenzeklappen.</string>
+ <string name="permlab_install_shortcut">Ofkierzungen installéieren</string>
+ <string name="permdesc_install_shortcut">Erlaabt der App, Ofkierzungen ouni Benotzeragrëff op de Startschierm ze setzen.</string>
+ <string name="permlab_uninstall_shortcut">Ofkierzungen desinstalléieren</string>
+ <string name="permdesc_uninstall_shortcut">Erlaabt der App, Ofkierzungen ouni Benotzeragrëff vum Startschierm ze läschen.</string>
+ <string name="permlab_processOutgoingCalls">Erausgoend Uriff ëmleeden</string>
+ <string name="permdesc_processOutgoingCalls">Erlaabt der App, ze gesi wéi eng Nummer grad gewielt gëtt an erméiglecht den Uruff op eng aner Nummer ëmzeleeden oder den Uruff ofzebriechen.</string>
+ <string name="permlab_receiveSms">SMSen empfänken</string>
+ <string name="permdesc_receiveSms">Erlaabt der App, SMSen z\'empfänken an ze veraarbechten. Dat bedeit datt d\'App Messagen déi s du geschéckt kriss iwwerwaachen oder läsche kann ouni datt s du se gesäis.</string>
+ <string name="permlab_receiveMms">MMSen empfänken</string>
+ <string name="permdesc_receiveMms">Erlaabt der App, MMSen z\'empfänken an ze veraarbechten. Dat bedeit datt d\'App Messagen déi s du geschéckt kriss iwwerwaachen oder läsche kann ouni datt s du se gesäis.</string>
+ <string name="permlab_readCellBroadcasts">Messagë vun Zelliwwerdrounge liesen</string>
+ <string name="permlab_subscribedFeedsRead">Abonnéiert Feeds liesen</string>
+ <string name="permdesc_subscribedFeedsRead">Erlaabt der App, Detailer iwwer déi momentan synchroniséiert Feeds ofzeruffen.</string>
+ <string name="permdesc_sendSms">Erlaabt der App, SMSen ze schécken. Doduerch kéinten onerwaart Käschten entstoen. Béiswëlleg Appe kéinten dech Sue kaschten andeem se Messagen ouni deng Bestätegung verschécken.</string>
+ <string name="permlab_readSms">SMSen oder MMSe liesen</string>
+ <string name="permdesc_readSms" product="tablet">Erlaabt der App, SMSen ze liesen déi um Tablet oder op der SIM-Kaart gespäichert sinn. Doduerch kann d\'App all d\'SMSe liesen, onofhängeg vum Inhalt an egal wéi vertraulech se sinn.</string>
+ <string name="permdesc_readSms" product="tv">Erlaabt der App SMSen ze liesen déi op der Tëlee oder op der SIM-Kaart gespäichert sinn. Doduerch kann d\'App all d\'SMSe liesen, onofhängeg vum Inhalt an egal wéi confidentiell se sinn.</string>
+ <string name="permdesc_readSms" product="default">Erlaabt der App, SMSen ze liesen déi um Telefon oder op der SIM-Kaart gespäichert sinn. Doduerch kann d\'App all d\'SMSe liesen, onofhängeg vum Inhalt an egal wéi vertraulech se sinn.</string>
+ <string name="permlab_receiveWapPush">Textmessagen (WAP) empfänken</string>
+ <string name="permdesc_receiveWapPush">Erlaabt der App, WAP-Messagen z\'empfänken an ze beaarbechten. Dës Berechtegung huet d\'Fäegkeet, Messagen déi s du geschéckt kriss z\'iwwerwaachen oder ze läschen, ouni datt s du se ze gesi kriss.</string>
+ <string name="permlab_getTasks">Lafend Appen ausliesen</string>
+ <string name="permdesc_getTasks">Erlaabt der App, Informatiounen iwwer Aufgaben ofzeruffen déi grad lafen oder viru kuerzem gelaf sinn. Dat kéint der App erméiglechen, Informatiounen z\'entdecken iwwer d\'Appen déi um Apparat benotzt ginn.</string>
+ <string name="permlab_reorderTasks">Lafend Appen ëmzortéieren</string>
+ <string name="permdesc_reorderTasks">Erlaabt der App, Aufgabe vum Virgrond an den Hannergrond ze réckelen. D\'App kéint dat ouni däin Awierke maachen.</string>
+ <string name="permlab_enableCarMode">Automodus aktivéieren</string>
+ <string name="permdesc_enableCarMode">Der App erlaben den Automodus z\'aktivéieren.</string>
+ <string name="permlab_killBackgroundProcesses">Aner Appen zoumaachen</string>
+ <string name="permdesc_killBackgroundProcesses">Erlaabt der App, Hannergrondprozesser vun aneren Appen zouzemaachen. Doduerch kéinten aner Appen ophale mat funktionéieren.</string>
+ <string name="permlab_systemAlertWindow">Iwwer aner Appen uweisen</string>
+ <string name="permdesc_systemAlertWindow">Erlaabt der App, fir iwwer aner Applikatiounen oder Deeler vum Benotzerinterface ze zeechnen. Dat kéint mat denge Benotzungsgewunneschten interferéieren, oder ännere wat s du an aneren Appe mengs ze gesinn.</string>
+ <string name="permlab_persistentActivity">App permanent ausféieren</string>
+ <string name="permdesc_persistentActivity" product="tablet">Erlaabt der App, Deeler vu sech selwer am Späicher ze persistéieren. Dat kann de Späicher dee fir aner Appen disponibel ass limitéieren an doduerch den Tablet méi lues maachen.</string>
+ <string name="permdesc_persistentActivity" product="tv">Erlaabt der App, Deeler vu sech selwer am Späicher ze persistéieren. Dat kann de Späicher dee fir aner Appen disponibel ass limitéieren an doduerch d\'Tëlee méi lues maachen.</string>
+ <string name="permdesc_persistentActivity" product="default">Erlaabt der App, Deeler vu sech selwer am Späicher ze persistéieren. Dat kann de Späicher dee fir aner Appen disponibel ass limitéieren an doduerch den Telefon méi lues maachen.</string>
+ <string name="permlab_getPackageSize">Späicherplaz vun Appe moossen</string>
+ <string name="permdesc_getPackageSize">Erlaabt der App, säi Code, seng Daten a seng Tëschespäicher-Gréissten auszeliesen</string>
+ <string name="permlab_writeSettings">Systemastellungen änneren</string>
+ <string name="permdesc_writeSettings">Erlaabt der App, d\'Systemastellungsdaten z\'änneren. Béisaarteg Appe kéinten doduerch d\'Konfiguratioun vun dengem System beschiedegen.</string>
+ <string name="permlab_receiveBootCompleted">Beim Start ausféieren</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet">Erlaabt der App, sech selwer ze starte soubal de System fäerdeg gelueden ass. Doduerch kéint den Tablet méi laang brauche fir ze starten an d\'App kéint de gesamten Tablet méi lues maache wa se stänneg leeft.</string>
+ <string name="permdesc_receiveBootCompleted" product="tv">Erlaabt der App sech selwer ze starte soubal de System fäerdeg gelueden ass. Doduerch kéint d\'Tëlee méi laang brauche fir ze starten an d\'App kéint déi gesamt Tëlee méi lues maache wa se stänneg leeft.</string>
+ <string name="permdesc_receiveBootCompleted" product="default">Erlaabt der App, sech selwer ze starte soubal de System fäerdeg gelueden ass. Doduerch kéint den Telefon méi laang brauche fir ze starten an d\'App kéint de gesamten Telefon méi lues maache wa se stänneg leeft.</string>
+ <string name="permlab_broadcastSticky">Dauerhafte Broadcast schécken</string>
+ <string name="permdesc_broadcastSticky" product="tablet">Erlaabt der App, dauerhaft Broadcasten ze schécken, déi no der Iwwerdroung bestoe bleiwen. Exzessiv Benotzung kéint den Tablet méi lues oder instabil maachen, andeem ze vill Späicher benotzt gëtt.</string>
+ <string name="permdesc_broadcastSticky" product="tv">Erlaabt der App, dauerhaft Broadcasten ze schécken, déi no der Iwwerdroung bestoe bleiwen. Exzessiv Benotzung kéint d\'Tëlee méi lues oder instabil maachen, andeem ze vill Späicher benotzt gëtt.</string>
+ <string name="permdesc_broadcastSticky" product="default">Erlaabt der App, dauerhaft Broadcasten ze schécken, déi no der Iwwerdroung bestoe bleiwen. Exzessiv Benotzung kéint den Telefon méi lues oder instabil maachen, andeem ze vill Späicher benotzt gëtt.</string>
+ <string name="permlab_readContacts">Kontakter liesen</string>
+ <string name="permdesc_readContacts" product="tablet">Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Tablet gespäichert sinn ze liesen, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten z\'änneren, a béisaarteg Appe kéinte Kontaktdaten ouni däi Wëssen deelen.</string>
+ <string name="permdesc_readContacts" product="tv">Erlaabt der App, Daten iwwer d\'Kontakter déi op denger Tëlee gespäichert sinn ze liesen, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten z\'änneren, a béisaarteg Appe kéinte Kontaktdaten ouni däi Wëssen deelen.</string>
+ <string name="permdesc_readContacts" product="default">Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Telefon gespäichert sinn ze liesen, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten z\'änneren, a béisaarteg Appe kéinte Kontaktdaten ouni däi Wëssen deelen.</string>
+ <string name="permlab_writeContacts">Kontakter änneren</string>
+ <string name="permdesc_writeContacts" product="tablet">Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Tablet gespäichert sinn z\'änneren, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten ze läschen.</string>
+ <string name="permdesc_writeContacts" product="tv">Erlaabt der App, Daten iwwer d\'Kontakter déi op denger Tëlee gespäichert sinn z\'änneren, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten ze läschen.</string>
+ <string name="permdesc_writeContacts" product="default">Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Telefon gespäichert sinn z\'änneren, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten ze läschen.</string>
+ <string name="permlab_readCallLog">Urufflëscht liesen</string>
+ <string name="permdesc_readCallLog" product="tablet">Erlaabt der App, d\'Urufflëscht vum Tablet auszeliesen, inklusiv Daten iwwer erakommend an erausgoend Uriff. Dës Berechtegung erlaabt et Appen, d\'Daten aus denger Urufflëscht ze späicheren, a béisaarteg Appe kéinten dës Daten ouni däi Wëssen deelen.</string>
+ <string name="permdesc_readCallLog" product="tv">Erlaabt der App, d\'Urufflëscht vun der Tëlee auszeliesen, inklusiv Daten iwwer erakommend an erausgoend Uriff. Dës Berechtegung erlaabt et Appen, d\'Daten aus denger Urufflëscht ze späicheren, a béisaarteg Appe kéinten dës Daten ouni däi Wëssen deelen.</string>
+ <string name="permdesc_readCallLog" product="default">Erlaabt der App, d\'Urufflëscht vum Telefon auszeliesen, inklusiv Daten iwwer erakommend an erausgoend Uriff. Dës Berechtegung erlaabt et Appen, d\'Daten aus denger Urufflëscht ze späicheren, a béisaarteg Appe kéinten dës Daten ouni däi Wëssen deelen.</string>
+ <string name="permlab_writeCallLog">Urufflëscht änneren</string>
+ <string name="permdesc_writeCallLog" product="tablet">Erlaabt der App, d\'Urufflëscht vum Tablet z\'änneren, inklusiv Daten iwwer erakommend an erausgoend Uriff. Béisaarteg Appe kéinten dës Berechtegung benotze fir d\'Daten ouni däi Wëssen ze läschen oder z\'änneren.</string>
+ <string name="permdesc_writeCallLog" product="tv">Erlaabt der App, d\'Urufflëscht vun der Tëlee z\'änneren, inklusiv Daten iwwer erakommend an erausgoend Uriff. Béisaarteg Appe kéinten dës Berechtegung benotze fir d\'Daten ouni däi Wëssen ze läschen oder z\'änneren.</string>
+ <string name="permdesc_writeCallLog" product="default">Erlaabt der App, d\'Urufflëscht vum Telefon z\'änneren, inklusiv Daten iwwer erakommend an erausgoend Uriff. Béisaarteg Appe kéinten dës Berechtegung benotze fir d\'Daten ouni däi Wëssen ze läschen oder z\'änneren.</string>
+ <string name="permlab_bodySensors">Kierpersensoren (wéi e Bolsmiesser)</string>
+ <string name="permdesc_bodySensors" product="default">Erlaabt der App, op d\'Date vu Sensoren zouzegräifen, déi deng kierperlech Verfaassung iwwerwaachen, z. B. däi Puls.</string>
+ <string name="permlab_readCalendar">Kalenner-Rendezvousen a vertraulech Informatioune liesen</string>
+ <string name="permdesc_readCalendar" product="tablet">Erlaabt der App, all d\'Kalenner-Evenementer déi um Tablet gespäichert sinn ze liesen, inklusiv deene vu Frënn a Mataarbechter. Doduerch kéint d\'App deng Kalennerdate späicheren oder deelen, onofhängeg vun der agestallter Konfidentialitéit.</string>
+ <string name="permdesc_readCalendar" product="tv">Erlaabt der App, all d\'Kalenner-Evenementer déi op der Tëlee gespäichert sinn ze liesen, inklusiv deene vu Frënn a Mataarbechter. Doduerch kéint d\'App deng Kalennerdate späicheren oder deelen, onofhängeg vun der agestallter Konfidentialitéit.</string>
+ <string name="permdesc_readCalendar" product="default">Erlaabt der App, all d\'Kalenner-Evenementer déi um Telefon gespäichert sinn ze liesen, inklusiv deene vu Frënn a Mataarbechter. Doduerch kéint d\'App deng Kalennerdate späicheren oder deelen, onofhängeg vun der agestallter Konfidentialitéit.</string>
+ <string name="permlab_writeCalendar">Kalenner-Rendezvousen dobäisetzen oder änneren an E-Mailen u Gäscht ouni d\'Wësse vun de Benotzer schécken</string>
+ <string name="permdesc_writeCalendar" product="tablet">Erlaabt der App, Rendezvousen, déi s du op dengem Tablet ännere kanns, dobäizesetzen, ze läschen an z\'änneren, inklusiv deene vu Frënn oder Kollegen. Doduerch kann d\'App Noriichte verschécken, déi sou ausgesi wéi wa se vum Besëtzer vum Kalenner géife stamen, oder Rendezvousen änneren ouni datt de Besëtzer et matkritt.</string>
+ <string name="permdesc_writeCalendar" product="tv">Erlaabt der App, Rendezvousen, déi s du op denger Tëlee ännere kanns, dobäizesetzen, ze läschen an z\'änneren, inklusiv deene vu Frënn oder Kollegen. Doduerch kann d\'App Noriichte verschécken, déi sou ausgesi wéi wa se vum Besëtzer vum Kalenner géife stamen, oder Rendezvousen änneren ouni datt de Besëtzer et matkritt.</string>
+ <string name="permdesc_writeCalendar" product="default">Erlaabt der App, Rendezvousen, déi s du op dengem Telefon ännere kanns, dobäizesetzen, ze läschen an z\'änneren, inklusiv deene vu Frënn oder Kollegen. Doduerch kann d\'App Noriichte verschécken, déi sou ausgesi wéi wa se vum Besëtzer vum Kalenner géife stamen, oder Rendezvousen änneren ouni datt de Besëtzer et matkritt.</string>
+ <string name="permlab_accessLocationExtraCommands">Op zousätzlech Serviceproviderbefeeler fir de Standuert zougräifen</string>
+ <string name="permlab_accessFineLocation">Genaue Standuert (GPS- an Netzwierk-baséiert)</string>
+ <string name="permdesc_accessFineLocation">Erlaabt der App, iwwer de Globale Positionéierungs-System (GPS) oder iwwer Netzwierkquelle wéi Funkmasten oder WLAN däi genaue Standuert ze bestëmmen. Dës Standuert-Servicer mussen ugeschalt a fir däin Apparat disponibel si fir datt d\'App se ka benotzen. Appe kéinten dat benotze fir ze bestëmme wou s de dech ophäls, an doduerch zousätzlech Akkuleeschtung beusprochen.</string>
+ <string name="permlab_accessCoarseLocation">Ongeféiere Standuert (Netzwierk-baséiert)</string>
+ <string name="permdesc_accessCoarseLocation">Erlaabt der App, däin ongeféiere Standuert ze bestëmmen. De Standuert gëtt unhand vun Netzwierkstanduertquellen, wéi Funkmasten oder WLAN ofgeleent. Dës Standuert-Servicer mussen ugeschalt a fir däin Apparat disponibel si fir datt d\'App se ka benotzen. Appe kéinten dat benotze fir ze bestëmme wou ongeféier s de dech ophäls.</string>
+ <string name="permlab_modifyAudioSettings">Tounastellungen änneren</string>
+ <string name="permdesc_modifyAudioSettings">Erlaabt der App, déi global Audioastellungen ze steieren, z. B. d\'Lautstäerkt oder wéi ee Lautsprecher benotzt soll ginn.</string>
+ <string name="permlab_recordAudio">Toun ophuelen</string>
+ <string name="permdesc_recordAudio">Erlaabt der App, Toun mam Mikro opzehuelen. Dës Berechtegung erlaabt der App zu all Moment Toun ouni deng Bestätegung opzehuelen.</string>
+ <string name="permlab_sim_communication">SIM-Kommunikatioun</string>
+ <string name="permdesc_sim_communication">Erlaabt der App, Befeeler un d\'SIM ze schécken. Dat ass immens geféierlech.</string>
+ <string name="permlab_camera">Biller a Videoen ophuelen</string>
+ <string name="permdesc_camera">Erlaabt der App, Biller a Videoe mat der Kamera opzehuelen. Dës Berechtegung erlaabt der App, d\'Kamera zu all Moment ouni däin Awierken ze benotzen.</string>
+ <string name="permlab_vibrate">Vibratioun steieren</string>
+ <string name="permdesc_vibrate">Erlaabt der App, d\'Vibratioun ze steieren.</string>
+ <string name="permlab_flashlight">Täscheluucht steieren</string>
+ <string name="permdesc_flashlight">Erlaabt der App, d\'Täscheluucht ze steieren.</string>
+ <string name="permlab_callPhone">Telefonsnummeren direkt uruffen</string>
+ <string name="permdesc_callPhone">Erlaabt der App, Telefonsnummeren ouni deng Awierkung unzeruffen. Doduerch kéinten onerwaart Käschten oder Uriff entstoen. D\'App kann heiduerch awer keng Noutfallnummeren uruffen. Béiswëlleg Appe kéinte Käschte verursaachen andeem se Nummeren ouni deng Bestätegung uruffen.</string>
+ <string name="permlab_readPhoneState">Status an Identitéit vum Telefon liesen</string>
+ <string name="permdesc_readPhoneState">Erlaabt der App, op d\'Telefonsfunktioune vum Apparat zouzegräifen. Mat dëser Berechtegung kann d\'App d\'Telefonsnummer an d\'Identifikatiounsnummer vum Apparat, a wann en Uruff aktiv ass och d\'Telefonsnummer vum Gespréichspartner, ausliesen.</string>
+ <string name="permlab_wakeLock" product="tablet">Tablet vum Schlofen ofhalen</string>
+ <string name="permlab_wakeLock" product="tv">Rouzoustand vun der Tëlee ze desaktivéieren</string>
+ <string name="permlab_wakeLock" product="default">Telefon vum Schlofen ofhalen</string>
+ <string name="permdesc_wakeLock" product="tablet">Erlaabt der App, den Tablet dorun ze hënneren an de Rouzoustand ze wiesselen.</string>
+ <string name="permdesc_wakeLock" product="tv">Erlaabt der App d\'Tëlee dorun ze hënneren an de Rouzoustand ze wiesselen.</string>
+ <string name="permdesc_wakeLock" product="default">Erlaabt der App, den Telefon dorun ze hënneren an de Rouzoustand ze wiesselen.</string>
+ <string name="permlab_transmitIr">Infrarout iwwerdroen</string>
+ <string name="permdesc_transmitIr" product="tablet">Erlaabt der App, den Infrarout-Sender vum Tablet ze benotzen.</string>
+ <string name="permdesc_transmitIr" product="tv">Erlaabt der App, den Infrarout-Sender vun der Tëlee ze benotzen.</string>
+ <string name="permdesc_transmitIr" product="default">Erlaabt der App, den Infrarout-Sender vum Telefon ze benotzen.</string>
+ <string name="permlab_setWallpaper">Hannergrondbild setzen</string>
+ <string name="permdesc_setWallpaper">Erlaabt der App, d\'Hannergrondbild vum System ze setzen.</string>
+ <string name="permlab_setWallpaperHints">Gréisst vum Hannergrondbild ajustéieren</string>
+ <string name="permdesc_setWallpaperHints">Erlaabt der App, d\'Gréisstenhiwäiser fir d\'Systemhannergrondbiller ze definéieren.</string>
+ <string name="permlab_setTimeZone">Zäitzon setzen</string>
+ <string name="permdesc_setTimeZone" product="tablet">Erlaabt der App, d\'Zäitzon vum Tablet z\'änneren.</string>
+ <string name="permdesc_setTimeZone" product="tv">Erlaabt der App, d\'Zäitzon vun der Tëlee z\'änneren.</string>
+ <string name="permdesc_setTimeZone" product="default">Erlaabt der App, d\'Zäitzon vum Telefon z\'änneren.</string>
+ <string name="permlab_getAccounts">Konten op dësem Apparat sichen</string>
+ <string name="permdesc_getAccounts" product="tablet">Erlaabt der App, eng Lëscht vun de Konten auszeliesen déi dem Tablet bekannt sinn. Dat kéint Konten aschléissen, déi vun Appen ugeluecht goufen, déi s du installéiert hues.</string>
+ <string name="permdesc_getAccounts" product="tv">Erlaabt der App, eng Lëscht vun de Konten auszeliesen déi der Tëlee bekannt sinn. Dat kéint Konten aschléissen, déi vun Appen ugeluecht goufen, déi s du installéiert hues.</string>
+ <string name="permdesc_getAccounts" product="default">Erlaabt der App, eng Lëscht vun de Konten auszeliesen déi dem Telefon bekannt sinn. Dat kéint Konten aschléissen, déi vun Appen ugeluecht goufen, déi s du installéiert hues.</string>
+ <string name="permlab_accessNetworkState">Netzwierkconnectiounen ukucken</string>
+ <string name="permdesc_accessNetworkState">Erlaabt der App, Informatiounen iwwer Netzwierkconnectiounen auszeliesen, wéi z. B. wéi eng Netzwierker existéieren a wéi eng verbonne sinn.</string>
+ <string name="permlab_createNetworkSockets">Vollen Netzwierkzougrëff</string>
+ <string name="permdesc_createNetworkSockets">Erlaabt der App, Netzwierk-Sockets z\'erstellen an eegen Netzwierkprotokoller ze benotzen. De Browser an aner Appe bidde Méiglechkeeten, Daten iwwer den Internet ze verschécken. Dohier ass dës Berechtegung net néideg fir Daten iwwer den Internet ze schécken.</string>
+ <string name="permlab_changeNetworkState">Netzwierk-Connectivitéit änneren</string>
+ <string name="permdesc_changeNetworkState">Erlaabt der App, de Status vun der Netzwierkconnectivitéit z\'änneren.</string>
+ <string name="permlab_changeTetherState">Gethethert Connectivitéit änneren</string>
+ <string name="permdesc_changeTetherState">Erlaabt der App, de Status vun der getetherter Netzwierkconnectivitéit z\'änneren.</string>
+ <string name="permlab_accessWifiState">WLAN-Connectiounen uweisen</string>
+ <string name="permdesc_accessWifiState">Erlaabt der App, Informatiounen iwwer d\'WLAN-Netzwierker auszeliesen. Beispillsweis ob WLAN un ass a wéi eng Nimm déi connectéiert WLAN-Apparater hunn.</string>
+ <string name="permlab_changeWifiState">WLAN-Connectiounen hierstellen an trennen</string>
+ <string name="permdesc_changeWifiState">Erlaabt der App, Connectioune mat WLAN-Zougankspunkten hierzestellen an ze trennen a fir Ännerungen un der Konfiguratioun vun de WLAN-Netzwierker virzehuelen.</string>
+ <string name="permlab_changeWifiMulticastState">WLAN-Multicast-Empfang erlaben</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet">Erlaabt der App, Päck z\'empfänken, déi iwwer Multicast-Adressen u sämtlech Apparater an engem WLAN verschéckt ginn, net just un däin Tablet. Dat kascht méi Leeschtung wéi den Net-Multicast-Modus.</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv">Erlaabt der App, Päck z\'empfänken, déi iwwer Multicast-Adressen u sämtlech Apparater an engem WLAN verschéckt ginn, net just un deng Tëlee. Dat kascht méi Leeschtung wéi den Net-Multicast-Modus.</string>
+ <string name="permdesc_changeWifiMulticastState" product="default">Erlaabt der App, Päck z\'empfänken, déi iwwer Multicast-Adressen u sämtlech Apparater an engem WLAN verschéckt ginn, net just un däin Telefon. Dat kascht méi Leeschtung wéi den Net-Multicast-Modus.</string>
+ <string name="permlab_bluetoothAdmin">Op d\'Bluetooth-Astellungen zougräifen</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet">Erlaabt der App, Bluetooth um Tablet ze konfiguréieren, an anerer Apparater z\'entdecken a Koppelunge mat hinnen hierzestellen.</string>
+ <string name="permdesc_bluetoothAdmin" product="tv">Erlaabt der App, Bluetooth opo der Tëlee ze konfiguréieren, an anerer Apparater z\'entdecken a Koppelunge mat hinnen hierzestellen.</string>
+ <string name="permdesc_bluetoothAdmin" product="default">Erlaabt der App, Bluetooth um Telefon ze konfiguréieren, an anerer Apparater z\'entdecken a Koppelunge mat hinnen hierzestellen.</string>
+ <string name="permlab_accessWimaxState">WiMAX-Connectiounen hierstellen an trennen</string>
+ <string name="permdesc_accessWimaxState">Erlaabt der App, festzestellen ob WiMAX aktivéiert ass an Informatiounen iwwer all WiMAX-Netzwierker déi connectéiert sinn.</string>
+ <string name="permlab_changeWimaxState">WiMAX-Status änneren</string>
+ <string name="permdesc_changeWimaxState" product="tablet">Erlaabt der App, den Tablet mat WiMAX-Netzwierker ze connectéieren an deconnectéieren.</string>
+ <string name="permdesc_changeWimaxState" product="tv">Erlaabt der App, eng Connectioun tëscht der Tëlee a WiMAX-Netzwierker z\'erstellen an ze trennen.</string>
+ <string name="permdesc_changeWimaxState" product="default">Erlaabt der App, den Telefon mat WiMAX-Netzwierker ze connectéieren an deconnectéieren.</string>
+ <string name="permlab_bluetooth">Mat Bluetooth-Apparater koppelen</string>
+ <string name="permdesc_bluetooth" product="tablet">Erlaabt der App, d\'Bluetooth-Konfiguratioun um Tablet ze liesen, a Connectioune mat gekoppelten Apparater hierzestellen.</string>
+ <string name="permdesc_bluetooth" product="tv">Erlaabt der App, d\'Bluetooth-Konfiguratioun op der Tëlee ze liesen, a Connectioune mat gekoppelten Apparater hierzestellen.</string>
+ <string name="permdesc_bluetooth" product="default">Erlaabt der App, d\'Bluetooth-Konfiguratioun um Telefon ze liesen, a Connectioune mat gekoppelten Apparater hierzestellen.</string>
+ <string name="permlab_nfc">No-Feld-Communicatioun (NFC) kontrolléieren</string>
+ <string name="permdesc_nfc">Erlaabt der App, iwwer No-Feld-Communicatioun (NFC) Badgen, Kaarten a Liesapparater ze kontrolléieren.</string>
+ <string name="permlab_disableKeyguard">Schiermspär desaktivéieren</string>
+ <string name="permdesc_disableKeyguard">Erlaabt der App, d\'Tastespär an déi liéiert Passwuertsécherheet ze desaktivéieren. Den Telefon desaktivéiert beispillsweis d\'Tastespär wann en Uruff erakënnt, a reaktivéiert se wann den Uruff ofgeschloss ass.</string>
+ <string name="permlab_readSyncSettings">Synchroniséierungsastellunge liesen</string>
+ <string name="permdesc_readSyncSettings">Erlaabt der App, d\'Synchroniséierungsastellunge fir e Kont ze liesen. Doduerch ka beispillsweis festgestallt ginn ob d\'Kontakter mat engem Kont synchroniséiert sinn.</string>
+ <string name="permlab_writeSyncSettings">Synchronisatioun un- an ausschalten</string>
+ <string name="permdesc_writeSyncSettings">Erlaabt der App, d\'Synchroniséierungsastellunge fir e Kont z\'änneren. Doduerch ka beispillsweis d\'Synchroniséierung vun de Kontakter mat engem Kont aktivéiert ginn.</string>
+ <string name="permlab_readSyncStats">Synchronisatiounsstatistike liesen</string>
+ <string name="permdesc_readSyncStats">Erlaabt der App, d\'Synchroniséierungs-Statistike fir ee Kont ze liesen, inklusiv dem Verlaf vun de Synchronisatiountsevenementer a wéi vill Date synchroniséiert ginn.</string>
+ <string name="permlab_sdcardRead" product="nosdcard">Inhalter vun dengem USB-Späicher liesen</string>
+ <string name="permlab_sdcardRead" product="default">Inhalter vun denger SD-Kaart liesen</string>
+ <string name="permdesc_sdcardRead" product="nosdcard">Erlaabt der App, d\'Inhalter vum USB-Späicher ze liesen.</string>
+ <string name="permdesc_sdcardRead" product="default">Erlaabt der App, d\'Inhalter vun der SD-Kaart ze liesen.</string>
+ <string name="permlab_sdcardWrite" product="nosdcard">Inhalter vum USB-Späicher änneren oder läschen</string>
+ <string name="permlab_sdcardWrite" product="default">Inhalter vun der SD-Kaart änneren oder läschen</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard">Erlaabt der App, op den USB-Späicher ze schreiwen.</string>
+ <string name="permdesc_sdcardWrite" product="default">Erlaabt der App, op d\'SD-Kaart ze schreiwen.</string>
+ <string name="permlab_use_sip">SIP-Uriff maachen/empfänken</string>
+ <string name="permdesc_use_sip">Erlaabt der App, SIP-Uriff ze maachen an entgéintzehuelen.</string>
+ <string name="permlab_register_sim_subscription">Nei SIM-Telekommunikatiounsverbindunge registréieren</string>
+ <string name="permdesc_register_sim_subscription">Erlaabt der App, nei SIM-Telekommunikatiounsverbindungen ze registréieren.</string>
+ <string name="permlab_register_call_provider">Nei Telekommunikatiounsverbindunge registréieren</string>
+ <string name="permdesc_register_call_provider">Erlaabt der App, nei SIM-Telekommunikatiounsverbindungen ze registréieren.</string>
+ <string name="permlab_connection_manager">Telekommunikatiounsverbindunge verwalten</string>
+ <string name="permdesc_connection_manager">Erlaabt der App, Telekommunikatiounsverbindungen ze verwalten.</string>
+ <string name="permlab_bind_incall_service">Mam Uruffschierm interagéieren</string>
+ <string name="permdesc_bind_incall_service">Erlaabt der App, ze kontrolléiere wien a wéi de Benotzer den Uruffschierm gesäit.</string>
+ <string name="permlab_bind_connection_service">Mat Telefonsservicer interagéieren</string>
+ <string name="permdesc_bind_connection_service">Erlaabt der App, mat Telefonsservicer z\'interagéieren, fir Uriff ze maachen/z\'empfänken.</string>
+ <string name="permlab_control_incall_experience">Uruffoptioune fir de Benotzer ubidden</string>
+ <string name="permdesc_control_incall_experience">Erlaabt der App, Uruffoptioune fir de Benotzer unzebidden.</string>
+ <string name="permlab_readNetworkUsageHistory">Historesch Netzwierkdate liesen</string>
+ <string name="permdesc_readNetworkUsageHistory">Erlaabt der App, historesch Netzwierkbenotzungsdate fir spezifesch Netzwierker an Appen ze liesen.</string>
+ <string name="permlab_manageNetworkPolicy">Netzwierkrichtlinne verwalten</string>
+ <string name="permdesc_manageNetworkPolicy">Erlaabt der App, Netzwierkrichtlinnen ze geréieren an App-spezifesch Regelen ze definéieren.</string>
+ <string name="permlab_modifyNetworkAccounting">Statistike vun der Netzwierkbenotzung änneren</string>
+ <string name="permdesc_modifyNetworkAccounting">Erlaabt der App, z\'ännere wéi d\'Netzwierkbenotzung vun aneren Appe gemooss gëtt. Net fir normal Appe geduecht.</string>
+ <string name="permlab_accessNotifications">Op Notifikatiounen zougräifen</string>
+ <string name="permdesc_accessNotifications">Erlaabt der App, Notifikatiounen z\'empfänken, z\'analyséieren an ze läschen, inklusiv deenen déi vun aneren Appe geschriwwe goufen.</string>
+ <string name="permlab_bindNotificationListenerService">Un en Notifikatiouns-Lauschter-Service ubannen</string>
+ <string name="permdesc_bindNotificationListenerService">Erlaabt der App, sech um ieweschten Niveau vun engem Notifikatiouns-Lauschter-Service unzebannen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_bindConditionProviderService">Un e Konditiounsubidder-Service ubannen</string>
+ <string name="permdesc_bindConditionProviderService">Erlaabt der App, sech um ieweschten Niveau vun engem Konditiounsubidder-Service unzebannen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_bindDreamService">Un en Dramservice ubannen</string>
+ <string name="permdesc_bindDreamService">Erlaabt der App, sech op ieweschtem Niveau un d\'Schnëttstell vun engem Dramservice unzebannen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_invokeCarrierSetup">Konfiguratiounsapp vum Provider opruffen</string>
+ <string name="permdesc_invokeCarrierSetup">Erlaabt dem Besëtzer, d\'Konfiguratiounsapp vum Provider opzeruffen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_accessNetworkConditions">Informatiounen iwwer d\'Netzwierkkonditiounen offänken</string>
+ <string name="permdesc_accessNetworkConditions">Erlaabt der App, Informatiounen zu den Netzwierkkonditiounen z\'erfaassen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_setInputCalibration">Kalibréierung fir Methode fir anzeginn änneren</string>
+ <string name="permdesc_setInputCalibration">Erlaabt der App d\'Kalibratiounsparametere vum Touchscreen z\'änneren. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_accessDrmCertificates">Op DRM-Zertifikater zougräifen</string>
+ <string name="permdesc_accessDrmCertificates">Erlaabt enger App, op DRM-Zertifikater zouzegräifen a se ze provisionéieren. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_handoverStatus">Android-Beam-Iwwerdroungsstatus empfänken</string>
+ <string name="permdesc_handoverStatus">Erlaabt der App, Informatiounen iwwer aktuell Android-Beam-Iwwerdroungen z\'empfänken</string>
+ <string name="permlab_removeDrmCertificates">DRM-Zertifikater läschen</string>
+ <string name="permdesc_removeDrmCertificates">Erlaabt enger App, DRM-Zertifikater ze läschen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="permlab_bindCarrierMessagingService">Un engem Provider-SMS/MMS-Service bannen</string>
+ <string name="permdesc_bindCarrierMessagingService">Erlaabt de Besëtzer an d\'Iwwerfläch vum SMS/MMS-Service-Provider op dem ieweschten Niveau ze bannen. Sollt ni fir normal Appen néideg sinn.</string>
+ <string name="policylab_limitPassword">Passwuertregelen definéieren</string>
+ <string name="policylab_watchLogin">Versich fir d\'Entspäre vum Schierm iwwerwaachen</string>
+ <string name="policydesc_watchLogin" product="tablet">Unzuel vun de falsche Passwierder beim Entspäre vum Schierm iwwerwaachen an den Tablet spären oder all d\'Daten um Tablet läsche wann ze dacks een e falscht Passwuert aginn huet.</string>
+ <string name="policydesc_watchLogin" product="TV">Unzuel vun de falsche Passwierder beim Entspäre vum Schierm iwwerwaachen an d\'Tlee spären oder all d\'Daten um Telefon läsche wann ze dacks een e falscht Passwuert aginn huet.</string>
+ <string name="policydesc_watchLogin" product="default">Unzuel vun de falsche Passwierder beim Entspäre vum Schierm iwwerwaachen an den Telefon spären oder all d\'Daten um Telefon läsche wann ze dacks een e falscht Passwuert aginn huet.</string>
+ <string name="policylab_forceLock">De Schierm spären</string>
+ <string name="policydesc_forceLock">Festleeë wéi a wéini de Schierm späert.</string>
+ <string name="policylab_wipeData">All Date läschen</string>
+ <string name="policydesc_wipeData" product="tablet">Ouni Warnung op d\'Wierksastellungen zrécksetzen an Date vum Tablet läschen.</string>
+ <string name="policydesc_wipeData" product="tv">Ouni Warnung op d\'Wierksastellungen zrécksetzen an Date vun der Tëlee läschen.</string>
+ <string name="policydesc_wipeData" product="default">Ouni Warnung op d\'Wierksastellungen zrécksetzen an Date vum Telefon läschen.</string>
+ <string name="policylab_setGlobalProxy">De globale Proxy-Server fir den Apparat festleeën</string>
+ <string name="policylab_encryptedStorage">Späicherverschlësselung</string>
+ <string name="policydesc_encryptedStorage">Gespäichert App-Date musse verschlësselt ginn.</string>
+ <string name="policylab_disableCamera">Kameraen desaktivéieren</string>
+ <string name="policydesc_disableCamera">D\'Benotzung vun alle Kameraen um Apparat verhënneren.</string>
+ <string-array name="phoneTypes">
+ <item>Doheem</item>
+ <item>Mobil</item>
+ <item>Aarbecht</item>
+ <item>Aarbechtsfax</item>
+ <item>Fax doheem</item>
+ <item>Pager</item>
+ <item>Aner</item>
+ <item>Personaliséiert</item>
+ </string-array>
+ <string-array name="emailAddressTypes">
+ <item>Doheem</item>
+ <item>Aarbecht</item>
+ <item>Aner</item>
+ <item>Personaliséiert</item>
+ </string-array>
+ <string-array name="postalAddressTypes">
+ <item>Doheem</item>
+ <item>Aarbecht</item>
+ <item>Aner</item>
+ <item>Personaliséiert</item>
+ </string-array>
+ <string-array name="imAddressTypes">
+ <item>Doheem</item>
+ <item>Aarbecht</item>
+ <item>Aner</item>
+ <item>Personaliséiert</item>
+ </string-array>
+ <string-array name="organizationTypes">
+ <item>Aarbecht</item>
+ <item>Aner</item>
+ <item>Personaliséiert</item>
+ </string-array>
+ <string-array name="imProtocols">
+ <item>AIM</item>
+ <item>Windows Live</item>
+ <item>Yahoo</item>
+ <item>Skype</item>
+ <item>QQ</item>
+ <item>Google Talk</item>
+ <item>ICQ</item>
+ <item>Jabber</item>
+ </string-array>
+ <string name="phoneTypeCustom">Personaliséiert</string>
+ <string name="phoneTypeHome">Doheem</string>
+ <string name="phoneTypeMobile">Mobil</string>
+ <string name="phoneTypeWork">Aarbecht</string>
+ <string name="phoneTypeFaxWork">Aarbechtsfax</string>
+ <string name="phoneTypeFaxHome">Fax doheem</string>
+ <string name="phoneTypePager">Pager</string>
+ <string name="phoneTypeOther">Aner</string>
+ <string name="phoneTypeCallback">Réckruff</string>
+ <string name="phoneTypeCar">Auto</string>
+ <string name="phoneTypeCompanyMain">Firma</string>
+ <string name="phoneTypeIsdn">ISDN</string>
+ <string name="phoneTypeMain">Haapt</string>
+ <string name="phoneTypeOtherFax">Anere Fax</string>
+ <string name="phoneTypeRadio">Radio</string>
+ <string name="phoneTypeTelex">Telex</string>
+ <string name="phoneTypeTtyTdd">TTY/TDD</string>
+ <string name="phoneTypeWorkMobile">Handy (Aarbecht)</string>
+ <string name="phoneTypeWorkPager">Pager (Aarbecht)</string>
+ <string name="phoneTypeAssistant">Assistent</string>
+ <string name="phoneTypeMms">MMS</string>
+ <string name="eventTypeCustom">Personaliséiert</string>
+ <string name="eventTypeBirthday">Gebuertsdag</string>
+ <string name="eventTypeAnniversary">Joresdag</string>
+ <string name="eventTypeOther">Aner</string>
+ <string name="emailTypeCustom">Personaliséiert</string>
+ <string name="emailTypeHome">Doheem</string>
+ <string name="emailTypeWork">Aarbecht</string>
+ <string name="emailTypeOther">Aner</string>
+ <string name="emailTypeMobile">Mobil</string>
+ <string name="postalTypeCustom">Personaliséiert</string>
+ <string name="postalTypeHome">Doheem</string>
+ <string name="postalTypeWork">Aarbecht</string>
+ <string name="postalTypeOther">Aner</string>
+ <string name="imTypeCustom">Personaliséiert</string>
+ <string name="imTypeHome">Doheem</string>
+ <string name="imTypeWork">Aarbecht</string>
+ <string name="imTypeOther">Aner</string>
+ <string name="imProtocolCustom">Personaliséiert</string>
+ <string name="imProtocolAim">AIM</string>
+ <string name="imProtocolMsn">Windows Live</string>
+ <string name="imProtocolYahoo">Yahoo</string>
+ <string name="imProtocolSkype">Skype</string>
+ <string name="imProtocolQq">QQ</string>
+ <string name="imProtocolGoogleTalk">Hangouts</string>
+ <string name="imProtocolIcq">ICQ</string>
+ <string name="imProtocolJabber">Jabber</string>
+ <string name="imProtocolNetMeeting">NetMeeting</string>
+ <string name="orgTypeWork">Aarbecht</string>
+ <string name="orgTypeOther">Aner</string>
+ <string name="orgTypeCustom">Personaliséiert</string>
+ <string name="relationTypeCustom">Personaliséiert</string>
+ <string name="relationTypeAssistant">Assistent</string>
+ <string name="relationTypeBrother">Brudder</string>
+ <string name="relationTypeChild">Kand</string>
+ <string name="relationTypeDomesticPartner">Liewenspartner</string>
+ <string name="relationTypeFather">Papp</string>
+ <string name="relationTypeFriend">Frënd</string>
+ <string name="relationTypeManager">Manager</string>
+ <string name="relationTypeMother">Mamm</string>
+ <string name="relationTypeParent">Elterendeel</string>
+ <string name="relationTypePartner">Partner</string>
+ <string name="relationTypeReferredBy">Recommandéiert vu(n)</string>
+ <string name="relationTypeRelative">Verwandten</string>
+ <string name="relationTypeSister">Schwëster</string>
+ <string name="relationTypeSpouse">Éierpartner</string>
+ <string name="sipAddressTypeCustom">Personaliséiert</string>
+ <string name="sipAddressTypeHome">Doheem</string>
+ <string name="sipAddressTypeWork">Aarbecht</string>
+ <string name="sipAddressTypeOther">Aner</string>
+ <string name="quick_contacts_not_available">Keng Applikatioun fonnt fir dëse Kontakt unzekucken.</string>
+ <string name="keyguard_password_enter_pin_code">PIN-Code aginn</string>
+ <string name="keyguard_password_enter_puk_code">PUK an neie PIN-Code aginn</string>
+ <string name="keyguard_password_enter_puk_prompt">PUK-Code</string>
+ <string name="keyguard_password_enter_pin_prompt">Neie PIN-Code</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">Drécke fir d\'Passwuert anzeginn</font></string>
+ <string name="keyguard_password_enter_password_code">Passwuert agi fir z\'entspären</string>
+ <string name="keyguard_password_enter_pin_password_code">PIN agi fir z\'entspären</string>
+ <string name="keyguard_password_wrong_pin_code">Falsche PIN-Code.</string>
+ <string name="keyguard_label_text">Menü an dann 0 drécke fir z\'entspären.</string>
+ <string name="emergency_call_dialog_number_for_display">Noutruffnummer</string>
+ <string name="lockscreen_carrier_default">Kee Service.</string>
+ <string name="lockscreen_screen_locked">Schierm gespaart.</string>
+ <string name="lockscreen_instructions_when_pattern_enabled">Menü drécke fir z\'entspären oder en Noutruff ze maachen.</string>
+ <string name="lockscreen_instructions_when_pattern_disabled">Menü drécke fir z\'entspären.</string>
+ <string name="lockscreen_pattern_instructions">Muster zeechne fir z\'entspären</string>
+ <string name="lockscreen_return_to_call">Zréck bei d\'Gespréich</string>
+ <string name="lockscreen_pattern_correct">Korrekt!</string>
+ <string name="lockscreen_pattern_wrong">Probéier nees</string>
+ <string name="lockscreen_password_wrong">Probéier nees</string>
+ <string name="faceunlock_multiple_failures">Maximal Versich fir mam Gesiicht z\'entspären iwwerschratt</string>
+ <string name="lockscreen_missing_sim_message_short">Keng SIM-Kaart</string>
+ <string name="lockscreen_missing_sim_message" product="tablet">Keng SIM-Kaart am Tablet.</string>
+ <string name="lockscreen_missing_sim_message" product="tv">Keng Sim-Kaart an der Tëlee.</string>
+ <string name="lockscreen_missing_sim_message" product="default">Keng SIM-Kaart am Telefon.</string>
+ <string name="lockscreen_missing_sim_instructions">SIM-Kaart asetzen.</string>
+ <string name="lockscreen_missing_sim_instructions_long">D\'SIM-Kaart feelt oder ass net liesbar. Setz eng SIM-Kaart an.</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short">Onbenotzbar SIM-Kaart.</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions">Deng SIM-Kaart gouf permanent ausgeschalt.\n
+Kontaktéier däi Provider fir eng aner SIM-Kaart ze kréien.</string>
+ <string name="lockscreen_transport_prev_description">Viregen Titel</string>
+ <string name="lockscreen_transport_next_description">Nächsten Titel</string>
+ <string name="lockscreen_transport_pause_description">Paus</string>
+ <string name="lockscreen_transport_play_description">Ofspillen</string>
+ <string name="lockscreen_transport_stop_description">Stopp</string>
+ <string name="lockscreen_transport_rew_description">Zréckspullen</string>
+ <string name="lockscreen_transport_ffw_description">Virspullen</string>
+ <string name="emergency_calls_only" msgid="2485604591272668370">Just Noutriff</string>
+ <string name="lockscreen_network_locked_message">Netzwierk gespaart</string>
+ <string name="lockscreen_sim_puk_locked_message">SIM-Kaart ass PUK-gespaart.</string>
+ <string name="lockscreen_sim_puk_locked_instructions">D\'Benotzerhandbuch ukucken oder de Clientsservice kontaktéieren.</string>
+ <string name="lockscreen_sim_locked_message">D\'SIM-Kaart ass gespaart.</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message">D\'SIM-Kaart gëtt entspaart\u2026</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gemoolt.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message">Du hues däi Passwuert <xliff:g id="number">%d</xliff:g>-mol falsch aginn.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message">Du hues däi PIN <xliff:g id="number">%d</xliff:g>-mol falsch aginn.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gezeechent. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich muss du däin Tablet mat denge Login-Date vu Google entspären.\n\nProbéier a(n) <xliff:g id="number">%d</xliff:g> Sekonnen nees.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tv">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>mol- falsch gezeechent. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich muss du deng Tëlee mat denge Login-Date vu Google entspären.\n\nProbéier a(n) <xliff:g id="number">%d</xliff:g> Sekonnen nees.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gezeechent. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich muss du däin Telefon mat denge Login-Date vu Google entspären.\n\nProbéier a(n) <xliff:g id="number">%d</xliff:g> Sekonnen nees.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv">Du hues <xliff:g id="number">%d</xliff:g> mol ouni Erfolleg versicht d\'Tëlee z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt deng Tëlee op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer.</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat.</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht d\'Tëlee z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat.</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat.</string>
+ <string name="lockscreen_too_many_failed_attempts_countdown">Probéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="lockscreen_forgot_pattern_button_text">Muster vergiess?</string>
+ <string name="lockscreen_glogin_forgot_pattern">Kont-Entspärung</string>
+ <string name="lockscreen_glogin_too_many_attempts">Ze vill Musterversich</string>
+ <string name="lockscreen_glogin_instructions">Fir z\'entspären, mell dech mat dengem Google-Kont un.</string>
+ <string name="lockscreen_glogin_username_hint">Benotzernumm (E-Mail)</string>
+ <string name="lockscreen_glogin_password_hint">Passwuert</string>
+ <string name="lockscreen_glogin_submit_button">Aloggen</string>
+ <string name="lockscreen_glogin_invalid_input">Ongëltege Benotzernumm oder Passwuert.</string>
+ <string name="lockscreen_glogin_account_recovery_hint">Benotzernumm oder Passwuert vergiess\?\nBesich <b>google.com/accounts/recovery</b>.</string>
+ <string name="lockscreen_glogin_checking_password">Iwwerpréiwung\u2026</string>
+ <string name="lockscreen_unlock_label">Entspären</string>
+ <string name="lockscreen_sound_on_label">Toun un</string>
+ <string name="lockscreen_sound_off_label">Toun aus</string>
+ <string name="lockscreen_access_pattern_start">Muster ugefaangen</string>
+ <string name="lockscreen_access_pattern_cleared">Muster geläscht</string>
+ <string name="lockscreen_access_pattern_cell_added">Zell dobäigesat</string>
+ <string name="lockscreen_access_pattern_detected">Muster ofgeschloss</string>
+ <string name="lockscreen_access_pattern_area" msgid="">Musterberäich.</string>
+ <string name="keyguard_accessibility_widget_changed">%1$s. Widget %2$d vu(n) %3$d.</string>
+ <string name="keyguard_accessibility_add_widget">Widget dobäisetzen.</string>
+ <string name="keyguard_accessibility_widget_empty_slot">Eidel</string>
+ <string name="keyguard_accessibility_unlock_area_expanded">Entspärberäich maximéiert.</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed">Entspärberäich miniméiert.</string>
+ <string name="keyguard_accessibility_widget"><xliff:g id="widget_index">%1$s</xliff:g> Widget.</string>
+ <string name="keyguard_accessibility_user_selector">Benotzerauswiel</string>
+ <string name="keyguard_accessibility_status">Status</string>
+ <string name="keyguard_accessibility_camera">Fotoapparat</string>
+ <string name="keygaurd_accessibility_media_controls">Steierelementer fir Medien</string>
+ <string name="keyguard_accessibility_widget_reorder_start">Neiuerdnung vun de Widgete gestart.</string>
+ <string name="keyguard_accessibility_widget_reorder_end">Neiuerdnung vun de Widgete gestoppt.</string>
+ <string name="keyguard_accessibility_widget_deleted">Widget <xliff:g id="widget_index">%1$s</xliff:g> geläscht.</string>
+ <string name="keyguard_accessibility_expand_lock_area">Erweider den Entspärberäich.</string>
+ <string name="keyguard_accessibility_slide_unlock">Entspäre mat Fangerbeweegung.</string>
+ <string name="keyguard_accessibility_pattern_unlock">Entspäre mat Muster.</string>
+ <string name="keyguard_accessibility_face_unlock">Entspäre mam Gesiicht.</string>
+ <string name="keyguard_accessibility_pin_unlock">Entspäre mat PIN.</string>
+ <string name="keyguard_accessibility_password_unlock">Entspäre mat Passwuert.</string>
+ <string name="keyguard_accessibility_pattern_area">Musterberäich.</string>
+ <string name="keyguard_accessibility_slide_area">Beräich fir Fangerbeweegung.</string>
+ <string name="password_keyboard_label_symbol_key">\?123</string>
+ <string name="password_keyboard_label_alpha_key">ABC</string>
+ <string name="password_keyboard_label_alt_key">ALT</string>
+ <string name="granularity_label_character">Zeechen</string>
+ <string name="granularity_label_word">Wuert</string>
+ <string name="granularity_label_link">Link</string>
+ <string name="granularity_label_line">Zeil</string>
+ <string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
+ <string name="hour_cap_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="PM">%p</xliff:g>"</string>
+ <string name="factorytest_failed">Wierkstest feelgeschloen</string>
+ <string name="factorytest_not_system">D\'FACTORY_TEST-Aktioun ass just ënnerstëtzt fir Päck déi am Dossier /system/app installéiert sinn.</string>
+ <string name="factorytest_no_action">Et gouf kee Pak fonnt deen d\'FACTORY_TEST-Aktioun zur Verfügung stellt.</string>
+ <string name="factorytest_reboot">Nei starten</string>
+ <string name="js_dialog_title">D\'Säit \"<xliff:g id="title">%s</xliff:g>\" seet:</string>
+ <string name="js_dialog_title_default">JavaScript</string>
+ <string name="js_dialog_before_unload_title">Navigatioun bestätegen</string>
+ <string name="js_dialog_before_unload_positive_button">Dës Säit verloossen</string>
+ <string name="js_dialog_before_unload_negative_button">Op dëser Säit bleiwen</string>
+ <string name="js_dialog_before_unload"><xliff:g id="message">%s</xliff:g>\n\nBass du sécher datt s du vun dëser Säit ewechnavigéiere wëlls?</string>
+ <string name="save_password_label">Bestätegen</string>
+ <string name="double_tap_toast">Tipp: Zweemol drécke fir eran- an erauszezoomen.</string>
+ <string name="autofill_this_form">Automatescht Ausfëllen</string>
+ <string name="setup_autofill">Automatescht Ausfëllen astellen</string>
+ <string name="autofill_address_name_separator">\u0020</string>
+ <string name="autofill_address_summary_name_format">$1$2$3</string>
+ <string name="autofill_address_summary_separator">,\u0020</string>
+ <string name="autofill_address_summary_format">$1$2$3</string>
+ <string name="autofill_attention_ignored_re">attention|attn</string>
+ <string name="autofill_region_ignored_re">province|region|other<!-- es -->|provincia<!-- pt-BR, pt-PT -->|bairro|suburb</string>
+ <string name="autofill_company_re">company|business|organization|organisation|department<!-- de-DE -->|firma|firmenname<!-- es -->|empresa<!-- fr-FR -->|societe|société<!-- it-IT -->|ragione.?sociale<!-- ja-JP -->|会社<!-- ru -->|название.?компании<!-- zh-CN -->|单位|公司</string>
+ <string name="autofill_address_line_1_re">address.?line|address1|addr1|street<!-- de-DE -->|strasse|straße|hausnummer|housenumber<!-- en-GB -->|house.?name<!-- es -->|direccion|dirección<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所1<!-- pt-BR, pt-PT -->|morada|endereço<!-- ru -->|Адрес<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_1_label_re">address<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_2_re">address.?line2|address2|addr2|street|suite|unit<!-- de-DE -->|adresszusatz|ergänzende.?angaben<!-- es -->|direccion2|colonia|adicional<!-- fr-FR -->|addresssuppl|complementnom|appartement<!-- it-IT -->|indirizzo2<!-- ja-JP -->|住所2</string>
+ <string name="autofill_address_line_3_re">address.?line3|address3|addr3|street|line3<!-- es -->|municipio<!-- fr-FR -->|batiment|residence<!-- it-IT -->|indirizzo3</string>
+ <string name="autofill_country_re">country|location<!-- ja-JP -->|国<!-- zh-CN -->|国家</string>
+ <string name="autofill_zip_code_re">zip|postal|post code|pcode|^1z$<!-- de-DE -->|postleitzahl<!-- es -->|cp<!-- fr-FR -->|cdp<!-- it-IT -->|cap<!-- ja-JP -->|郵便番号<!-- pt-BR, pt-PT -->|codigo|codpos|cep<!-- ru -->|Почтовый.?Индекс<!--zh-CN -->|邮政编码|邮编<!-- zh-TW -->|郵遞區號</string>
+ <string name="autofill_zip_4_re">zip|^-$|post2<!-- pt-BR, pt-PT -->|codpos2</string>
+ <string name="autofill_city_re">city|town<!-- de-DE -->|ort|stadt<!-- en-AU -->|suburb<!-- es -->|ciudad|provincia|localidad|poblacion<!-- fr-FR -->|ville|commune<!-- it-IT -->|localita<!-- ja-JP -->|市区町村<!-- pt-BR, pt-PT -->|cidade<!-- ru -->|Город<!-- zh-CN -->|市<!-- zh-TW -->|分區</string>
+ <string name="autofill_state_re">state|county|region|province<!-- de-DE -->|land<!-- en-UK -->|county|principality<!-- ja-JP -->|都道府県<!-- pt-BR, pt-PT -->|estado|provincia<!-- ru -->|область<!-- zh-CN -->|省<!-- zh-TW -->|地區</string>
+ <string name="autofill_address_type_same_as_re">same as</string>
+ <string name="autofill_address_type_use_my_re">use my</string>
+ <string name="autofill_billing_designator_re">bill</string>
+ <string name="autofill_shipping_designator_re">ship</string>
+ <string name="autofill_email_re">e.?mail<!-- ja-JP -->|メールアドレス<!-- ru -->|Электронной.?Почты<!-- zh-CN -->|邮件|邮箱<!-- zh-TW -->|電郵地址</string>
+ <string name="autofill_username_re">user.?name|user.?id<!-- de-DE -->|vollständiger.?name<!-- zh-CN -->|用户名</string>
+ <string name="autofill_name_re">^name|full.?name|your.?name|customer.?name|firstandlastname<!-- es -->|nombre.*y.*apellidos<!-- fr-FR -->|^nom<!-- ja-JP -->|お名前|氏名<!-- pt-BR, pt-PT -->|^nome<!-- zh-CN -->|姓名</string>
+ <string name="autofill_name_specific_re">^name<!-- fr-FR -->|^nom<!-- pt-BR, pt-PT -->|^nome</string>
+ <string name="autofill_first_name_re">irst.*name|initials|fname|first$<!-- de-DE -->|vorname<!-- es -->|nombre<!-- fr-FR -->|forename|prénom|prenom<!-- ja-JP -->|名<!-- pt-BR, pt-PT -->|nome<!-- ru -->|Имя</string>
+ <string name="autofill_middle_initial_re">middle.*initial|m\\.i\\.|mi$</string>
+ <string name="autofill_middle_name_re">middle.*name|mname|middle$<!-- es -->|apellido.?materno|lastlastname</string>
+ <string name="autofill_last_name_re">last.*name|lname|surname|last$<!-- de-DE -->|nachname<!-- es -->|apellidos<!-- fr-FR -->|famille|^nom<!-- it-IT -->|cognome<!-- ja-JP -->|姓<!-- pt-BR, pt-PT -->|morada|apelidos|surename|sobrenome<!-- ru -->|Фамилия</string>
+ <string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfono<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string>
+ <string name="autofill_area_code_re">area.*code|acode|area</string>
+ <string name="autofill_phone_prefix_re">prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
+ <string name="autofill_phone_suffix_re">suffix</string>
+ <string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string>
+ <string name="autofill_name_on_card_re">card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|karteninhaber<!-- es -->|nombre.*tarjeta<!-- fr-FR -->|nom.*carte<!-- it-IT -->|nome.*cart<!-- ja-JP -->|名前<!-- ru -->|Имя.*карты<!-- zh-CN -->|信用卡开户名|开户名|持卡人姓名<!-- zh-TW -->|持卡人姓名</string>
+ <string name="autofill_name_on_card_contextual_re">name</string>
+ <string name="autofill_card_cvc_re">verification|card identification|cvn|security code|cvv code|cvc</string>
+ <string name="autofill_card_number_re">number|card.?#|card.?no|ccnum<!-- de-DE -->|nummer<!-- es -->|credito|numero|número<!-- fr-FR -->|numéro<!-- ja-JP -->|カード番号<!-- ru -->|Номер.*карты<!-- zh-CN -->|信用卡号|信用卡号码<!-- zh-TW -->|信用卡卡號</string>
+ <string name="autofill_expiration_month_re">expir|exp.*month|exp.*date|ccmonth<!-- de-DE -->|gueltig|gültig|monat<!-- es -->|fecha<!-- fr-FR -->|date.*exp<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|月</string>
+ <string name="autofill_expiration_date_re">exp|^/|year<!-- de-DE -->|ablaufdatum|gueltig|gültig|yahr<!-- es -->|fecha<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|年|有效期</string>
+ <string name="autofill_card_ignored_re">^card</string>
+ <string name="autofill_fax_re">fax<!-- fr-FR -->|télécopie|telecopie<!-- ja-JP -->|ファックス<!-- ru -->|факс<!-- zh-CN -->|传真<!-- zh-TW -->|傳真</string>
+ <string name="autofill_country_code_re">country.*code|ccode|_cc</string>
+ <string name="autofill_area_code_notext_re">^\\($</string>
+ <string name="autofill_phone_prefix_separator_re">^-$|^\\)$</string>
+ <string name="autofill_phone_suffix_separator_re">^-$</string>
+ <string name="autofill_province">Provënz</string>
+ <string name="autofill_postal_code">Postleetzuel</string>
+ <string name="autofill_state">Staat</string>
+ <string name="autofill_zip_code">Postleetzuel</string>
+ <string name="autofill_county">Landkrees</string>
+ <string name="autofill_island">Insel</string>
+ <string name="autofill_district">Bezierk</string>
+ <string name="autofill_department">Departement</string>
+ <string name="autofill_prefecture">Präfektur</string>
+ <string name="autofill_parish">Gemeng</string>
+ <string name="autofill_area">Gebitt</string>
+ <string name="autofill_emirate">Emirat</string>
+ <string name="permlab_readHistoryBookmarks">Internet-Lieszeechen an däin Historique liesen</string>
+ <string name="permdesc_readHistoryBookmarks">Erlaabt der App, den Historique vun alle Säiten déi s de besicht hues an all dengem Browser seng Liesezeechen ze liesen. Hiwäis: dës Berechtegung gëtt eventuell net vu Browsere vun Drëtthiersteller oder aneren Appe mat Internetfäegkeete berücksichtegt.</string>
+ <string name="permlab_writeHistoryBookmarks">Internet-Lieszeeche schreiwen an den Historique änneren</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv">Erlaabt der App, den Historique oder d\'Lieszeechen déi vun dengem Browser op der Tëlee gespäichert sinn z\'änneren. Dat kéint der App erméiglechen, d\'Browserdaten z\'änneren oder ze läschen. Wichteg: Dës Berechtegung kéint vu Browseren oder aneren Appe vun Drëtthiersteller net berücksichtegt ginn.</string>
+ <string name="permlab_setAlarm">Wecker stellen</string>
+ <string name="permlab_addVoicemail">Mailboxopnamen dobäisetzen</string>
+ <string name="permdesc_addVoicemail">Erlaabt der App, Messagen op denger Mailbox ze späicheren.</string>
+ <string name="permlab_writeGeolocationPermissions">Geolokaliséierungs-Berechtegunge vum Browser änneren</string>
+ <string name="permdesc_writeGeolocationPermissions">Erlaabt der App, d\'Geolokaliséierungs-Berechtegunge vum Browser z\'änneren. Béisaarteg Appe kéinten dat benotze fir Standuertinformatiounen un arbiträr Websäiten ze schécken.</string>
+ <string name="save_password_message">Wëlls du datt de Browser dëst Passwuert verhält?</string>
+ <string name="save_password_notnow">Net elo</string>
+ <string name="save_password_remember">Erënneren</string>
+ <string name="save_password_never">Ni</string>
+ <string name="open_permission_deny">Du hues keng Berechtegung fir dës Säit opzemaachen.</string>
+ <string name="text_copied">Text an d\'Tëschenoflag kopéiert.</string>
+ <string name="more_item_label">Méi</string>
+ <string name="prepend_shortcut_label">Menü+</string>
+ <string name="menu_space_shortcut_label">Espace</string>
+ <string name="menu_enter_shortcut_label">Enter</string>
+ <string name="menu_delete_shortcut_label">läschen</string>
+ <string name="search_go">Sichen</string>
+ <string name="search_hint">Sichen&#8230;</string>
+ <string name="searchview_description_search">Sichen</string>
+ <string name="searchview_description_query">Sichufro</string>
+ <string name="searchview_description_clear">Ufro läschen</string>
+ <string name="searchview_description_submit">Ufro schécken</string>
+ <string name="searchview_description_voice">Stëmmsich</string>
+ <string name="enable_explore_by_touch_warning_title">Drécken an Entdecken aktivéieren?</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet"><xliff:g id="accessibility_service_name">%1$s</xliff:g> wëll \"Drécken an Entdecken\" aktivéieren.
+Wann \"Drécken an Endecken\" aktivéiert ass, kanns du Beschreiwunge vun Elementer héieren oder gesinn déi ënner dengem Fanger sinn oder iwwer Geste mam Tablet interagéieren.</string>
+ <string name="enable_explore_by_touch_warning_message" product="default"><xliff:g id="accessibility_service_name">%1$s</xliff:g> wëll \"Drécken an Entdecken\" aktivéieren.
+Wann \"Drécken an Endecken\" aktivéiert ass, kanns du Beschreiwunge vun Elementer héieren oder gesinn déi ënner dengem Fanger sinn oder iwwer Geste mam Telefon interagéieren.</string>
+ <string name="oneMonthDurationPast">Virun 1 Mount</string>
+ <string name="beforeOneMonthDurationPast">Viru méi als 1 Mount</string>
+ <string name="last_month">Leschte Mount</string>
+ <string name="older">Méi al</string>
+ <string name="preposition_for_date">um <xliff:g id="date" example="May 29">%s</xliff:g></string>
+ <string name="preposition_for_time">um <xliff:g id="time" example="2:33 am">%s</xliff:g></string>
+ <string name="preposition_for_year">am Joer <xliff:g id="year" example="2003">%s</xliff:g></string>
+ <string name="day">Dag</string>
+ <string name="days">Deeg</string>
+ <string name="hour">Stonn</string>
+ <string name="hours">Stonnen</string>
+ <string name="minute">min</string>
+ <string name="minutes">min</string>
+ <string name="second">s</string>
+ <string name="seconds">s</string>
+ <string name="week">Woch</string>
+ <string name="weeks">Wochen</string>
+ <string name="year">Joer</string>
+ <string name="years">Joer</string>
+ <string name="VideoView_error_title">Videoproblem</string>
+ <string name="VideoView_error_text_invalid_progressive_playback">De Video ass net gëlteg fir op dësen Apparat gestreamt ze ginn.</string>
+ <string name="VideoView_error_text_unknown">Dëse Video kann net ofgespillt ginn.</string>
+ <string name="VideoView_error_button">OK</string>
+ <string name="relative_time">"<xliff:g id="date" example="4 hours ago">%1$s</xliff:g>, <xliff:g id="time" example="11:00 am">%2$s</xliff:g>"</string>
+ <string name="noon">"Mëtteg"</string>
+ <string name="Noon">"Mëtteg"</string>
+ <string name="midnight">"Hallefnuecht"</string>
+ <string name="Midnight">"Hallefnuecht"</string>
+ <string name="elapsed_time_short_format_mm_ss"><xliff:g id="minutes" example="1">%1$02d</xliff:g>:<xliff:g id="seconds" example="23">%2$02d</xliff:g></string>
+ <string name="elapsed_time_short_format_h_mm_ss"><xliff:g id="hours" example="1">%1$d</xliff:g>:<xliff:g id="minutes" example="43">%2$02d</xliff:g>:<xliff:g id="seconds" example="33">%3$02d</xliff:g></string>
+ <string name="selectAll">All auswielen</string>
+ <string name="cut">Schneiden</string>
+ <string name="copy">Kopéieren</string>
+ <string name="paste">Apechen</string>
+ <string name="replace">Ersetzen\u2026</string>
+ <string name="delete">Läschen</string>
+ <string name="copyUrl">URL kopéieren</string>
+ <string name="selectTextMode">Text auswielen</string>
+ <string name="textSelectionCABTitle">Textauswiel</string>
+ <string name="addToDictionary">An den Dictionnaire setzen</string>
+ <string name="deleteText">Läschen</string>
+ <string name="inputMethod">Method fir anzeginn</string>
+ <string name="editTextMenuTitle">Textaktiounen</string>
+ <string name="low_internal_storage_view_title">De Späicher huet geschwë keng Plaz méi</string>
+ <string name="low_internal_storage_view_text">E puer Systemfunktioune funktionéiere vläicht net</string>
+ <string name="low_internal_storage_view_text_no_boot">Net genuch Späicher fir de System. Stell sécher, datt s de 250MB fräi Späicherplaz hues a start nei.</string>
+ <string name="app_running_notification_title"><xliff:g id="app_name">%1$s</xliff:g> gëtt ausgeféiert</string>
+ <string name="app_running_notification_text">Dréck fir méi Informatiounen
+ oder fir d\'App unzehalen.</string>
+ <string name="ok">OK</string>
+ <string name="cancel">Ofbriechen</string>
+ <string name="yes">OK</string>
+ <string name="no">Ofbriechen</string>
+ <string name="dialog_alert_title">Opgepasst</string>
+ <string name="loading">Gëtt gelueden\u2026</string>
+ <string name="capital_on">UN</string>
+ <string name="capital_off">AUS</string>
+ <string name="whichApplication">Aktioun duerchféiere mat</string>
+ <string name="whichApplicationNamed">Aktioun mat %1$s ofschléissen</string>
+ <string name="whichViewApplication">Opmaache mat</string>
+ <string name="whichViewApplicationNamed">Opmaache mat %1$s</string>
+ <string name="whichEditApplication">Ännere mat</string>
+ <string name="whichEditApplicationNamed">Ännere mat %1$s</string>
+ <string name="whichSendApplication">Deele mat</string>
+ <string name="whichSendApplicationNamed">Deele mat %1$s</string>
+ <string name="whichHomeApplication">Start-App auswielen</string>
+ <string name="whichHomeApplicationNamed">%1$s als Start-App auswielen</string>
+ <string name="alwaysUse">Standardméisseg fir dës Aktioun benotzen.</string>
+ <string name="use_a_different_app">Eng aner App benotzen</string>
+ <string name="clearDefaultHintMsg">D\'Standardastellunge kënnen ënner \"Astellungen &gt; Appen &gt; Erofgelueden\" geläscht ginn.</string>
+ <string name="chooseActivity">Wiel eng Aktioun aus</string>
+ <string name="chooseUsbActivity">Wiel eng App fir den USB-Apparat aus</string>
+ <string name="noApplications">Dës Aktioun ka vu kenger App duerchgefouert ginn.</string>
+ <string name="aerr_application">Leider huet <xliff:g id="application">%1$s</xliff:g> opgehale mat Funktionéieren.</string>
+ <string name="aerr_process">Leider gouf de Prozess <xliff:g id="process">%1$s</xliff:g> gestoppt.</string>
+ <string name="anr_activity_application"><xliff:g id="application">%2$s</xliff:g> äntwert net.\n\nWëlls de d\'App zoumaachen?</string>
+ <string name="anr_activity_process">D\'Aktivitéit <xliff:g id="activity">%1$s</xliff:g> äntwert net.\n\nWëlls de se zoumaachen?</string>
+ <string name="anr_application_process"><xliff:g id="application">%1$s</xliff:g> äntwert net.\n\nWëlls de d\'App zoumaachen?</string>
+ <string name="anr_process">De Prozess <xliff:g id="activity">%1$s</xliff:g> äntwert net.\n\nWëlls de e zoumaachen?</string>
+ <string name="force_close">OK</string>
+ <string name="report">Bericht</string>
+ <string name="wait">Waart</string>
+ <string name="webpage_unresponsive">D\'Säit reagéiert net méi.\n\nWëlls de se zoumaachen?</string>
+ <string name="launch_warning_title">App ëmgeleet</string>
+ <string name="launch_warning_replace"><xliff:g id="app_name">%1$s</xliff:g> leeft elo.</string>
+ <string name="launch_warning_original"><xliff:g id="app_name">%1$s</xliff:g> gouf ursprünglech gestart.</string>
+ <string name="screen_compat_mode_scale">Skaléieren</string>
+ <string name="screen_compat_mode_show">Ëmmer uweisen</string>
+ <string name="screen_compat_mode_hint">Reaktivéierung ënner Astellungen &gt; Appen &gt; Erofgelueden.</string>
+ <string name="smv_application">D\'App <xliff:g id="application">%1$s</xliff:g> (Prozess <xliff:g id="process">%2$s</xliff:g>) huet géint déi selwer operluechte StrictMode-Richtlinne verstouss.</string>
+ <string name="smv_process">De Prozess <xliff:g id="process">%1$s</xliff:g> huet géint déi selwer operluechte StrictMode-Richtlinne verstouss.</string>
+ <string name="android_upgrading_title">Android gëtt aktualiséiert\u2026</string>
+ <string name="android_start_title">Android gëtt gestart\u2026</string>
+ <string name="android_upgrading_fstrim">Späicher optiméieren.</string>
+ <string name="android_upgrading_apk">Optiméierung vun der App <xliff:g id="number" example="123">%1$d</xliff:g> / <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
+ <string name="android_upgrading_starting_apps">Appe gi gestart.</string>
+ <string name="android_upgrading_complete">Start gëtt ofgeschloss.</string>
+ <string name="heavy_weight_notification"><xliff:g id="app">%1$s</xliff:g> leeft</string>
+ <string name="heavy_weight_notification_detail">Drécke fir bei d\'App ze wiesselen</string>
+ <string name="heavy_weight_switcher_title">Appe wiesselen?</string>
+ <string name="heavy_weight_switcher_text">Et leeft schonn eng App déi muss gestoppt gi fir eng nei ze starten.</string>
+ <string name="old_app_action">Zréck bei <xliff:g id="old_app">%1$s</xliff:g></string>
+ <string name="old_app_description">Déi nei App net starten.</string>
+ <string name="new_app_action"><xliff:g id="old_app">%1$s</xliff:g> starten</string>
+ <string name="new_app_description">Déi al App ouni ze späichere stoppen.</string>
+ <string name="sendText">Aktioun fir Text auswielen</string>
+ <string name="volume_ringtone">Schelltounlautstäerkt</string>
+ <string name="volume_music">Medielautstäerkt</string>
+ <string name="volume_music_hint_playing_through_bluetooth">Iwwer Bluetooth ofspillen</string>
+ <string name="volume_music_hint_silent_ringtone_selected">Stëlle Schelltoun gesat</string>
+ <string name="volume_call">Hörerlautstäerkt</string>
+ <string name="volume_bluetooth_call">Hörerlautstäerkt iwwer Bluetooth</string>
+ <string name="volume_alarm">Weckerlautstäerkt</string>
+ <string name="volume_notification">Notifikatiounslautstäerkt</string>
+ <string name="volume_unknown">Lautstäerkt</string>
+ <string name="volume_icon_description_bluetooth">Bluetooth-Lautstäerkt</string>
+ <string name="volume_icon_description_ringer">Schelltounlautstäerkt</string>
+ <string name="volume_icon_description_incall">Urufflautstäerkt</string>
+ <string name="volume_icon_description_media">Medielautstäerkt</string>
+ <string name="volume_icon_description_notification">Notifikatiounslautstäerkt</string>
+ <string name="ringtone_default">Standardschelltoun</string>
+ <string name="ringtone_default_with_actual">Standard-Schelltoun (<xliff:g id="actual_ringtone">%1$s</xliff:g>)</string>
+ <string name="ringtone_silent">Keen</string>
+ <string name="ringtone_picker_title">Schelltéin</string>
+ <string name="ringtone_unknown">Onbekannte Schelltoun</string>
+ <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
+ <string name="wifi_watchdog_network_disabled">Konnt net mam WLAN connectéieren</string>
+ <string name="wifi_watchdog_network_disabled_detailed">\u0020huet eng schwaach Internetconnectioun.</string>
+ <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
+ <string name="wifi_p2p_turnon_message">Wi-Fi Direct starten. De WLAN-Zougankspunkt gëtt doduerch ausgeschalt.</string>
+ <string name="wifi_p2p_failed_message">Konnt Wi-Fi Direct net starten.</string>
+ <string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct ass un</string>
+ <string name="wifi_p2p_enabled_notification_message">Dréck fir d\'Astellungen</string>
+ <string name="accept">Acceptéieren</string>
+ <string name="decline">Refuséieren</string>
+ <string name="wifi_p2p_invitation_sent_title">Invitatioun geschéckt</string>
+ <string name="wifi_p2p_invitation_to_connect_title">Invitatioun fir ze verbannen</string>
+ <string name="wifi_p2p_from_message">Vun: </string>
+ <string name="wifi_p2p_to_message">Un: </string>
+ <string name="wifi_p2p_enter_pin_message">Gëff de benéidegte PIN an: </string>
+ <string name="wifi_p2p_show_pin_message">PIN: </string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet">Den Tablet gëtt kuerzzäiteg vum WLAN deconnectéiert während e mat <xliff:g id="device_name">%1$s</xliff:g> verbonnen ass</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tv">D\'Tëlee gëtt kuerzzäiteg vum WLAN deconnectéiert während e mat <xliff:g id="device_name">%1$s</xliff:g> verbonnen ass</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default">Den Telefon gëtt kuerzzäiteg vum WLAN deconnectéiert während e mat <xliff:g id="device_name">%1$s</xliff:g> verbonnen ass</string>
+ <string name="select_character">Zeechen aginn</string>
+ <string name="sms_control_title">SMS-Messagë gi geschéckt</string>
+ <string name="sms_control_message">&lt;b&gt;<xliff:g id="app_name">%1$s</xliff:g>&lt;/b&gt; verschéckt eng grouss Zuel vun SMSen. Wëlls du der App erlabe weider Messagen ze verschécken?</string>
+ <string name="sms_control_yes">Erlaben</string>
+ <string name="sms_control_no">Verweigeren</string>
+ <string name="sms_short_code_confirm_message">&lt;b&gt;<xliff:g id="app_name">%1$s</xliff:g>&lt;/b&gt; wëll e Message un &lt;b&gt;<xliff:g id="dest_address">%2$s</xliff:g>&lt;/b&gt; schécken.</string>
+ <string name="sms_short_code_details">Doduerch <b>kënne Käschten op denger Mobilrechnung</b> entstoen.</string>
+ <string name="sms_premium_short_code_details"><b>Doduerch entsti Käschten op dengem Mobilabo.</b></string>
+ <string name="sms_short_code_confirm_allow">Schécken</string>
+ <string name="sms_short_code_confirm_deny">Ofbriechen</string>
+ <string name="sms_short_code_remember_choice">Mäi Choix verhalen</string>
+ <string name="sms_short_code_remember_undo_instruction">Du kanns dat méi spéit ënner Astellungen\u00A0&gt;\u00A0Appen änneren</string>
+ <string name="sms_short_code_confirm_always_allow">Ëmmer erlaben</string>
+ <string name="sms_short_code_confirm_never_allow">Ni erlaben</string>
+ <string name="sim_removed_title">SIM-Kaart erausgeholl</string>
+ <string name="sim_removed_message">D\'Mobilnetzwierk ass net disponibel bis de eng gëlteg SIM-Kaart asetz an nei starts.</string>
+ <string name="sim_done_button">Fäerdeg</string>
+ <string name="sim_added_title">SIM-Kaart dobäigesat</string>
+ <string name="sim_added_message">Start den Handy nei fir op d\'Mobilnetz zouzegräifen.</string>
+ <string name="sim_restart_button">Nei starten</string>
+ <string name="time_picker_dialog_title">Zäit setzen</string>
+ <string name="date_picker_dialog_title">Datum setzen</string>
+ <string name="date_time_set">Setzen</string>
+ <string name="date_time_done">Fäerdeg</string>
+ <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff33b5e5">NEI: </font></string>
+ <string name="perms_description_app">Zur Verfügung gestallt vu(n) <xliff:g id="app_name">%1$s</xliff:g>.</string>
+ <string name="no_permissions">Keng Berechtegungen néideg</string>
+ <string name="perm_costs_money">dëst kéint dech Sue kaschten</string>
+ <string name="usb_storage_activity_title">USB-Massespäicher</string>
+ <string name="usb_storage_title">USB connectéiert</string>
+ <string name="usb_storage_message" product="nosdcard">Du hues den Apparat iwwer USB un däi Computer ugeschloss. Dréck de Knäppchen hei drënner wann s du Fichieren tëscht dengem Computer an dem USB-Späicher vun dengem Android-Apparat wëlls kopéieren.</string>
+ <string name="usb_storage_message" product="default">Du hues den Apparat iwwer USB un däi Computer ugeschloss. Dréck de Knäppchen hei drënner wann s du Fichieren tëscht dengem Computer an der SD-Kaart vun dengem Android-Apparat wëlls kopéieren.</string>
+ <string name="usb_storage_button_mount">USB-Späicher aktivéieren</string>
+ <string name="usb_storage_error_message" product="nosdcard">Beim Versuch däin USB-Späicher als USB-Massespäicher ze benotze gouf et e Problem.</string>
+ <string name="usb_storage_error_message" product="default">Beim Versuch deng SD-Kaart als USB-Massespäicher ze benotze gouf et e Problem.</string>
+ <string name="usb_storage_notification_title">USB connectéiert</string>
+ <string name="usb_storage_notification_message">Dréck fir Fichiere vum/op de Computer ze kopéieren.</string>
+ <string name="usb_storage_stop_notification_title">USB-Späicher desaktivéieren</string>
+ <string name="usb_storage_stop_notification_message">Dréck fir den USB-Späicher auszeschalten.</string>
+ <string name="usb_storage_stop_title">USB-Späicher gëtt benotzt</string>
+ <string name="usb_storage_stop_message" product="nosdcard">Ier s de den USB-Späicher ausschalts, trenn (\"ejectéieren\") dengem Android säin USB-Späicher vum Computer.</string>
+ <string name="usb_storage_stop_message" product="default">Ier s de den USB-Späicher ausschalts, trenn (\"ejectéieren\") dengem Android seng SD-Kaart vum Computer.</string>
+ <string name="usb_storage_stop_button_mount">USB-Späicher desaktivéieren</string>
+ <string name="usb_storage_stop_error_message">Et gouf e Problem beim Ausschalte vum USB-Späicher. Kontrolléier datt den USB-Host getrennt gouf a probéier nees.</string>
+ <string name="dlg_confirm_kill_storage_users_title">USB-Späicher aktivéieren</string>
+ <string name="dlg_confirm_kill_storage_users_text">Wann s du den USB-Späicher uschalts kéinte verschidden Appen ophale mat funktionéiere bis de den USB-Späicher nees ausschalts.</string>
+ <string name="dlg_error_title">USB-Operatioun feelgeschloen</string>
+ <string name="dlg_ok">OK</string>
+ <string name="usb_accessory_notification_title">Als USB-Accessoire verbonnen</string>
+ <string name="adb_active_notification_title">USB-Debugging verbonnen</string>
+ <string name="adb_active_notification_message">Dréck fir USB-Debugging auszeschalten.</string>
+ <string name="select_input_method">Tastatur wiesselen</string>
+ <string name="configure_input_methods">Tastaturen auswielen</string>
+ <string name="show_ime">Method fir anzeginn uweisen</string>
+ <string name="hardware">Hardware</string>
+ <string name="select_keyboard_layout_notification_title">Tastaturlayout auswielen</string>
+ <string name="select_keyboard_layout_notification_message">Dréck fir den Tastaturlayout auszewielen.</string>
+ <string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="candidates_style"><u>Kandidaten</u></string>
+ <string name="ext_media_status_checking">Iwwerpréiwung\u2026</string>
+ <string name="activity_list_empty">Keng passend Aktivitéit fonnt.</string>
+ <string name="permlab_route_media_output">Medienausgab ëmleeden</string>
+ <string name="permdesc_route_media_output">Erlaabt der App, d\'Medienausgab un extern Apparater weiderzeleeden.</string>
+ <string name="permlab_readInstallSessions">Installatiounssëtzunge liesen</string>
+ <string name="permdesc_readInstallSessions">Erlaabt der App, Installatiounssëtzungen ze liesen. Dat erméiglecht der App, Detailer iwwer Päck ze gesinn, déi grad installéiert ginn.</string>
+ <string name="tutorial_double_tap_to_zoom_message_short">Zweemol drécke fir d\'Zoomastellungen</string>
+ <string name="gadget_host_error_inflating">Konnt de Widget net dobäisetzen.</string>
+ <string name="ime_action_go">Lass</string>
+ <string name="ime_action_search">Sichen</string>
+ <string name="ime_action_send">Schécken</string>
+ <string name="ime_action_next">Weider</string>
+ <string name="ime_action_done">Fäerdeg</string>
+ <string name="ime_action_previous">Zréck</string>
+ <string name="ime_action_default">Ausféieren</string>
+ <string name="dial_number_using">Nummer\nmat <xliff:g id="number" example="555">%s</xliff:g> auswielen</string>
+ <string name="create_contact_using">Neie Kontakt\nmat <xliff:g id="number" example="555">%s</xliff:g> erstellen</string>
+ <string name="grant_credentials_permission_message_header">Dës Appe brauchen eng Berechtegung fir elo an an Zukunft op däi Kont zouzegräifen.</string>
+ <string name="grant_credentials_permission_message_footer">Wëlls du dës Ufro erlaben?</string>
+ <string name="grant_permissions_header_text">Zougrëffsufro</string>
+ <string name="allow">Erlaben</string>
+ <string name="deny">Verweigeren</string>
+ <string name="permission_request_notification_title">Erlaabnesufro</string>
+ <string name="permission_request_notification_with_subtitle">Erlaabnes ugefrot\nfir de Kont <xliff:g id="account" example="foo@gmail.com">%s</xliff:g>.</string>
+ <string name="forward_intent_to_owner">Du benotz dës App ausserhalb vun dengem Aarbechtsprofil</string>
+ <string name="forward_intent_to_work">Du benotz dës App an dengem Aarbechtsprofil</string>
+ <string name="input_method_binding_label">Method fir anzeginn</string>
+ <string name="sync_binding_label">Sync</string>
+ <string name="accessibility_binding_label">Accessibilitéit</string>
+ <string name="wallpaper_binding_label">Hannergrondbild</string>
+ <string name="chooser_wallpaper">Hannergrondbild änneren</string>
+ <string name="notification_listener_binding_label">Notifikatiouns-Nolauschterer</string>
+ <string name="condition_provider_service_binding_label">Konditiounsubidder</string>
+ <string name="vpn_title">VPN aktivéiert</string>
+ <string name="vpn_title_long">VPN ass aktivéiert vum <xliff:g id="app" example="FooVPN client">%s</xliff:g></string>
+ <string name="vpn_text">Dréck fir d\'Netzwierk ze geréieren.</string>
+ <string name="vpn_text_long">Verbonne mat <xliff:g id="session" example="office">%s</xliff:g>. Dréck fir d\'Netzwierk ze geréieren.</string>
+ <string name="vpn_lockdown_connecting">Permanent aktive VPN gëtt connectéiert\u2026</string>
+ <string name="vpn_lockdown_connected">Permanent aktive VPN connectéiert</string>
+ <string name="vpn_lockdown_error">Feeler beim permanent aktive VPN</string>
+ <string name="vpn_lockdown_config">Dréck fir anzestellen</string>
+ <string name="upload_file">Fichier auswielen</string>
+ <string name="no_file_chosen">Kee Fichier ausgewielt</string>
+ <string name="reset">Zrécksetzen</string>
+ <string name="submit">Schécken</string>
+ <string name="car_mode_disable_notification_title">Automodus aktivéiert</string>
+ <string name="car_mode_disable_notification_message">Dréck fir den Automodus auszemaachen.</string>
+ <string name="tethered_notification_title">Tethering oder Zougankspunkt aktiv</string>
+ <string name="tethered_notification_message">Fir ze setzen drécken.</string>
+ <string name="back_button_label">Zréck</string>
+ <string name="next_button_label">Weider</string>
+ <string name="skip_button_label">Iwwersprangen</string>
+ <string name="no_matches">Keng Treffer</string>
+ <string name="find_on_page">Op der Säit fannen</string>
+ <string name="action_mode_done">Fäerdeg</string>
+ <string name="progress_erasing" product="nosdcard">Den USB-Späicher gëtt geläscht\u2026</string>
+ <string name="progress_erasing" product="default">SD-Kaart gëtt geläscht\u2026</string>
+ <string name="share">Deelen</string>
+ <string name="find">Sichen</string>
+ <string name="websearch">Websich</string>
+ <string name="find_next">Weidersichen</string>
+ <string name="find_previous">Resultat virdrun</string>
+ <string name="gpsNotifTicker">Standuertoffro vu(n) <xliff:g id="name">%s</xliff:g></string>
+ <string name="gpsNotifTitle">Standuertoffro</string>
+ <string name="gpsNotifMessage">Ugefrot vum <xliff:g id="name">%1$s</xliff:g> (<xliff:g id="service" example="SUPL-service">%2$s</xliff:g>)</string>
+ <string name="gpsVerifYes">Jo</string>
+ <string name="gpsVerifNo">Nee</string>
+ <string name="sync_too_many_deletes">Läschlimitt erreecht</string>
+ <string name="sync_too_many_deletes_desc">Et ginn <xliff:g id="number_of_deleted_items">%1$d</xliff:g> geläschten Elementer fir <xliff:g id="type_of_sync">%2$s</xliff:g>, Kont <xliff:g id="account_name">%3$s</xliff:g>. Wat wëlls du maachen?</string>
+ <string name="sync_really_delete">Elementer läschen</string>
+ <string name="sync_undo_deletes">Läschen zrécksetzen</string>
+ <string name="sync_do_nothing">Am Moment näischt maachen</string>
+ <string name="choose_account_label">E Kont auswielen</string>
+ <string name="add_account_label">"E Kont dobäisetzen"</string>
+ <string name="add_account_button_label">Kont dobäisetzen</string>
+ <string name="number_picker_increment_button">Eropsetzen</string>
+ <string name="number_picker_decrement_button">Erofsetzen</string>
+ <string name="number_picker_increment_scroll_mode"><xliff:g id="value" example="3">%s</xliff:g> drécken an unhalen.</string>
+ <string name="number_picker_increment_scroll_action">Eropwësche fir z\'erhéijen, erofwësche fir ze reduzéieren.</string>
+ <string name="time_picker_increment_minute_button">Minutt eropsetzen</string>
+ <string name="time_picker_decrement_minute_button">Minutt erofsetzen</string>
+ <string name="time_picker_increment_hour_button">Stonn eropsetzen</string>
+ <string name="time_picker_decrement_hour_button">Stonn erofsetzen</string>
+ <string name="time_picker_increment_set_pm_button">PM-Wäert setzen</string>
+ <string name="time_picker_decrement_set_am_button">AM-Wäert setzen</string>
+ <string name="date_picker_increment_month_button">Mount eropsetzen</string>
+ <string name="date_picker_decrement_month_button">Mount erofsetzen</string>
+ <string name="date_picker_increment_day_button">Dag eropsetzen</string>
+ <string name="date_picker_decrement_day_button">Dag erofsetzen</string>
+ <string name="date_picker_increment_year_button">Joer eropsetzen</string>
+ <string name="date_picker_decrement_year_button">Joer erofsetzen</string>
+ <string name="keyboardview_keycode_alt">Alt</string>
+ <string name="keyboardview_keycode_cancel">Ofbriechen</string>
+ <string name="keyboardview_keycode_delete">Läschen</string>
+ <string name="keyboardview_keycode_done">Fäerdeg</string>
+ <string name="keyboardview_keycode_mode_change">Modusännerung</string>
+ <string name="keyboardview_keycode_shift">Shift</string>
+ <string name="keyboardview_keycode_enter">Enter</string>
+ <string name="activitychooserview_choose_application">App auswielen</string>
+ <string name="activitychooserview_choose_application_error">Konnt <xliff:g id="application_name" example="Acme">%s</xliff:g> net starten</string>
+ <string name="shareactionprovider_share_with">Deele mat</string>
+ <string name="shareactionprovider_share_with_application">Deele mat <xliff:g id="application_name" example="Bluetooth">%s</xliff:g></string>
+ <string name="content_description_sliding_handle">"Wëschgrëff. Drécken an halen."</string>
+ <string name="description_target_unlock_tablet">Wësche fir z\'entspären.</string>
+ <string name="keyboard_headset_required_to_hear_password">Schléiss en Headset u fir d\'Passwuerttaste virgelies ze kréien.</string>
+ <string name="keyboard_password_character_no_headset">Punkt.</string>
+ <string name="action_bar_home_description">Heem navigéieren</string>
+ <string name="action_bar_up_description">Erop navigéieren</string>
+ <string name="action_menu_overflow_description">Méi Optiounen</string>
+ <string name="action_bar_home_description_format">%1$s. %2$s</string>
+ <string name="action_bar_home_subtitle_description_format">%1$s, %2$s. %3$s</string>
+ <string name="storage_internal">Interne Späicher</string>
+ <string name="storage_sd_card">SD-Kaart</string>
+ <string name="storage_usb">USB-Späicher</string>
+ <string name="data_usage_warning_title">Dateverbrauchswarnung</string>
+ <string name="data_usage_warning_body">Drécke fir Verbrauch an Astellungen unzeweisen.</string>
+ <string name="data_usage_3g_limit_title">2G/3G Datelimitt erreecht</string>
+ <string name="data_usage_4g_limit_title">4G Datelimitt erreecht</string>
+ <string name="data_usage_mobile_limit_title">Mobil Datelimitt erreecht</string>
+ <string name="data_usage_wifi_limit_title">WLAN-Datelimitt erreecht</string>
+ <string name="data_usage_limit_body">Date pauséiert fir de Rescht vum Zyklus</string>
+ <string name="data_usage_3g_limit_snoozed_title">2G- an 3G-Datelimitt iwwerschratt</string>
+ <string name="data_usage_4g_limit_snoozed_title">4G-Datelimitt iwwerschratt</string>
+ <string name="data_usage_mobile_limit_snoozed_title">Mobil Datelimitt iwwerschratt</string>
+ <string name="data_usage_wifi_limit_snoozed_title">Wi-Fi-Datelimitt iwwerschratt</string>
+ <string name="data_usage_limit_snoozed_body"><xliff:g id="size" example="3.8GB">%s</xliff:g> iwwer der definéierter Limitt.</string>
+ <string name="data_usage_restricted_title">Hannergronddaten ageschränkt</string>
+ <string name="data_usage_restricted_body">Drécke fir d\'Restriktiounen opzehiewen.</string>
+ <string name="ssl_certificate">Sécherheetszertifikat</string>
+ <string name="ssl_certificate_is_valid">Dëst Zertifikat ass gëlteg.</string>
+ <string name="issued_to">Ausgestallt fir:</string>
+ <string name="common_name">Allgemengen Numm:</string>
+ <string name="org_name">Organisatioun:</string>
+ <string name="org_unit">Eenheet an der Organisatioun:</string>
+ <string name="issued_by">Ausgestallt vun:</string>
+ <string name="validity_period">Gëltegkeet:</string>
+ <string name="issued_on">Ausgestallt den:</string>
+ <string name="expires_on">Leeft of den:</string>
+ <string name="serial_number">Seriennummer:</string>
+ <string name="fingerprints">Fangerofdréck:</string>
+ <string name="sha256_fingerprint">SHA-256-Fangerofdrock:</string>
+ <string name="sha1_fingerprint">SHA-1-Fangerofdrock:</string>
+ <string name="activity_chooser_view_see_all">All uweisen</string>
+ <string name="activity_chooser_view_dialog_title_default">Aktivitéit auswielen</string>
+ <string name="share_action_provider_share_with">Deele mat</string>
+ <string name="list_delimeter">", "</string>
+ <string name="sending">Gëtt geschéckt\u2026</string>
+ <string name="launchBrowserDefault">Browser starten?</string>
+ <string name="SetupCallDefault">Uruff unhuelen?</string>
+ <string name="activity_resolver_use_always">Ëmmer</string>
+ <string name="activity_resolver_use_once">Just eemol</string>
+ <string name="activity_resolver_work_profiles_support">%1$s ënnerstëtzt keen Aarbechtsprofil</string>
+ <string name="default_audio_route_name" product="tablet">Tablet</string>
+ <string name="default_audio_route_name" product="tv">Tëlee</string>
+ <string name="default_audio_route_name" product="default">Telefon</string>
+ <string name="default_audio_route_name_headphones">Kopfhörer</string>
+ <string name="default_audio_route_name_dock_speakers">Dock-Lautsprecher</string>
+ <string name="default_media_route_name_hdmi">HDMI</string>
+ <string name="default_audio_route_category_name">System</string>
+ <string name="bluetooth_a2dp_audio_route_name">Bluetooth-Audio</string>
+ <string name="wireless_display_route_description">Kabellose Schierm</string>
+ <string name="media_route_button_content_description">Iwwerdroen</string>
+ <string name="media_route_chooser_title">Mat Apparat verbannen</string>
+ <string name="media_route_chooser_title_for_remote_display">Schierm op Apparat iwwerdroen</string>
+ <string name="media_route_chooser_searching">Et gëtt no Apparater gesicht\u2026</string>
+ <string name="media_route_chooser_extended_settings">Astellungen</string>
+ <string name="media_route_controller_disconnect">Deconnectéieren</string>
+ <string name="media_route_status_scanning">Gëtt gescannt...</string>
+ <string name="media_route_status_connecting">Gëtt connectéiert...</string>
+ <string name="media_route_status_available">Disponibel</string>
+ <string name="media_route_status_not_available">Net disponibel</string>
+ <string name="media_route_status_in_use">Gëtt benotzt</string>
+ <string name="display_manager_built_in_display_name">Agebaute Schierm</string>
+ <string name="display_manager_hdmi_display_name">HDMI-Schierm</string>
+ <string name="display_manager_overlay_display_name">Overlay #<xliff:g id="id">%1$d</xliff:g></string>
+ <string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string>
+ <string name="display_manager_overlay_display_secure_suffix">, sécher</string>
+ <string name="kg_forgot_pattern_button_text">Muster vergiess</string>
+ <string name="kg_wrong_pattern">Falscht Muster</string>
+ <string name="kg_wrong_password">Falscht Passwuert</string>
+ <string name="kg_wrong_pin">Falsche PIN</string>
+ <string name="kg_too_many_failed_attempts_countdown">Probéier nees a(n) <xliff:g id="number">%1$d</xliff:g> Sekonnen.</string>
+ <string name="kg_pattern_instructions">Mol däi Muster</string>
+ <string name="kg_sim_pin_instructions">SIM-PIN aginn</string>
+ <string name="kg_pin_instructions">PIN aginn</string>
+ <string name="kg_password_instructions">Passwuert aginn</string>
+ <string name="kg_puk_enter_puk_hint">D\'SIM ass elo desaktivéiert. Gëff e PUK-Code a fir weiderzemaachen. Kontaktéier däi Provider fir Detailer.</string>
+ <string name="kg_puk_enter_pin_hint">Gëff de gewënschte PIN-Code an</string>
+ <string name="kg_enter_confirm_pin_hint">Bestäteg de gewënschte PIN-Code</string>
+ <string name="kg_sim_unlock_progress_dialog_message">D\'SIM-Kaart gëtt entspaart\u2026</string>
+ <string name="kg_password_wrong_pin_code">Falsche PIN-Code.</string>
+ <string name="kg_invalid_sim_pin_hint">Gëff e PIN an, deen tëscht 4 an 8 Zifferen huet.</string>
+ <string name="kg_invalid_sim_puk_hint">De PUK-Code sollt 8 Ziffere laang sinn.</string>
+ <string name="kg_invalid_puk">Gëff de korrekte PUK-Code nees an. Bei widderhuelende Versich gëtt d\'SIM permanent desaktivéiert.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">D\'PIN-Codë stëmmen net iwwereneen</string>
+ <string name="kg_login_too_many_attempts">Zevill Muster-Versich</string>
+ <string name="kg_login_instructions">Fir z\'entspären, mell dech mat dengem Google-Kont un.</string>
+ <string name="kg_login_username_hint">Benotzernumm (E-Mail)</string>
+ <string name="kg_login_password_hint">Passwuert</string>
+ <string name="kg_login_submit_button">Aloggen</string>
+ <string name="kg_login_invalid_input">Ongëltege Benotzernumm oder Passwuert.</string>
+ <string name="kg_login_account_recovery_hint">Benotzernumm oder Passwuert vergiess\?\nBesich <b>google.com/accounts/recovery</b>.</string>
+ <string name="kg_login_checking_password">Kont gëtt iwwerpréift\u2026</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">Du hues däi PIN <xliff:g id="number">%d</xliff:g>-mol falsch aginn.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">Du hues däi Passwuert <xliff:g id="number">%d</xliff:g>-mol falsch aginn.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gemoolt.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tv">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht d\'Tëlee z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Telefon op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Telefon op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer.</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat.</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht d\'Tëlee z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat.</string>
+ <string name="kg_failed_attempts_now_wiping" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gezeechent. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëss de gefrot däin Tablet mat engem E-Mail-Kont z\'entspären.\n\nProbéier a(n) <xliff:g id="number">%d</xliff:g> Sekonnen nees.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gemoolt. No <xliff:g id="number">%d</xliff:g> weidere feelsgeschloene Versich gëss du gefrot deng Tëlee duerch en E-Mail-Kont z\'entspären. Probéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gezeechent. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëss de gefrot däin Telefon mat engem E-Mail-Kont z\'entspären.\n\nProbéier a(n) <xliff:g id="number">%d</xliff:g> Sekonnen nees.</string>
+ <string name="kg_text_message_separator" product="default">" \u2014 "</string>
+ <string name="kg_reordering_delete_drop_target_text">Ewechhuelen</string>
+ <string name="safe_media_volume_warning" product="default">D\'Lautstäerkt iwwer de recommandéierten Niveau erhéijen?\n\nIwwer laang Periode bei héijer Lautstäerkt Musek lauschtere kéint däi Gehéier schiedegen.</string>
+ <string name="continue_to_enable_accessibility">Mat zwee Fangeren drécke fir d\'Benotzungshëllefen z\'aktivéieren.</string>
+ <string name="accessibility_enabled">Accessibilitéit aktivéiert.</string>
+ <string name="enable_accessibility_canceled">Accessibilitéit ofgebrach.</string>
+ <string name="user_switched">Aktuelle Benotzer <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string>
+ <string name="user_switching_message">Wiesselen op de Benotzer <xliff:g id="name" example="Bob">%1$s</xliff:g>\u2026</string>
+ <string name="owner_name" msgid="3879126011135546571">Besëtzer</string>
+ <string name="error_message_title">Feeler</string>
+ <string name="error_message_change_not_allowed">Dës Ännerung ass duerch däin Administrateur net erlaabt</string>
+ <string name="app_not_found">Et gouf keng Applikatioun fonnt fir dës Aktioun auszeféieren</string>
+ <string name="revoke">Zréckzéien</string>
+ <string name="mediasize_iso_a0">ISO A0</string>
+ <string name="mediasize_iso_a1">ISO A1</string>
+ <string name="mediasize_iso_a2">ISO A2</string>
+ <string name="mediasize_iso_a3">ISO A3</string>
+ <string name="mediasize_iso_a4">ISO A4</string>
+ <string name="mediasize_iso_a5">ISO A5</string>
+ <string name="mediasize_iso_a6">ISO A6</string>
+ <string name="mediasize_iso_a7">ISO A7</string>
+ <string name="mediasize_iso_a8">ISO A8</string>
+ <string name="mediasize_iso_a9">ISO A9</string>
+ <string name="mediasize_iso_a10">ISO A10</string>
+ <string name="mediasize_iso_b0">ISO B0</string>
+ <string name="mediasize_iso_b1">ISO B1</string>
+ <string name="mediasize_iso_b2">ISO B2</string>
+ <string name="mediasize_iso_b3">ISO B3</string>
+ <string name="mediasize_iso_b4">ISO B4</string>
+ <string name="mediasize_iso_b5">ISO B5</string>
+ <string name="mediasize_iso_b6">ISO B6</string>
+ <string name="mediasize_iso_b7">ISO B7</string>
+ <string name="mediasize_iso_b8">ISO B8</string>
+ <string name="mediasize_iso_b9">ISO B9</string>
+ <string name="mediasize_iso_b10">ISO B10</string>
+ <string name="mediasize_iso_c0">ISO C0</string>
+ <string name="mediasize_iso_c1">ISO C1</string>
+ <string name="mediasize_iso_c2">ISO C2</string>
+ <string name="mediasize_iso_c3">ISO C3</string>
+ <string name="mediasize_iso_c4">ISO C4</string>
+ <string name="mediasize_iso_c5">ISO C5</string>
+ <string name="mediasize_iso_c6">ISO C6</string>
+ <string name="mediasize_iso_c7">ISO C7</string>
+ <string name="mediasize_iso_c8">ISO C8</string>
+ <string name="mediasize_iso_c9">ISO C9</string>
+ <string name="mediasize_iso_c10">ISO C10</string>
+ <string name="mediasize_na_letter">Letter</string>
+ <string name="mediasize_na_gvrnmt_letter">Government Letter</string>
+ <string name="mediasize_na_legal">Legal</string>
+ <string name="mediasize_na_junior_legal">Junior Legal</string>
+ <string name="mediasize_na_ledger">Ledger</string>
+ <string name="mediasize_na_tabloid">Tabloid</string>
+ <string name="mediasize_na_index_3x5">Index Card 3x5</string>
+ <string name="mediasize_na_index_4x6">Index Card 4x6</string>
+ <string name="mediasize_na_index_5x8">Index Card 5x8</string>
+ <string name="mediasize_na_monarch">Monarch</string>
+ <string name="mediasize_na_quarto">Quarto</string>
+ <string name="mediasize_na_foolscap">Foolscap</string>
+ <string name="mediasize_chinese_roc_8k">ROC 8K</string>
+ <string name="mediasize_chinese_roc_16k">ROC 16K</string>
+ <string name="mediasize_chinese_prc_1">PRC 1</string>
+ <string name="mediasize_chinese_prc_2">PRC 2</string>
+ <string name="mediasize_chinese_prc_3">PRC 3</string>
+ <string name="mediasize_chinese_prc_4">PRC 4</string>
+ <string name="mediasize_chinese_prc_5">PRC 5</string>
+ <string name="mediasize_chinese_prc_6">PRC 6</string>
+ <string name="mediasize_chinese_prc_7">PRC 7</string>
+ <string name="mediasize_chinese_prc_8">PRC 8</string>
+ <string name="mediasize_chinese_prc_9">PRC 9</string>
+ <string name="mediasize_chinese_prc_10">PRC 10</string>
+ <string name="mediasize_chinese_prc_16k">PRC 16K</string>
+ <string name="mediasize_chinese_om_pa_kai">Pa Kai</string>
+ <string name="mediasize_chinese_om_dai_pa_kai">Dai Pa Kai</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai">Jurro Ku Kai</string>
+ <string name="mediasize_japanese_jis_b10">JIS B10</string>
+ <string name="mediasize_japanese_jis_b9">JIS B9</string>
+ <string name="mediasize_japanese_jis_b8">JIS B8</string>
+ <string name="mediasize_japanese_jis_b7">JIS B7</string>
+ <string name="mediasize_japanese_jis_b6">JIS B6</string>
+ <string name="mediasize_japanese_jis_b5">JIS B5</string>
+ <string name="mediasize_japanese_jis_b4">JIS B4</string>
+ <string name="mediasize_japanese_jis_b3">JIS B3</string>
+ <string name="mediasize_japanese_jis_b2">JIS B2</string>
+ <string name="mediasize_japanese_jis_b1">JIS B1</string>
+ <string name="mediasize_japanese_jis_b0">JIS B0</string>
+ <string name="mediasize_japanese_jis_exec">JIS Exec</string>
+ <string name="mediasize_japanese_chou4">Chou4</string>
+ <string name="mediasize_japanese_chou3">c</string>
+ <string name="mediasize_japanese_chou2">Chou2</string>
+ <string name="mediasize_japanese_hagaki">Hagaki </string>
+ <string name="mediasize_japanese_oufuku">Oufuku </string>
+ <string name="mediasize_japanese_kahu">Kahu</string>
+ <string name="mediasize_japanese_kaku2">Kaku2</string>
+ <string name="mediasize_japanese_you4">You4</string>
+ <string name="mediasize_unknown_portrait">Onbekannt Héichformat</string>
+ <string name="mediasize_unknown_landscape">Onbekannt Queeschformat</string>
+ <string name="write_fail_reason_cancelled">Ofgebrach</string>
+ <string name="write_fail_reason_cannot_write">Feeler beim Schreiwe vum Inhalt</string>
+ <string name="reason_unknown">onbekannt</string>
+ <string name="reason_service_unavailable">Dréck-Service net aktivéiert</string>
+ <string name="print_service_installed_title"><xliff:g id="name" example="Cloud Print">%s</xliff:g> Service installéiert</string>
+ <string name="print_service_installed_message">Dréck fir z\'aktivéieren</string>
+ <string name="restr_pin_enter_admin_pin">Administrateur-PIN aginn</string>
+ <string name="restr_pin_enter_pin">PIN aginn</string>
+ <string name="restr_pin_incorrect">Inkorrekt</string>
+ <string name="restr_pin_enter_old_pin">Aktuell PIN</string>
+ <string name="restr_pin_enter_new_pin">Nei PIN</string>
+ <string name="restr_pin_confirm_pin">Nei PIN bestätegen</string>
+ <string name="restr_pin_create_pin">PIN fir d\'Ännerung vun Aschränkungen uleeën</string>
+ <string name="restr_pin_error_doesnt_match">D\'PINe stëmmen net iwwereneen. Probéier nees w.e.g..</string>
+ <string name="restr_pin_error_too_short">De PIN ass ze kuerz. E muss mindestens 4 Zifferen hunn.</string>
+ <string name="restr_pin_try_later">Probéier méi spéit nees</string>
+ <string name="done_label">Fäerdeg</string>
+ <string name="hour_picker_description">Kreesfërmege Regeler fir Stonnen</string>
+ <string name="minute_picker_description">Kreesfërmege Regeler fir Minutten</string>
+ <string name="select_hours">Stonnen auswielen</string>
+ <string name="select_minutes">Minutten auswielen</string>
+ <string name="select_day">Mount an Dag auswielen</string>
+ <string name="select_year">Joer auswielen</string>
+ <string name="deleted_key"><xliff:g id="key" example="4">%1$s</xliff:g> geläscht</string>
+ <string name="managed_profile_label_badge"><xliff:g id="label" example="Email">%1$s</xliff:g> (Aarbecht)</string>
+ <string name="time_placeholder">--</string>
+ <string name="lock_to_app_toast">Hal \"Zréck\" an \"Iwwersiicht\" matenee gedréckt fir dëse Schierm fräizeginn.</string>
+ <string name="lock_to_app_toast_accessible">Hal \"Iwwersiicht\" gedréckt fir dëse Schierm fräizeginn.</string>
+ <string name="lock_to_app_start">Schierm fixéiert</string>
+ <string name="lock_to_app_exit">Schierm fräiginn</string>
+ <string name="lock_to_app_unlock_pin">E PIN froe fir e Schierm fräizeginn</string>
+ <string name="lock_to_app_unlock_pattern">En Entspärmuster froe fir e Schierm fräizeginn</string>
+ <string name="lock_to_app_unlock_password">E Passwuert froe fir e Schierm fräizeginn</string>
+ <string name="battery_saver_description">Den Energiespuermodus schount den Akku, andeem en d\'Leeschtung vum Apparat reduzéiert, d\'Vibratioun limitéiert an déi meescht Hannergronddatenaktivitéiten aschränkt. E-Mail, Messagen an aner Appen, déi op dengem Apparat synchroniséieren, gi méiglecherweis eréischt nom Opmaachen aktualiséiert.\n\nDen Energiespuermodus gëtt automatesch desaktivéiert, wann däin Apparat opgeluede gëtt.</string>
+ <string name="zen_mode_until">Bis <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
+ <string name="toolbar_collapse_description">Zouklappen</string>
+ <string name="zen_mode_feature_name">Net stéieren</string>
+ <string name="muted_by">Roueg gestallt duerch <xliff:g id="third_party">%1$s</xliff:g></string>
+ <string name="system_error_wipe_data">Mat dengem Apparat ass en interne Problem opgetrueden. Wann e sech instabil behuelt muss du en op d\'Wierksastellungen zrécksetzen.</string>
+ <string name="system_error_manufacturer">Mat dengem Apparat ass en interne Problem opgetrueden. Kontaktéier däin Hiersteller fir méi Detailer.</string>
+ <string name="stk_cc_ussd_to_dial">D\'USSD-Ufro gouf an eng DIAL-Ufro ëmgewandelt.</string>
+ <string name="stk_cc_ussd_to_ss">D\'USSD-Ufro gouf an eng SS-Ufro ëmgewandelt.</string>
+ <string name="stk_cc_ussd_to_ussd">D\'USSD-Ufro gouf an eng nei USSD-Ufro ëmgewandelt.</string>
+ <string name="stk_cc_ss_to_dial">D\'SS-Ufro gouf an eng DIAL-Ufro ëmgewandelt.</string>
+ <string name="stk_cc_ss_to_ussd">D\'SS-Ufro gouf an eng USSD-Ufro ëmgewandelt.</string>
+ <string name="stk_cc_ss_to_ss">D\'SS-Ufro gouf an eng nei SS-Ufro ëmgewandelt.</string>
+ <string name="floating_toolbar_open_overflow_description">Méi Optiounen</string>
+</resources>
diff --git a/core/res/res/values-lt/cm_strings.xml b/core/res/res/values-lt/cm_strings.xml
new file mode 100644
index 0000000..b4877ac
--- /dev/null
+++ b/core/res/res/values-lt/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ekrano kopija</string>
+ <string name="permlab_receiveProtectedSms">gauti apsaugotus SMS</string>
+ <string name="permdesc_receiveProtectedSms">Leidžia programai gauti įeinančius apsaugotus SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">keisti apsaugotų SMS sąrašą</string>
+ <string name="permdesc_modifyProtectedSmsList">Leidžia programai keisti apsaugotų SMS adresų sąrašą.</string>
+ <string name="permgrouplab_security">Sauga</string>
+ <string name="permgroupdesc_security">Leidimai susiję su įrenginio saugumo informacija.</string>
+ <string name="permlab_readPhoneBlacklist">skaityti telefono juodąjį sąrašą</string>
+ <string name="permdesc_readPhoneBlacklist">Leidžia programai skaityti informaciją apie telefono numerius kurie yra užblokuoti dėl įeinančių skambučių ar pranešimų.</string>
+ <string name="permlab_changePhoneBlacklist">pakeisti telefono juodąjį sąrašą</string>
+ <string name="permdesc_changePhoneBlacklist">Leidžia programai keisti telefono numerius kurie yra užblokuoti dėl įeinančių skambučių ar pranešimų.</string>
+ <string name="permlab_setKeyguardWallpaper">nustatyti klaviatūros apsaugos foną</string>
+ <string name="permdesc_setKeyguardWallpaper">Leidžia programai pakeisti ekrano užrakto foną.</string>
+ <string name="global_action_reboot">Paleisti iš naujo</string>
+ <string name="global_action_current_user">Dabartinis</string>
+ <string name="reboot_reboot">Paleisti iš naujo</string>
+ <string name="reboot_recovery">Atkūrimo režimas</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Atsisiuntimo režimas</string>
+ <string name="reboot_soft">Paleisti iš naujo OS</string>
+ <string name="reboot_title">Paleisti iš naujo</string>
+ <string name="reboot_confirm" product="tablet">Jūsų planšetinis kompiuteris bus paleistas iš naujo.</string>
+ <string name="reboot_confirm" product="default">Jūsų telefonas bus paleistas iš naujo.</string>
+ <string name="reboot_progress">Paleidžiama iš naujo\u2026</string>
+ <string name="app_killed_message">Programa priverstinai uždaryta</string>
+ <string name="adb_net_active_notification_title">USB derinimas per tinklą įgalintas</string>
+ <string name="adb_both_active_notification_title">USB derinimas per USB ir tinklą įgalintas</string>
+ <string name="adb_active_generic_notification_message">Palieskite, kad neleistumėte derinimo.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB ir tinklas</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Tinklas</string>
+ <string name="permlab_interceptPackageLaunch">perimti programos paleidimą</string>
+ <string name="stylus_app_not_installed">%s neįdiegta</string>
+ <string name="silent_mode_priority">Prioritetas</string>
+ <string name="silent_mode_none">Joks</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi-Fi saitvietė išjungta dėl SIM prenumeratos kaitos</string>
+ <string name="notify_turn_wifi_off_title">Išjunkite „Wi-Fi“</string>
+ <string name="permlab_changePrivacyGuardState">įgalinti arba neleisti privatumo saugos</string>
+ <string name="permdesc_changePrivacyGuardState">Leisti programai keisti, kai kita programa veikia su privatumo sauga. Kai programa veikia su privatumo sauga ji neturės prieigos prie asmeninių duomenų pvz., kontaktų, skambučių žurnalų ar pranešimų.</string>
+ <string name="privacy_guard_notification">Privatumo sauga aktyvi</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> negalės prieiti prie asmeninių duomenų</string>
+ <string name="privacy_guard_dialog_title">Privatumo sauga</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> norėtu <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Prisiminti mano pasirinkimą</string>
+ <string name="app_ops_access_camera">pasiekti fotoaparatą</string>
+ <string name="app_ops_access_location">pasiekti jūsų vietą</string>
+ <string name="app_ops_access_notifications">skaityti jūsų pranešimus</string>
+ <string name="app_ops_activate_vpn">suaktyvinti VPN</string>
+ <string name="app_ops_auto_start">paleisti įsijungiant</string>
+ <string name="app_ops_delete_call_log">Ištrinti jūsų skambučių žurnalą</string>
+ <string name="app_ops_delete_contacts">Ištrinti jūsų kontaktus</string>
+ <string name="app_ops_delete_mms">Ištrinti jūsų MMS pranešimus</string>
+ <string name="app_ops_delete_sms">Ištrinti jūsų SMS pranešimus</string>
+ <string name="app_ops_draw_on_top">Piešti langus viršuje</string>
+ <string name="app_ops_get_usage_stats">gauti programos naudojimo statistiką</string>
+ <string name="app_ops_keep_device_awake">laikyti jūsų įrenginį pabudusį</string>
+ <string name="app_ops_make_phone_call">skambinti</string>
+ <string name="app_ops_modify_calendar">atnaujinti jūsų kalendorių</string>
+ <string name="app_ops_modify_call_log">atnaujinti skambučių žurnalą</string>
+ <string name="app_ops_modify_clipboard">keisti iškarpinę</string>
+ <string name="app_ops_modify_contacts">atnaujinti jūsų kontaktus</string>
+ <string name="app_ops_modify_settings">atnaujinti sistemos nustatymus</string>
+ <string name="app_ops_mute_unmute_microphone">nutildyti / įjungti mikrofoną</string>
+ <string name="app_ops_play_audio">leisti garso įrašą</string>
+ <string name="app_ops_post_notification">rašyti pranešimą</string>
+ <string name="app_ops_project_media">medijos projektas</string>
+ <string name="app_ops_read_calendar">skaityti jūsų kalendorių</string>
+ <string name="app_ops_read_call_log">skaityti skambučių žurnalą</string>
+ <string name="app_ops_read_clipboard">skaityti iškarpinę</string>
+ <string name="app_ops_read_contacts">skaityti jūsų kontaktus</string>
+ <string name="app_ops_read_mms">skaityti jūsų MMS pranešimus</string>
+ <string name="app_ops_read_sms">skaityti jūsų SMS pranešimus</string>
+ <string name="app_ops_receive_sms">gauti SMS pranešimą</string>
+ <string name="app_ops_record_audio">įrašyti garso įrašą</string>
+ <string name="app_ops_send_mms">siųsti MMS pranešimą</string>
+ <string name="app_ops_send_sms">siųsti SMS pranešimą</string>
+ <string name="app_ops_start_at_bootup">paleisti įsijungiant</string>
+ <string name="app_ops_toast_window">Rodyti informacinius pranešimus</string>
+ <string name="app_ops_toggle_bluetooth">įjungti „Bluetooth“</string>
+ <string name="app_ops_toggle_nfc">Įjungti / išjungti NFC</string>
+ <string name="app_ops_use_alarm_volume">valdyti signalo garsumą</string>
+ <string name="app_ops_use_audio_focus">valdyti garso sutelktį</string>
+ <string name="app_ops_use_bluetooth_volume">valdyti „Bluetooth“ garsumą</string>
+ <string name="app_ops_use_master_volume">valdyti pagrindinį garsumą</string>
+ <string name="app_ops_use_media_buttons">naudoti medijos mygtukus</string>
+ <string name="app_ops_use_media_volume">valdyti medijos garsumą</string>
+ <string name="app_ops_use_notification_volume">valdyti pranešimo garsumą</string>
+ <string name="app_ops_use_ring_volume">valdyti skambėjimo garsumą</string>
+ <string name="app_ops_use_vibrate">naudoti liečiamuosius atsiliepimus</string>
+ <string name="app_ops_use_voice_volume">valdyti balso skambučio garsumą</string>
+ <string name="app_ops_write_mms">rašyti MMS pranešimą</string>
+ <string name="app_ops_write_sms">rašyti SMS pranešimą</string>
+ <string name="app_ops_su">gauti „Root“ prieigą</string>
+ <string name="lock_to_app_toast_no_navbar">Kad atsegtumėte šį ekraną palieskite ir laikykite mygtuką atgal.</string>
+ <string name="live_display_auto">Automatinis</string>
+ <string name="live_display_auto_summary">Automatiškai sureguliuoti ekrano spalvos temperatūrą po saulėlydžio ir saulėtekio</string>
+ <string name="live_display_off">Išjungta</string>
+ <string name="live_display_off_summary">Neleisti visų reguliavimų</string>
+ <string name="live_display_day">Diena</string>
+ <string name="live_display_day_summary">Naudoti tik dienos nustatymus</string>
+ <string name="live_display_night">Naktis</string>
+ <string name="live_display_night_summary">Naudoti tik nakties nustatymus</string>
+ <string name="live_display_outdoor">Laukas (ryški saulė)</string>
+ <string name="live_display_outdoor_summary">Naudoti tik lauko nustatymus</string>
+ <string name="live_display_hint">„LiveDisplay“ gali padėti sumažinti akių įtampą ir padėti jums užmigti naktį. Spauskite čia, kad jį išbandyti!</string>
+ <string name="tethered_notification_no_device_message">Nėra prijungto įrenginio</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> prijungtas įrenginys</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> prijungti įrenginiai</string>
+</resources>
diff --git a/core/res/res/values-lv/cm_strings.xml b/core/res/res/values-lv/cm_strings.xml
new file mode 100644
index 0000000..b350009
--- /dev/null
+++ b/core/res/res/values-lv/cm_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ekrānattēls</string>
+ <string name="permlab_receiveProtectedSms">saņemt aizsargātu īsziņu</string>
+ <string name="permdesc_receiveProtectedSms">Ļauj lietotnēm saņemt aizsargātu ienākošo īsziņu.</string>
+ <string name="permlab_modifyProtectedSmsList">mainīt aizsargāto īsziņu sarakstu</string>
+ <string name="permdesc_modifyProtectedSmsList">Ļauj lietotnei mainīt aizsargāto īsziņu adrešu sarakstu.</string>
+ <string name="permgrouplab_security">Drošība</string>
+ <string name="permgroupdesc_security">Atļaujas saistītas ar iekārtas drošības informāciju.</string>
+ <string name="permlab_readPhoneBlacklist">lasīt telefona melno sarakstu</string>
+ <string name="permdesc_readPhoneBlacklist">Ļauj lietotnei lasīt informāciju par bloķētajiem ienākošo zvanu un ziņu telefona numuriem.</string>
+ <string name="permlab_changePhoneBlacklist">mainīt telefona melno sarakstu</string>
+ <string name="permdesc_changePhoneBlacklist">Ļauj lietotnei mainīt bloķēto saņemto zvanu vai īsziņu telefona numurus.</string>
+ <string name="permlab_setKeyguardWallpaper">iestatīt taustiņslēga tapeti</string>
+ <string name="permdesc_setKeyguardWallpaper">Ļauj lietotnei manīt slēgekrāna tapeti.</string>
+ <string name="global_action_reboot">Pārsāknēt</string>
+ <string name="reboot_reboot">Pārsāknēt</string>
+ <string name="reboot_recovery">Atjaunošana</string>
+ <string name="reboot_bootloader">Sāknētājs</string>
+ <string name="reboot_download">Lejuplādēt</string>
+ <string name="reboot_soft">Programmātiskā pārsāknēšana</string>
+ <string name="reboot_title">Restartēt</string>
+ <string name="reboot_confirm" product="tablet">Jūsu planšete pārsāknēsies.</string>
+ <string name="reboot_confirm" product="default">Jūsu telefons pārsāknēsies.</string>
+ <string name="reboot_progress">Pārsāknē\u2026</string>
+ <string name="app_killed_message">Lietotne izbeigta</string>
+ <string name="adb_net_active_notification_title">ADB pa tīklu ieslēgts</string>
+ <string name="adb_both_active_notification_title">ADB pa USB &amp; tīklu ieslēgts</string>
+ <string name="adb_active_generic_notification_message">Pieskarieties, lai atslēgtu atkļūdošanu.</string>
+ <string name="permlab_changePrivacyGuardState">Ieslēgt vai atslēgt Privātuma sargu</string>
+ <string name="permdesc_changePrivacyGuardState">Ļauj lietotnei mainīties pat ja cita lietotne lieto Privātuma Sargu. Kad lietotne darbojas ar privātuma sargu, tai nebūs pieejas personīgajiem datiem, kā kontakti, zvanu saraksts, vai īsziņas.</string>
+ <string name="privacy_guard_notification">Privātuma Sargs ir aktīvs</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> nevarēs piekļūt personīgajiem datiem</string>
+ <string name="privacy_guard_dialog_title">Privātuma sargs</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app"> %1$s </xliff:g> vēlētos <xliff:g id="op"> %2$s </xliff:g>.</string>
+ <string name="permission_remember_choice">Atcerēties manu izvēli</string>
+ <string name="app_ops_access_camera">piekļuve kamerai</string>
+ <string name="app_ops_access_location">piekļeve jūsu atrašanās vietai</string>
+ <string name="app_ops_access_notifications">lasīt jūsu ziņas</string>
+ <string name="app_ops_activate_vpn">aktivizēt VPN</string>
+ <string name="app_ops_auto_start">palaist pēc ieslēgšanas</string>
+ <string name="app_ops_delete_call_log">izdzēst zvanu žurnālu</string>
+ <string name="app_ops_delete_contacts">dzēst jūsu kontaktus</string>
+ <string name="app_ops_delete_mms">dzēst jūsu MMS ziņas</string>
+ <string name="app_ops_delete_sms">dzēst jūsu SMS īsziņas</string>
+ <string name="app_ops_draw_on_top">radīt logus pa virsu</string>
+ <string name="app_ops_get_usage_stats">saņemt lietotnes lietošanas statistiku</string>
+ <string name="app_ops_keep_device_awake">turēt iekārtu nomodā</string>
+ <string name="app_ops_make_phone_call">zvanīt pa telefonu</string>
+ <string name="app_ops_modify_calendar">atjaunot kalendāru</string>
+ <string name="app_ops_modify_call_log">atjaunot zvanu žurnālu</string>
+ <string name="app_ops_modify_clipboard">mainīt starpliktuvi</string>
+ <string name="app_ops_modify_contacts">atjaunot kontaktus</string>
+ <string name="app_ops_modify_settings">atjaunot sistēmas iestatījumus</string>
+ <string name="app_ops_mute_unmute_microphone">izslēgt/ieslēgt mikrofonu</string>
+ <string name="app_ops_play_audio">atskaņot audio failus</string>
+ <string name="app_ops_post_notification">sūtīt ziņas</string>
+ <string name="app_ops_project_media">medija projekts</string>
+ <string name="app_ops_read_calendar">lasīt jūsu kalendāru</string>
+ <string name="app_ops_read_call_log">lasīt zvanu žurnālu</string>
+ <string name="app_ops_read_clipboard">lasīt starpliktuvi</string>
+ <string name="app_ops_read_contacts">lasīt jūsu kontaktus</string>
+ <string name="app_ops_read_mms">lasīt jūsu multivides ziņas</string>
+ <string name="app_ops_read_sms">lasīt jūsu īsziņas</string>
+ <string name="app_ops_receive_sms">saņemt īsziņas</string>
+ <string name="app_ops_record_audio">ierakstīt audio</string>
+ <string name="app_ops_send_mms">sūtīt multiziņu</string>
+ <string name="app_ops_send_sms">sūtīt īsziņu</string>
+ <string name="app_ops_start_at_bootup">palaist pēc ieslēgšanas</string>
+ <string name="app_ops_toggle_bluetooth">ieslēgt Bluetooth</string>
+ <string name="app_ops_toggle_nfc">pārslēgt NFC</string>
+ <string name="app_ops_use_alarm_volume">regulēt trauksmes skaļumu</string>
+ <string name="app_ops_use_audio_focus">regulēt audio fokusu</string>
+ <string name="app_ops_use_bluetooth_volume">regulēt Bluetooth skaļumu</string>
+ <string name="app_ops_use_master_volume">regulēt galveno skaļumu</string>
+ <string name="app_ops_use_media_buttons">lietot multivides pogas</string>
+ <string name="app_ops_use_media_volume">regulēt multivides skaļumu</string>
+ <string name="app_ops_use_notification_volume">regulēt ziņojumu skaļumu</string>
+ <string name="app_ops_use_ring_volume">regulēt zvana skaļumu</string>
+ <string name="app_ops_use_vibrate">lietot vibrāciju atgriezeniskai saitei</string>
+ <string name="app_ops_use_voice_volume">regulēt balss zvana skaļumu</string>
+ <string name="app_ops_write_mms">rakstīt multivides ziņu</string>
+ <string name="app_ops_write_sms">rakstīt īsziņu</string>
+ <string name="app_ops_su">saņemt root piekļuvi</string>
+ <string name="tethered_notification_no_device_message">Nav pievienota ierīce</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> pievienota ierīce</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s </xliff:g> pievienotas ierīces</string>
+</resources>
diff --git a/core/res/res/values-mcc204-mnc02/config.xml b/core/res/res/values-mcc204-mnc02/config.xml
new file mode 100644
index 0000000..ee7a899
--- /dev/null
+++ b/core/res/res/values-mcc204-mnc02/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Tele2: Don't use roaming icon for T-Mo -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>20416</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc07/config.xml b/core/res/res/values-mcc214-mnc07/config.xml
index 4b7cc7c..21d9bf7 100644
--- a/core/res/res/values-mcc214-mnc07/config.xml
+++ b/core/res/res/values-mcc214-mnc07/config.xml
@@ -30,4 +30,32 @@
<item>Conexión Compartida,movistar.es,,,MOVISTAR,MOVISTAR,,,,,214,07,1,DUN</item>
</string-array>
+ <!-- National Language Identifier codes for the following two config items.
+ (from 3GPP TS 23.038 V9.1.1 Table 6.2.1.2.4.1):
+ 0 - reserved
+ 1 - Turkish
+ 2 - Spanish (single shift table only)
+ 3 - Portuguese
+ 4 - Bengali
+ 5 - Gujarati
+ 6 - Hindi
+ 7 - Kannada
+ 8 - Malayalam
+ 9 - Oriya
+ 10 - Punjabi
+ 11 - Tamil
+ 12 - Telugu
+ 13 - Urdu
+ 14+ - reserved -->
+
+ <!-- National language single shift tables to enable for SMS encoding.
+ Decoding is always enabled. 3GPP TS 23.038 states that this feature
+ should not be enabled until a formal request is issued by the relevant
+ national regulatory body. Array elements are codes from the table above.
+ Example 1: devices sold in Turkey must include table 1 to conform with
+ By-Law Number 27230. (http://www.btk.gov.tr/eng/pdf/2009/BY-LAW_SMS.pdf)
+ Example 2: devices sold in India should include tables 4 through 13
+ to enable use of the new Release 9 tables for Indic languages. -->
+ <integer-array name="config_sms_enabled_single_shift_tables"><item>2</item></integer-array>
+
</resources>
diff --git a/core/res/res/values-mcc214-mnc32/config.xml b/core/res/res/values-mcc214-mnc32/config.xml
new file mode 100644
index 0000000..874e3a5
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc32/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources>
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>21405</item>
+ <item>21407</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc219-mnc02/config.xml b/core/res/res/values-mcc219-mnc02/config.xml
index 2ac6ba6..d491951 100644
--- a/core/res/res/values-mcc219-mnc02/config.xml
+++ b/core/res/res/values-mcc219-mnc02/config.xml
@@ -20,6 +20,7 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Don't use roaming icon for considered operators -->
<string-array translatable="false" name="config_operatorConsideredNonRoaming">
- <item>21901</item>
+ <item>21901</item> <!-- Tele2: Don't use roaming icon for T-Mobile -->
+ <item>21910</item> <!-- Tele2: Don't use roaming icon for VIPnet -->
</string-array>
</resources>
diff --git a/core/res/res/values-mcc222-mnc07/config.xml b/core/res/res/values-mcc222-mnc07/config.xml
new file mode 100644
index 0000000..707c769
--- /dev/null
+++ b/core/res/res/values-mcc222-mnc07/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Noverca: Don't use roaming icon for TIM -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>22201</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc03/config.xml b/core/res/res/values-mcc232-mnc03/config.xml
new file mode 100644
index 0000000..bc19384
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc03/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23210</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc05/config.xml b/core/res/res/values-mcc232-mnc05/config.xml
new file mode 100644
index 0000000..11e2585
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc05/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23203</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc10/config.xml b/core/res/res/values-mcc232-mnc10/config.xml
new file mode 100644
index 0000000..11e2585
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc10/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23203</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc11/config.xml b/core/res/res/values-mcc232-mnc11/config.xml
new file mode 100644
index 0000000..27cc63d
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc11/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23201</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc12/config.xml b/core/res/res/values-mcc232-mnc12/config.xml
new file mode 100644
index 0000000..409cecc
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc12/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ /*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23201</item>
+ </string-array>
+</resources>
+
diff --git a/core/res/res/values-mcc234-mnc01/config.xml b/core/res/res/values-mcc234-mnc01/config.xml
new file mode 100644
index 0000000..32335ae2
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc01/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Vectone: Don't use roaming icon for T-Mobile -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc240-mnc10/config.xml b/core/res/res/values-mcc240-mnc10/config.xml
new file mode 100644
index 0000000..28109e0
--- /dev/null
+++ b/core/res/res/values-mcc240-mnc10/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>24005</item>
+ <item>24024</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc244-mnc21/config.xml b/core/res/res/values-mcc244-mnc21/config.xml
new file mode 100644
index 0000000..731a7fd
--- /dev/null
+++ b/core/res/res/values-mcc244-mnc21/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Sunalahti: Don't use roaming icon for Elisa -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>24405</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc260-mnc06/config.xml b/core/res/res/values-mcc260-mnc06/config.xml
new file mode 100644
index 0000000..252565f
--- /dev/null
+++ b/core/res/res/values-mcc260-mnc06/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>26001</item>
+ <item>26002</item>
+ <item>26003</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc268-mnc04/config.xml b/core/res/res/values-mcc268-mnc04/config.xml
new file mode 100644
index 0000000..cc70a32
--- /dev/null
+++ b/core/res/res/values-mcc268-mnc04/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Lycamobile: Don't use roaming icon for Vodafone -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>26801</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc268-mnc07/config.xml b/core/res/res/values-mcc268-mnc07/config.xml
new file mode 100644
index 0000000..8af7199
--- /dev/null
+++ b/core/res/res/values-mcc268-mnc07/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Vectone/Delight: Don't use roaming icon for Optimus/NOS -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>26803</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc272-mnc05/config.xml b/core/res/res/values-mcc272-mnc05/config.xml
new file mode 100644
index 0000000..50770ef
--- /dev/null
+++ b/core/res/res/values-mcc272-mnc05/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>27201</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc272-mnc11/config.xml b/core/res/res/values-mcc272-mnc11/config.xml
new file mode 100644
index 0000000..f7850c9
--- /dev/null
+++ b/core/res/res/values-mcc272-mnc11/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>27202</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index cbe5145..60b67d0 100755
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -39,4 +39,11 @@
<item>true</item>
</string-array>
<string translatable="false" name="prohibit_manual_network_selection_in_gobal_mode">true</string>
+ <!-- Configuration that determines if ACTIVATE_REJECT_GGSN is to be
+ treated as a permanent error -->
+ <bool translatable="false" name="config_reject_ggsn_perm_failure">false</bool>
+ <!-- Configuration that determines if PROTOCOL_ERRORS is to be treated as
+ a permamnent error -->
+ <bool translatable="false" name="config_protocol_errors_perm_failure">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc310-mnc008/config.xml b/core/res/res/values-mcc310-mnc008/config.xml
new file mode 100644
index 0000000..48c98cc
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc008/config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright (c) 2014 The Linux Foundation. All rights reserved.
+** Not a Contribution.
+** 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Configuration that determines if ACTIVATE_REJECT_GGSN is to be
+ treated as a permanent error -->
+ <bool translatable="false" name="config_reject_ggsn_perm_failure">false</bool>
+ <!-- Configuration that determines if PROTOCOL_ERRORS is to be treated as
+ a permamnent error -->
+ <bool translatable="false" name="config_protocol_errors_perm_failure">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc310-mnc009/config.xml b/core/res/res/values-mcc310-mnc009/config.xml
new file mode 100644
index 0000000..48c98cc
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc009/config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright (c) 2014 The Linux Foundation. All rights reserved.
+** Not a Contribution.
+** 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Configuration that determines if ACTIVATE_REJECT_GGSN is to be
+ treated as a permanent error -->
+ <bool translatable="false" name="config_reject_ggsn_perm_failure">false</bool>
+ <!-- Configuration that determines if PROTOCOL_ERRORS is to be treated as
+ a permamnent error -->
+ <bool translatable="false" name="config_protocol_errors_perm_failure">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index a986b75..343033d 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -69,4 +69,10 @@
<item>true</item>
</string-array>
<string translatable="false" name="prohibit_manual_network_selection_in_gobal_mode">true</string>
+ <!-- Configuration that determines if ACTIVATE_REJECT_GGSN is to be
+ treated as a permanent error -->
+ <bool translatable="false" name="config_reject_ggsn_perm_failure">false</bool>
+ <!-- Configuration that determines if PROTOCOL_ERRORS is to be treated as
+ a permamnent error -->
+ <bool translatable="false" name="config_protocol_errors_perm_failure">false</bool>
</resources>
diff --git a/core/res/res/values-mcc404-mnc55/config.xml b/core/res/res/values-mcc404-mnc55/config.xml
new file mode 100644
index 0000000..14d3d36
--- /dev/null
+++ b/core/res/res/values-mcc404-mnc55/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>40454</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-nb/cm_strings.xml b/core/res/res/values-nb/cm_strings.xml
new file mode 100644
index 0000000..791d6ce
--- /dev/null
+++ b/core/res/res/values-nb/cm_strings.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Skjermbilde</string>
+ <string name="permlab_receiveProtectedSms">motta beskyttet SMS</string>
+ <string name="permdesc_receiveProtectedSms">Lar programmet motta innkommende beskyttede SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">endre beskyttede SMS-listen</string>
+ <string name="permdesc_modifyProtectedSmsList">Lar programmet endre adresselisten for beskyttede SMS.</string>
+ <string name="permgrouplab_security">Sikkerhet</string>
+ <string name="permgroupdesc_security">Tillatelser knyttet til enhetens sikkerhetsinformasjon.</string>
+ <string name="permlab_readPhoneBlacklist">les telefonens svarteliste</string>
+ <string name="permdesc_readPhoneBlacklist">Tillater en app å lese informasjon om telefonnummer som er blokkert for innkommende samtaler eller meldinger.</string>
+ <string name="permlab_changePhoneBlacklist">endre telefonens svarteliste</string>
+ <string name="permdesc_changePhoneBlacklist">Tillater en app å endre telefonnummer som er blokkert for innkommende samtaler eller meldinger.</string>
+ <string name="permlab_setKeyguardWallpaper">Angi tastaturbakgrunn</string>
+ <string name="permdesc_setKeyguardWallpaper">Tillat en app å endre låseskjermsbakgrunn.</string>
+ <string name="global_action_reboot">Start på nytt</string>
+ <string name="global_action_current_user">Nåværende</string>
+ <string name="reboot_reboot">Start på nytt</string>
+ <string name="reboot_recovery">Gjenoppretting</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Myk omstart</string>
+ <string name="reboot_title">Omstart</string>
+ <string name="reboot_confirm" product="tablet">Nettbrettet startes på nytt.</string>
+ <string name="reboot_confirm" product="default">Telefonen startes på nytt.</string>
+ <string name="reboot_progress">Starter på nytt\u2026</string>
+ <string name="app_killed_message">App stoppet</string>
+ <string name="adb_net_active_notification_title">ADB over nettverk aktivert</string>
+ <string name="adb_both_active_notification_title">ADB over USB &amp; nettverk aktivert</string>
+ <string name="adb_active_generic_notification_message">Trykk for å deaktivere feilsøking.</string>
+ <string name="adb_active_custom_tile">ADB – <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB og nettverk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Nettverk</string>
+ <string name="permlab_interceptPackageLaunch">avbryt app start</string>
+ <string name="stylus_app_not_installed">%s er ikke installert</string>
+ <string name="silent_mode_priority">Prioritet</string>
+ <string name="silent_mode_none">Ingen</string>
+ <string name="subscription_change_disabled_wifi_ap">Deaktivert Wi-Fi hotspot på grunn av endring i SIM-abbonement</string>
+ <string name="notify_turn_wifi_off_title">Deaktiver Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">aktivere eller deaktivere personvernvakt</string>
+ <string name="permdesc_changePrivacyGuardState">Lar appen endre om en annen app kjører med personlighetsvern. Når en app kjører med personlighetsvern vil den ikke ha tilgang til personlig data som kontakter, samtalelogg eller meldinger.</string>
+ <string name="privacy_guard_notification">Personvernvakt aktiv</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> vil ikke få tilgang til personlige data</string>
+ <string name="privacy_guard_dialog_title">Personvernvakt</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> vil gjerne <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Husk mitt valg</string>
+ <string name="app_ops_access_camera">tilgang til kameraet</string>
+ <string name="app_ops_access_location">tilgang til din plassering</string>
+ <string name="app_ops_access_notifications">lese dine notifikasjoner</string>
+ <string name="app_ops_activate_vpn">aktiver en VPN</string>
+ <string name="app_ops_auto_start">start under oppstart</string>
+ <string name="app_ops_delete_call_log">Slett samtaleloggen</string>
+ <string name="app_ops_delete_contacts">Slett kontaktene dine</string>
+ <string name="app_ops_delete_mms">slett dine MMS-meldinger</string>
+ <string name="app_ops_delete_sms">slett dine SMS-meldinger</string>
+ <string name="app_ops_draw_on_top">tegn vinduer på topp</string>
+ <string name="app_ops_get_usage_stats">få brukstatistikk over app</string>
+ <string name="app_ops_keep_device_awake">holde enheten våken</string>
+ <string name="app_ops_make_phone_call">utføre en samtale</string>
+ <string name="app_ops_modify_calendar">oppdatere kalenderen</string>
+ <string name="app_ops_modify_call_log">oppdatere samtaleloggen</string>
+ <string name="app_ops_modify_clipboard">endre utklippstavlen</string>
+ <string name="app_ops_modify_contacts">Oppdater kontaktene</string>
+ <string name="app_ops_modify_settings">oppdatere systeminnstillinger</string>
+ <string name="app_ops_mute_unmute_microphone">Demp/fjern demping av mikrofonen</string>
+ <string name="app_ops_play_audio">spille av lyd</string>
+ <string name="app_ops_post_notification">legge inn en melding</string>
+ <string name="app_ops_project_media">Prosjekt media</string>
+ <string name="app_ops_read_calendar">lese kalenderen</string>
+ <string name="app_ops_read_call_log">lese i samtaleloggen</string>
+ <string name="app_ops_read_clipboard">lese utklippstavlen</string>
+ <string name="app_ops_read_contacts">lese kontaktene</string>
+ <string name="app_ops_read_mms">lese MMS meldinger</string>
+ <string name="app_ops_read_sms">lese SMS-meldinger</string>
+ <string name="app_ops_receive_sms">motta en SMS-melding</string>
+ <string name="app_ops_record_audio">spille inn lyd</string>
+ <string name="app_ops_send_mms">sende en MMS-melding</string>
+ <string name="app_ops_send_sms">sende en tekstmelding</string>
+ <string name="app_ops_start_at_bootup">starte under oppstart</string>
+ <string name="app_ops_toast_window">vis toast meldinger</string>
+ <string name="app_ops_toggle_bluetooth">aktivere/deaktivere bluetooth</string>
+ <string name="app_ops_toggle_nfc">NFC av/på</string>
+ <string name="app_ops_toggle_wifi">veksle Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">styre alarmvolum</string>
+ <string name="app_ops_use_audio_focus">styre lydfokus</string>
+ <string name="app_ops_use_bluetooth_volume">styre bluetooth volum</string>
+ <string name="app_ops_use_master_volume">styre hovedvolum</string>
+ <string name="app_ops_use_media_buttons">bruke mediaknappene</string>
+ <string name="app_ops_use_media_volume">styre mediavolum</string>
+ <string name="app_ops_use_notification_volume">styre varslingsvolum</string>
+ <string name="app_ops_use_ring_volume">styre ringevolum</string>
+ <string name="app_ops_use_vibrate">Bruk haptisk tilbakemelding</string>
+ <string name="app_ops_use_voice_volume">styre stemmesamtalevolum</string>
+ <string name="app_ops_write_mms">skrive en MMS-melding</string>
+ <string name="app_ops_write_sms">skrive en tekstmelding</string>
+ <string name="app_ops_use_fingerprint">bruk fingeravtrykk</string>
+ <string name="app_ops_add_voicemail">legge til en telefonsvarer</string>
+ <string name="app_ops_read_phone_state">hente telefontilstand</string>
+ <string name="app_ops_scan_wifi">skann trådløse nettverk</string>
+ <string name="app_ops_change_wallpaper">endre bakgrunnsbilde</string>
+ <string name="app_ops_assist_structure">bruke hjelpestruktur</string>
+ <string name="app_ops_assist_screenshot">ta et skjermbilde</string>
+ <string name="app_ops_use_body_sensors">bruke enhetssensorer</string>
+ <string name="app_ops_read_cell_broadcasts">lese cellekringkastinger</string>
+ <string name="app_ops_mock_location">simulere posisjon</string>
+ <string name="app_ops_read_external_storage">lese fra ekstern lagring</string>
+ <string name="app_ops_write_external_storage">skrive til ekstern lagring</string>
+ <string name="app_ops_turn_on_screen">slå skjermen på</string>
+ <string name="app_ops_get_accounts">hente enhetskontoer</string>
+ <string name="app_ops_wifi_change">endre Wi-Fi-tilstand</string>
+ <string name="app_ops_su">få root-tilgang</string>
+ <string name="lock_to_app_toast_no_navbar">For å unpin denne skjermen, trykk og hold tilbake-knappen.</string>
+ <string name="live_display_auto">Automatisk</string>
+ <string name="live_display_auto_summary">Juster fargetemperatur på skjermen etter solnedgang og soloppgang</string>
+ <string name="live_display_off">Av</string>
+ <string name="live_display_off_summary">Deaktivere alle justeringer</string>
+ <string name="live_display_day">Dag</string>
+ <string name="live_display_day_summary">Bruk kun dag innstillinger</string>
+ <string name="live_display_night">Natt</string>
+ <string name="live_display_night_summary">Bruk kun natt instillinger</string>
+ <string name="live_display_outdoor">Utendørs (sterkt sollys)</string>
+ <string name="live_display_outdoor_summary">Bruk kun utendørs innstillinger</string>
+ <string name="live_display_hint">LiveDisplay kan hjelpe deg med å redusere belastningen på øynene og hjelpe deg med å sove om natten. Trykk her for å prøve det ut!</string>
+ <string name="tethered_notification_no_device_message">Ingen tilkoblede enheter</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> tilkoblet enhet</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> tilkoblede enheter</string>
+ <string name="notify_package_component_protected_title">Aktivitets oppstart blokkert</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> er beskyttet mot oppstart. Trykk for å godkjenne og starte programmet.</string>
+</resources>
diff --git a/core/res/res/values-nl/cm_strings.xml b/core/res/res/values-nl/cm_strings.xml
new file mode 100644
index 0000000..6d72bbd
--- /dev/null
+++ b/core/res/res/values-nl/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Screenshot</string>
+ <string name="permlab_receiveProtectedSms">beschermd sms-bericht ontvangen</string>
+ <string name="permdesc_receiveProtectedSms">Hiermee kan de app een inkomend beschermd sms-bericht ontvangen.</string>
+ <string name="permlab_modifyProtectedSmsList">beschermde sms-berichtenlijst wijzigen</string>
+ <string name="permdesc_modifyProtectedSmsList">Hiermee kan de app de lijst van beschermde sms-adressen wijzigen.</string>
+ <string name="permgrouplab_security">Beveiliging</string>
+ <string name="permgroupdesc_security">Machtigingen gerelateerd aan beveiligingsinformatie van het apparaat.</string>
+ <string name="permlab_readPhoneBlacklist">zwarte lijst lezen</string>
+ <string name="permdesc_readPhoneBlacklist">Hiermee kan de app informatie lezen over telefoonnummers waarvan inkomende oproepen of berichten zijn geblokkeerd.</string>
+ <string name="permlab_changePhoneBlacklist">zwarte lijst aanpassen</string>
+ <string name="permdesc_changePhoneBlacklist">Hiermee kan de app telefoonnummers aanpassen waarvan inkomende oproepen of berichten zijn geblokkeerd.</string>
+ <string name="permlab_setKeyguardWallpaper">achtergrond van vergrendelingsscherm instellen</string>
+ <string name="permdesc_setKeyguardWallpaper">Hiermee kan de app de achtergrond van het vergrendelingsscherm aanpassen.</string>
+ <string name="global_action_reboot">Herstarten</string>
+ <string name="global_action_current_user">Huidige</string>
+ <string name="reboot_reboot">Herstarten</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Soft reboot</string>
+ <string name="reboot_title">Herstarten</string>
+ <string name="reboot_confirm" product="tablet">Uw tablet wordt herstart.</string>
+ <string name="reboot_confirm" product="default">Uw telefoon wordt herstart.</string>
+ <string name="reboot_progress">Herstarten\u2026</string>
+ <string name="app_killed_message">App afgesloten</string>
+ <string name="adb_net_active_notification_title">ADB over netwerk ingeschakeld</string>
+ <string name="adb_both_active_notification_title">ADB over USB &amp; netwerk ingeschakeld</string>
+ <string name="adb_active_generic_notification_message">Tik om foutopsporing uit te schakelen.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; netwerk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Netwerk</string>
+ <string name="permlab_interceptPackageLaunch">Openen van app onderscheppen</string>
+ <string name="stylus_app_not_installed">%s is niet geïnstalleerd</string>
+ <string name="silent_mode_priority">Prioriteit</string>
+ <string name="silent_mode_none">Geen</string>
+ <string name="subscription_change_disabled_wifi_ap">Wifi-hotspot uitgeschakeld door een SIM-abonnementwijziging</string>
+ <string name="notify_turn_wifi_off_title">Wifi uitschakelen</string>
+ <string name="permlab_changePrivacyGuardState">Privacybescherming in- of uitschakelen</string>
+ <string name="permdesc_changePrivacyGuardState">Hiermee kan de app bepalen of een andere app start met Privacybescherming. Als een app start met Privacybescherming, zal het geen toegang hebben tot persoonsgegevens zoals contacten, berichten of gespreksstatistieken.</string>
+ <string name="privacy_guard_notification">Privacybescherming actief</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> zal geen toegang hebben tot persoonsgegevens</string>
+ <string name="privacy_guard_dialog_title">Privacybescherming</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> wil <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Keuze onthouden</string>
+ <string name="app_ops_access_camera">toegang tot camera</string>
+ <string name="app_ops_access_location">toegang tot uw locatie</string>
+ <string name="app_ops_access_notifications">meldingen lezen</string>
+ <string name="app_ops_activate_vpn">VPN activeren</string>
+ <string name="app_ops_auto_start">starten tijdens opstarten</string>
+ <string name="app_ops_delete_call_log">gespreksstatistieken verwijderen</string>
+ <string name="app_ops_delete_contacts">contacten verwijderen</string>
+ <string name="app_ops_delete_mms">mms-berichten verwijderen</string>
+ <string name="app_ops_delete_sms">sms-berichten verwijderen</string>
+ <string name="app_ops_draw_on_top">bovenop tekenen</string>
+ <string name="app_ops_get_usage_stats">app-gebruiksstatistieken opvragen</string>
+ <string name="app_ops_keep_device_awake">apparaat wakker houden</string>
+ <string name="app_ops_make_phone_call">telefoongesprek starten</string>
+ <string name="app_ops_modify_calendar">agenda vernieuwen</string>
+ <string name="app_ops_modify_call_log">gespreksstatistieken vernieuwen</string>
+ <string name="app_ops_modify_clipboard">klembord aanpassen</string>
+ <string name="app_ops_modify_contacts">contacten vernieuwen</string>
+ <string name="app_ops_modify_settings">systeeminstellingen vernieuwen</string>
+ <string name="app_ops_mute_unmute_microphone">microfoon in-/uitschakelen</string>
+ <string name="app_ops_play_audio">audio afspelen</string>
+ <string name="app_ops_post_notification">melding tonen</string>
+ <string name="app_ops_project_media">media projecteren</string>
+ <string name="app_ops_read_calendar">agenda lezen</string>
+ <string name="app_ops_read_call_log">gespreksstatistieken lezen</string>
+ <string name="app_ops_read_clipboard">klembord lezen</string>
+ <string name="app_ops_read_contacts">contacten lezen</string>
+ <string name="app_ops_read_mms">mms-berichten lezen</string>
+ <string name="app_ops_read_sms">sms-berichten lezen</string>
+ <string name="app_ops_receive_sms">sms-bericht ontvangen</string>
+ <string name="app_ops_record_audio">audio opnemen</string>
+ <string name="app_ops_send_mms">mms-bericht versturen</string>
+ <string name="app_ops_send_sms">sms-bericht versturen</string>
+ <string name="app_ops_start_at_bootup">starten tijdens opstarten</string>
+ <string name="app_ops_toast_window">meldingen weergeven</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth aan-/uitzetten</string>
+ <string name="app_ops_toggle_mobile_data">mobiele gegevens aan-/uitzetten</string>
+ <string name="app_ops_toggle_nfc">NFC aan-/uitzetten</string>
+ <string name="app_ops_toggle_wifi">wifi aan-/uitzetten</string>
+ <string name="app_ops_use_alarm_volume">alarmvolume beheren</string>
+ <string name="app_ops_use_audio_focus">audiofocus beheren</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetooth-volume beheren</string>
+ <string name="app_ops_use_master_volume">hoofdvolume beheren</string>
+ <string name="app_ops_use_media_buttons">mediaknoppen gebruiken</string>
+ <string name="app_ops_use_media_volume">mediavolume beheren</string>
+ <string name="app_ops_use_notification_volume">meldingsvolume beheren</string>
+ <string name="app_ops_use_ring_volume">beltoonvolume beheren</string>
+ <string name="app_ops_use_vibrate">trillen gebruiken</string>
+ <string name="app_ops_use_voice_volume">stemvolume beheren</string>
+ <string name="app_ops_write_mms">mms-bericht schrijven</string>
+ <string name="app_ops_write_sms">sms-bericht schrijven</string>
+ <string name="app_ops_use_fingerprint">vingerafdruk gebruiken</string>
+ <string name="app_ops_add_voicemail">voicemail toevoegen</string>
+ <string name="app_ops_read_phone_state">toegang tot telefoonstatus</string>
+ <string name="app_ops_scan_wifi">wifi-netwerken scannen</string>
+ <string name="app_ops_change_wallpaper">achtergrond aanpassen</string>
+ <string name="app_ops_assist_structure">structuur voor ondersteuning gebruiken</string>
+ <string name="app_ops_assist_screenshot">screenshot maken</string>
+ <string name="app_ops_use_body_sensors">lichaamssensoren gebruiken</string>
+ <string name="app_ops_read_cell_broadcasts">nooduitzendingen lezen</string>
+ <string name="app_ops_mock_location">neplocatie gebruiken</string>
+ <string name="app_ops_read_external_storage">externe opslag lezen</string>
+ <string name="app_ops_write_external_storage">naar externe opslag schrijven</string>
+ <string name="app_ops_turn_on_screen">scherm aanzetten</string>
+ <string name="app_ops_get_accounts">apparaataccounts opvragen</string>
+ <string name="app_ops_wifi_change">wifi-status aanpassen</string>
+ <string name="app_ops_su">root-toegang krijgen</string>
+ <string name="lock_to_app_toast_no_navbar">Blijf de Terug-knop aanraken om dit scherm los te maken.</string>
+ <string name="live_display_auto">Automatisch</string>
+ <string name="live_display_auto_summary">Automatisch kleurtemperatuur van scherm aanpassen na zonsopkomst en -ondergang</string>
+ <string name="live_display_off">Uit</string>
+ <string name="live_display_off_summary">Alle aanpassingen uitschakelen</string>
+ <string name="live_display_day">Overdag</string>
+ <string name="live_display_day_summary">Alleen instellingen voor overdag gebruiken</string>
+ <string name="live_display_night">\'s Nachts</string>
+ <string name="live_display_night_summary">Alleen instellingen voor \'s nachts gebruiken</string>
+ <string name="live_display_outdoor">Buitenshuis (felle zon)</string>
+ <string name="live_display_outdoor_summary">Alleen instellingen voor buitenshuis gebruiken</string>
+ <string name="live_display_hint">LiveDisplay kan oogvermoeidheid verminderen en helpt u om \'s nachts te slapen. Tik hier om het uit te proberen</string>
+ <string name="tethered_notification_no_device_message">Geen aangesloten apparaat</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> aangesloten apparaat</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> aangesloten apparaten</string>
+ <string name="notify_package_component_protected_title">Starten van activiteit geblokkeerd</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> is beschermd tegen opstarten. Tik om aan te melden en de app te starten.</string>
+ <string name="notify_battery_fully_charged_title">Accu volledig opgeladen</string>
+ <string name="notify_battery_fully_charged_text">Ontkoppel uw apparaat van de oplader om de levensduur van de accu te verlengen.</string>
+</resources>
diff --git a/core/res/res/values-pl/cm_strings.xml b/core/res/res/values-pl/cm_strings.xml
new file mode 100644
index 0000000..f9706fc
--- /dev/null
+++ b/core/res/res/values-pl/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Zrzut ekranu</string>
+ <string name="permlab_receiveProtectedSms">odbieranie chronionych SMS-ów</string>
+ <string name="permdesc_receiveProtectedSms">Umożliwia aplikacji odbieranie przychodzących chronionych SMS-ów.</string>
+ <string name="permlab_modifyProtectedSmsList">Modyfikowanie listy chronionych SMS-ów</string>
+ <string name="permdesc_modifyProtectedSmsList">Umożliwia aplikacji modyfikowanie listy chronionych SMS-ów.</string>
+ <string name="permgrouplab_security">Zabezpieczenia</string>
+ <string name="permgroupdesc_security">Uprawnienia związane z informacjami o bezpieczeństwie urządzenia.</string>
+ <string name="permlab_readPhoneBlacklist">odczytywanie czarnej listy</string>
+ <string name="permdesc_readPhoneBlacklist">Umożliwia aplikacji odczytywanie informacji o numerach telefonów, od których przychodzące połączenia i wiadomości są blokowane.</string>
+ <string name="permlab_changePhoneBlacklist">edytowanie czarnej listy</string>
+ <string name="permdesc_changePhoneBlacklist">Umożliwia aplikacji zmianę numerów telefonów, od których przychodzące połączenia i wiadomości są blokowane.</string>
+ <string name="permlab_setKeyguardWallpaper">Ustawianie tła ekranu blokady</string>
+ <string name="permdesc_setKeyguardWallpaper">Umożliwia aplikacji zmianę tła ekranu blokady.</string>
+ <string name="global_action_reboot">Uruchom ponownie</string>
+ <string name="global_action_current_user">Bieżący</string>
+ <string name="reboot_reboot">Uruchom ponownie</string>
+ <string name="reboot_recovery">Uruchom w trybie Recovery</string>
+ <string name="reboot_bootloader">Uruchom w trybie Bootloader</string>
+ <string name="reboot_download">Uruchom w trybie Download</string>
+ <string name="reboot_soft">Miękki restart</string>
+ <string name="reboot_title">Uruchom ponownie</string>
+ <string name="reboot_confirm" product="tablet">Tablet zostanie uruchomiony ponownie.</string>
+ <string name="reboot_confirm" product="default">Telefon zostanie uruchomiony ponownie.</string>
+ <string name="reboot_progress">Ponowne uruchamianie\u2026</string>
+ <string name="app_killed_message">Aplikacja została zamknięta</string>
+ <string name="adb_net_active_notification_title">ADB przez sieć włączone</string>
+ <string name="adb_both_active_notification_title">ADB przez USB &amp; sieć włączone</string>
+ <string name="adb_active_generic_notification_message">Dotknij, aby wyłączyć debugowanie.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; sieć</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Sieć</string>
+ <string name="permlab_interceptPackageLaunch">przechwytywanie uruchamiania aplikacji</string>
+ <string name="stylus_app_not_installed">Nie zainstalowano aplikacji %s</string>
+ <string name="silent_mode_priority">Priorytet</string>
+ <string name="silent_mode_none">Brak</string>
+ <string name="subscription_change_disabled_wifi_ap">Wyłączono hotspot WiFi z powodu zmiany karty SIM</string>
+ <string name="notify_turn_wifi_off_title">Wyłącz Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">włącz/wyłącz Ochronę Prywatności</string>
+ <string name="permdesc_changePrivacyGuardState">Pozwala aplikacji decydować, kiedy inna aplikacja zostanie uruchomiona w trybie ochrony prywatności. W trybie tym aplikacje nie mają dostępu do osobistych danych użytkownika, takich jak kontakty, historia połączeń czy wiadomości.</string>
+ <string name="privacy_guard_notification">Ochrona prywatności aktywna</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> nie będzie mieć dostępu do osobistych danych</string>
+ <string name="privacy_guard_dialog_title">Ochrona prywatności</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> czy chciałbyś <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Zapamiętaj mój wybór</string>
+ <string name="app_ops_access_camera">dostęp do kamery</string>
+ <string name="app_ops_access_location">dostęp do lokalizacji</string>
+ <string name="app_ops_access_notifications">czytanie powiadomień</string>
+ <string name="app_ops_activate_vpn">aktywowanie VPN</string>
+ <string name="app_ops_auto_start">uruchamianie podczas włączania urządzenia</string>
+ <string name="app_ops_delete_call_log">usuwanie dziennika połączeń</string>
+ <string name="app_ops_delete_contacts">usuwanie kontaktów</string>
+ <string name="app_ops_delete_mms">usuwanie wiadomości MMS</string>
+ <string name="app_ops_delete_sms">usuwanie wiadomości SMS</string>
+ <string name="app_ops_draw_on_top">rysowanie okien na wierzchu</string>
+ <string name="app_ops_get_usage_stats">uzyskanie statystyk użytkowania aplikacji</string>
+ <string name="app_ops_keep_device_awake">zapobieganie przejściu telefonu w stan uśpienia</string>
+ <string name="app_ops_make_phone_call">wykonywanie połączeń telefonicznych</string>
+ <string name="app_ops_modify_calendar">aktualizowanie kalendarza</string>
+ <string name="app_ops_modify_call_log">aktualizowanie rejestru połączeń</string>
+ <string name="app_ops_modify_clipboard">modyfikowanie schowka</string>
+ <string name="app_ops_modify_contacts">aktualizowanie kontaktów</string>
+ <string name="app_ops_modify_settings">aktualizowanie ustawień systemowych</string>
+ <string name="app_ops_mute_unmute_microphone">włączanie/wyłączanie mikrofonu</string>
+ <string name="app_ops_play_audio">odtwarzanie dźwięków</string>
+ <string name="app_ops_post_notification">wysyłanie powiadomienia</string>
+ <string name="app_ops_project_media">wyświetlanie multimediów</string>
+ <string name="app_ops_read_calendar">czytanie kalendarza</string>
+ <string name="app_ops_read_call_log">czytanie rejestru połączeń</string>
+ <string name="app_ops_read_clipboard">czytanie schowka</string>
+ <string name="app_ops_read_contacts">czytanie kontaktów</string>
+ <string name="app_ops_read_mms">czytanie MMS-ów</string>
+ <string name="app_ops_read_sms">czytanie SMS-ów</string>
+ <string name="app_ops_receive_sms">odbieranie SMS-ów</string>
+ <string name="app_ops_record_audio">nagrywanie dźwięku</string>
+ <string name="app_ops_send_mms">wysyłanie MMS-ów</string>
+ <string name="app_ops_send_sms">wysyłanie SMS-ów</string>
+ <string name="app_ops_start_at_bootup">uruchamianie podczas włączania urządzenia</string>
+ <string name="app_ops_toast_window">wyświetlanie komunikatów w dymkach</string>
+ <string name="app_ops_toggle_bluetooth">przełączanie Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">przełączanie transmisji danych</string>
+ <string name="app_ops_toggle_nfc">Przełączanie NFC</string>
+ <string name="app_ops_toggle_wifi">przełączanie Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">kontrolowanie głośności alarmu</string>
+ <string name="app_ops_use_audio_focus">kontrolowanie priorytetów audio</string>
+ <string name="app_ops_use_bluetooth_volume">kontrolowanie głośności urządzenia Bluetooth</string>
+ <string name="app_ops_use_master_volume">kontrolowanie głośności</string>
+ <string name="app_ops_use_media_buttons">używanie przycisków mediów</string>
+ <string name="app_ops_use_media_volume">kontrolowanie głośności mediów</string>
+ <string name="app_ops_use_notification_volume">kontrolowanie głośności powiadomień</string>
+ <string name="app_ops_use_ring_volume">kontrolowanie głośności dzwonka</string>
+ <string name="app_ops_use_vibrate">używanie haptic feedback</string>
+ <string name="app_ops_use_voice_volume">kontrolowanie głośności rozmów</string>
+ <string name="app_ops_write_mms">pisanie MMS-ów</string>
+ <string name="app_ops_write_sms">pisanie SMS-ów</string>
+ <string name="app_ops_use_fingerprint">odczyt linii papilarnych</string>
+ <string name="app_ops_add_voicemail">dodawanie wiadomości głosowej</string>
+ <string name="app_ops_read_phone_state">dostęp do stanu telefonu</string>
+ <string name="app_ops_scan_wifi">skanowanie sieci Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">zmiana tapety</string>
+ <string name="app_ops_assist_structure">wykorzystanie asystenta</string>
+ <string name="app_ops_assist_screenshot">tworzenie zrzutów ekranu</string>
+ <string name="app_ops_use_body_sensors">odczyt czujników ciała</string>
+ <string name="app_ops_read_cell_broadcasts">odczyt transmisji komórkowych</string>
+ <string name="app_ops_mock_location">pozorowanie twojej lokalizacji</string>
+ <string name="app_ops_read_external_storage">odczyt pamięci zewnętrznej</string>
+ <string name="app_ops_write_external_storage">zapis pamięci zewnętrznej</string>
+ <string name="app_ops_turn_on_screen">włączanie ekranu</string>
+ <string name="app_ops_get_accounts">dostęp do kont urządzenia</string>
+ <string name="app_ops_wifi_change">zmiana stanu Wi-Fi</string>
+ <string name="app_ops_su">dostęp do roota</string>
+ <string name="lock_to_app_toast_no_navbar">Aby odpiąć ekran, dotknij i przytrzymaj przycisk Wstecz.</string>
+ <string name="live_display_auto">Automatycznie</string>
+ <string name="live_display_auto_summary">Automatycznie dostosuj temperaturę kolorów ekranu po zachodzie i wschodzie słońca</string>
+ <string name="live_display_off">Wyłączony</string>
+ <string name="live_display_off_summary">Wyłącz wszystkie zmiany</string>
+ <string name="live_display_day">Dzień</string>
+ <string name="live_display_day_summary">Używaj tylko ustawień na dzień</string>
+ <string name="live_display_night">Noc</string>
+ <string name="live_display_night_summary">Używaj ustawień tylko w nocy</string>
+ <string name="live_display_outdoor">Na zewnątrz (jasne światło)</string>
+ <string name="live_display_outdoor_summary">Używaj ustawienia tylko na zewnątrz</string>
+ <string name="live_display_hint">LiveDisplay może pomóc w zredukowaniu efektu zmęczenia oczu oraz pomaga zasnąć w nocy. Kliknij tutaj, aby wypróbować!</string>
+ <string name="tethered_notification_no_device_message">Brak podłączonego urządzenia</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> podłączone urządzenie</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s </xliff:g> podłączone urządzenia</string>
+ <string name="notify_package_component_protected_title">Aktywność uruchamiania zablokowana</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s </xliff:g> jest chroniony(a) przed uruchomieniem. Kliknij, aby uwierzytelnić i uruchomić tę aplikację.</string>
+ <string name="notify_battery_fully_charged_title">Bateria naładowana</string>
+ <string name="notify_battery_fully_charged_text">Odłącz urządzenie od ładowarki, aby poprawić żywotność baterii.</string>
+</resources>
diff --git a/core/res/res/values-pt-rBR/cm_strings.xml b/core/res/res/values-pt-rBR/cm_strings.xml
new file mode 100644
index 0000000..622e01a
--- /dev/null
+++ b/core/res/res/values-pt-rBR/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Capturar tela</string>
+ <string name="permlab_receiveProtectedSms">receber SMS protegido</string>
+ <string name="permdesc_receiveProtectedSms">Permite ao aplicativo receber um SMS protegido.</string>
+ <string name="permlab_modifyProtectedSmsList">modifica a lista de SMS protegidos</string>
+ <string name="permdesc_modifyProtectedSmsList">Permite ao aplicativo modificar a lista de endereço de SMS protegido.</string>
+ <string name="permgrouplab_security">Segurança</string>
+ <string name="permgroupdesc_security">Permissões relacionadas com as informações de segurança do aparelho.</string>
+ <string name="permlab_readPhoneBlacklist">Ler a lista negra do telefone</string>
+ <string name="permdesc_readPhoneBlacklist">Permite que um aplicativo leia informações sobre números de telefone bloqueados para efetuar chamadas ou enviar mensagens.</string>
+ <string name="permlab_changePhoneBlacklist">alterar a lista negra do telefone</string>
+ <string name="permdesc_changePhoneBlacklist">Permite que um aplicativo altere os números de telefone bloqueados para efetuar chamadas ou enviar mensagens.</string>
+ <string name="permlab_setKeyguardWallpaper">definir papel de parede da tela de bloqueio</string>
+ <string name="permdesc_setKeyguardWallpaper">Permite um aplicativo a trocar o papel de parede da tela de bloqueio.</string>
+ <string name="global_action_reboot">Reiniciar</string>
+ <string name="global_action_current_user">Atual</string>
+ <string name="reboot_reboot">Reiniciar</string>
+ <string name="reboot_recovery">Recuperação</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Reiniciar via software</string>
+ <string name="reboot_title">Reiniciar</string>
+ <string name="reboot_confirm" product="tablet">Seu tablet irá reiniciar.</string>
+ <string name="reboot_confirm" product="default">Seu telefone irá reiniciar.</string>
+ <string name="reboot_progress">Reiniciando\u2026</string>
+ <string name="app_killed_message">Aplicativo encerrado</string>
+ <string name="adb_net_active_notification_title">ADB sobre rede ativado</string>
+ <string name="adb_both_active_notification_title">ABD sobre USB e rede ativado</string>
+ <string name="adb_active_generic_notification_message">Toque para desativar a depuração.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB e rede</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Rede</string>
+ <string name="permlab_interceptPackageLaunch">interceptar inicialização de app</string>
+ <string name="stylus_app_not_installed">%s não está instalado</string>
+ <string name="silent_mode_priority">Prioridade</string>
+ <string name="silent_mode_none">Nenhum</string>
+ <string name="subscription_change_disabled_wifi_ap">Hotspot Wi-Fi desativado devido a mudança de assinatura do SIM</string>
+ <string name="notify_turn_wifi_off_title">Desligar Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">ativar ou desativar a Proteção da Privacidade</string>
+ <string name="permdesc_changePrivacyGuardState">Permite ao aplicativo alterar se outra aplicação executa com Proteção à Privacidade. Quando um aplicativo estiver executando com Proteção à Privacidade, ela será capaz de acessar dados pessoais como contatos, registro de chamadas, ou mensagens.</string>
+ <string name="privacy_guard_notification">Proteção à Privacidade ativa</string>
+ <string name="privacy_guard_notification_detail"><xliff:g xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" id="app">%1$s</xliff:g> não será capaz de acessar dados pessoais</string>
+ <string name="privacy_guard_dialog_title">Proteção à Privacidade</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> gostaria de <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Lembrar minha escolha</string>
+ <string name="app_ops_access_camera">acessar a câmera</string>
+ <string name="app_ops_access_location">acessar sua localização</string>
+ <string name="app_ops_access_notifications">ler suas notificações</string>
+ <string name="app_ops_activate_vpn">ativar uma VPN</string>
+ <string name="app_ops_auto_start">iniciar ao ligar</string>
+ <string name="app_ops_delete_call_log">excluir seu registro de chamadas</string>
+ <string name="app_ops_delete_contacts">excluir seus contatos</string>
+ <string name="app_ops_delete_mms">excluir suas mensagens MMS</string>
+ <string name="app_ops_delete_sms">excluir suas mensagens SMS</string>
+ <string name="app_ops_draw_on_top">desenhar janelas em primeiro plano</string>
+ <string name="app_ops_get_usage_stats">obter estatísticas de uso do aplicativo</string>
+ <string name="app_ops_keep_device_awake">manter seu dispositivo acordado</string>
+ <string name="app_ops_make_phone_call">realizar uma chamada telefônica</string>
+ <string name="app_ops_modify_calendar">atualizar seu calendário</string>
+ <string name="app_ops_modify_call_log">atualizar o registro de chamadas</string>
+ <string name="app_ops_modify_clipboard">modificar a área de transferência</string>
+ <string name="app_ops_modify_contacts">atualizar seus contatos</string>
+ <string name="app_ops_modify_settings">atualizar configurações de sistema</string>
+ <string name="app_ops_mute_unmute_microphone">ligar/desligar o microfone</string>
+ <string name="app_ops_play_audio">reproduzir áudio</string>
+ <string name="app_ops_post_notification">postar uma notificação</string>
+ <string name="app_ops_project_media">projetar multimídia</string>
+ <string name="app_ops_read_calendar">ler seu calendário</string>
+ <string name="app_ops_read_call_log">ler o registro de chamadas</string>
+ <string name="app_ops_read_clipboard">ler a área de transferência</string>
+ <string name="app_ops_read_contacts">ler seus contatos</string>
+ <string name="app_ops_read_mms">ler suas mensagens MMS</string>
+ <string name="app_ops_read_sms">ler suas mensagens SMS</string>
+ <string name="app_ops_receive_sms">receber uma mensagem SMS</string>
+ <string name="app_ops_record_audio">gravar áudio</string>
+ <string name="app_ops_send_mms">enviar uma mensagem MMS</string>
+ <string name="app_ops_send_sms">enviar uma mensagem SMS</string>
+ <string name="app_ops_start_at_bootup">iniciar na inicialização</string>
+ <string name="app_ops_toast_window">exibir mensagens flutuantes na tela</string>
+ <string name="app_ops_toggle_bluetooth">alternar Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">alternar dados de celular</string>
+ <string name="app_ops_toggle_nfc">alternar NFC</string>
+ <string name="app_ops_toggle_wifi">alternar Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">controlar volume do alarme</string>
+ <string name="app_ops_use_audio_focus">controlar o foco do áudio</string>
+ <string name="app_ops_use_bluetooth_volume">controlar o volume de Bluetooth</string>
+ <string name="app_ops_use_master_volume">controlar o volume principal</string>
+ <string name="app_ops_use_media_buttons">usar os botões de mídia</string>
+ <string name="app_ops_use_media_volume">controlar o volume de mídia</string>
+ <string name="app_ops_use_notification_volume">controlar o volume de notificação</string>
+ <string name="app_ops_use_ring_volume">controlar o volume de campainha</string>
+ <string name="app_ops_use_vibrate">controlar reposta ao toque</string>
+ <string name="app_ops_use_voice_volume">controlar o volume de chamadas de voz</string>
+ <string name="app_ops_write_mms">escrever uma mensagem MMS</string>
+ <string name="app_ops_write_sms">escrever uma mensagem SMS</string>
+ <string name="app_ops_use_fingerprint">usar a impressão digital</string>
+ <string name="app_ops_add_voicemail">adicionar uma mensagem de voz</string>
+ <string name="app_ops_read_phone_state">acessar estado do telefone</string>
+ <string name="app_ops_scan_wifi">procurar rede Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">mudar o papel de parede</string>
+ <string name="app_ops_assist_structure">usar estrutura de assistência</string>
+ <string name="app_ops_assist_screenshot">capturar a tela</string>
+ <string name="app_ops_use_body_sensors">usar sensores corporais</string>
+ <string name="app_ops_read_cell_broadcasts">ler transmissões da rede de celular</string>
+ <string name="app_ops_mock_location">simular a sua localização</string>
+ <string name="app_ops_read_external_storage">ler o armazenamento externo</string>
+ <string name="app_ops_write_external_storage">escrever no armazenamento externo</string>
+ <string name="app_ops_turn_on_screen">ligar a tela</string>
+ <string name="app_ops_get_accounts">obter as contas do dispositivo</string>
+ <string name="app_ops_wifi_change">alterar o estado do Wi-Fi</string>
+ <string name="app_ops_su">obter acesso super usuário</string>
+ <string name="lock_to_app_toast_no_navbar">Para desafixar esta tela, toque e segure o botão Voltar.</string>
+ <string name="live_display_auto">Automático</string>
+ <string name="live_display_auto_summary">Ajusta automaticamente a temperatura de cor da tela após o pôr do sol e nascer do sol</string>
+ <string name="live_display_off">Desligado</string>
+ <string name="live_display_off_summary">Desativar todos os ajustes</string>
+ <string name="live_display_day">Dia</string>
+ <string name="live_display_day_summary">Usar apenas configurações de dia</string>
+ <string name="live_display_night">Noite</string>
+ <string name="live_display_night_summary">Use apenas configurações de noite</string>
+ <string name="live_display_outdoor">Ao ar livre (sol forte)</string>
+ <string name="live_display_outdoor_summary">Usar apenas configurações de ao ar livre</string>
+ <string name="live_display_hint">LiveDisplay pode ajudar a reduzir o cansaço visual e ajudá-lo a dormir à noite. Clique aqui para experimentá-lo!</string>
+ <string name="tethered_notification_no_device_message">Nenhum dispositivo conectado</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivo conectado</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivos conectados</string>
+ <string name="notify_package_component_protected_title">Início de atividade foi bloqueado</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> está protegido de ser iniciado. Toque para autenticar e iniciar o aplicativo.</string>
+ <string name="notify_battery_fully_charged_title">Bateria totalmente carregada</string>
+ <string name="notify_battery_fully_charged_text">Desconecte seu dispositivo do carregador para aumentar a vida útil da bateria.</string>
+</resources>
diff --git a/core/res/res/values-pt-rPT/cm_strings.xml b/core/res/res/values-pt-rPT/cm_strings.xml
new file mode 100644
index 0000000..53f81eb
--- /dev/null
+++ b/core/res/res/values-pt-rPT/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Captura de ecrã</string>
+ <string name="permlab_receiveProtectedSms">receber SMS protegida</string>
+ <string name="permdesc_receiveProtectedSms">Permite que a aplicação receba uma SMS protegida.</string>
+ <string name="permlab_modifyProtectedSmsList">modificar a lista de SMS protegidas</string>
+ <string name="permdesc_modifyProtectedSmsList">Permite que a aplicação modifique a lista de endereços de SMS protegidas.</string>
+ <string name="permgrouplab_security">Segurança</string>
+ <string name="permgroupdesc_security">Permissões relacionadas com as informações de segurança do dispositivo.</string>
+ <string name="permlab_readPhoneBlacklist">Ler a lista negra do telefone</string>
+ <string name="permdesc_readPhoneBlacklist">Permite a uma aplicação ler informações sobre números de telefone que são bloqueados para chamadas ou mensagens de entrada.</string>
+ <string name="permlab_changePhoneBlacklist">Alterar a lista negra do telefone</string>
+ <string name="permdesc_changePhoneBlacklist">Permite a uma aplicação alterar os números de telefone que são bloqueados para chamadas ou mensagens de entrada.</string>
+ <string name="permlab_setKeyguardWallpaper">Definir a imagem de fundo do ecrã de bloqueio</string>
+ <string name="permdesc_setKeyguardWallpaper">Permite a uma aplicação trocar a imagem de fundo do ecrã de bloqueio.</string>
+ <string name="global_action_reboot">Reiniciar</string>
+ <string name="global_action_current_user">Atual</string>
+ <string name="reboot_reboot">Reiniciar</string>
+ <string name="reboot_recovery">Recuperação</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Reinicialização suave</string>
+ <string name="reboot_title">Reiniciar</string>
+ <string name="reboot_confirm" product="tablet">O seu tablet vai reiniciar.</string>
+ <string name="reboot_confirm" product="default">O seu telemóvel irá reiniciar.</string>
+ <string name="reboot_progress">A reiniciar\u2026</string>
+ <string name="app_killed_message">Aplicação terminada</string>
+ <string name="adb_net_active_notification_title">ADB através da rede ativado</string>
+ <string name="adb_both_active_notification_title">ABD através de USB e da rede ativado</string>
+ <string name="adb_active_generic_notification_message">Toque para desativar a depuração.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB e rede</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Rede</string>
+ <string name="permlab_interceptPackageLaunch">Intercetar a inicialização de uma aplicação</string>
+ <string name="stylus_app_not_installed">%s não está instalada</string>
+ <string name="silent_mode_priority">Prioridade</string>
+ <string name="silent_mode_none">Nenhum</string>
+ <string name="subscription_change_disabled_wifi_ap">Zona Wi-Fi portátil desligada devido à alteração da assinatura SIM</string>
+ <string name="notify_turn_wifi_off_title">Desligar Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">ativar ou desativar a Proteção da Privacidade</string>
+ <string name="permdesc_changePrivacyGuardState">Permite à aplicação escolher se outra aplicação corre com Proteção da Privacidade. Quando uma aplicação corre com Proteção da Privacidade, não terá acesso a dados pessoais como contactos, registo de chamadas ou mensagens.</string>
+ <string name="privacy_guard_notification">Proteção da Privacidade ativa</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> não poderá aceder a dados pessoais</string>
+ <string name="privacy_guard_dialog_title">Proteção da Privacidade</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="aplicação">%1$s</xliff:g> gostaria de <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Memorizar a minha escolha</string>
+ <string name="app_ops_access_camera">aceder à câmara</string>
+ <string name="app_ops_access_location">aceder à sua localização</string>
+ <string name="app_ops_access_notifications">ler as suas notificações</string>
+ <string name="app_ops_activate_vpn">ativar uma VPN</string>
+ <string name="app_ops_auto_start">iniciar no arranque</string>
+ <string name="app_ops_delete_call_log">eliminar o registo de chamadas</string>
+ <string name="app_ops_delete_contacts">eliminar os seus contactos</string>
+ <string name="app_ops_delete_mms">eliminar as suas mensagens MMS</string>
+ <string name="app_ops_delete_sms">eliminar as suas mensagens SMS</string>
+ <string name="app_ops_draw_on_top">desenhar janelas em primeiro plano</string>
+ <string name="app_ops_get_usage_stats">obter estatísticas de utilização</string>
+ <string name="app_ops_keep_device_awake">manter o seu dispositivo acordado</string>
+ <string name="app_ops_make_phone_call">fazer uma chamada telefónica</string>
+ <string name="app_ops_modify_calendar">atualizar o seu calendário</string>
+ <string name="app_ops_modify_call_log">atualização do registo de chamadas</string>
+ <string name="app_ops_modify_clipboard">modificar a área de transferência</string>
+ <string name="app_ops_modify_contacts">atualizar os seus contatos</string>
+ <string name="app_ops_modify_settings">atualizar as definições de sistema</string>
+ <string name="app_ops_mute_unmute_microphone">ligar/desligar o microfone</string>
+ <string name="app_ops_play_audio">reproduzir áudio</string>
+ <string name="app_ops_post_notification">postar uma notificação</string>
+ <string name="app_ops_project_media">projetar multimédia</string>
+ <string name="app_ops_read_calendar">ver o seu calendário</string>
+ <string name="app_ops_read_call_log">ver o registo de chamadas</string>
+ <string name="app_ops_read_clipboard">ver a área de transferência</string>
+ <string name="app_ops_read_contacts">ver os seus contactos</string>
+ <string name="app_ops_read_mms">ver as suas mensagens MMS</string>
+ <string name="app_ops_read_sms">ler as suas mensagens SMS</string>
+ <string name="app_ops_receive_sms">receber uma mensagem de SMS</string>
+ <string name="app_ops_record_audio">gravar áudio</string>
+ <string name="app_ops_send_mms">Enviar uma mensagem MMS</string>
+ <string name="app_ops_send_sms">Enviar uma mensagem SMS</string>
+ <string name="app_ops_start_at_bootup">iniciar no arranque</string>
+ <string name="app_ops_toast_window">exibir avisos no ecrã</string>
+ <string name="app_ops_toggle_bluetooth">alternar bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">alternar o estado dos dados móveis</string>
+ <string name="app_ops_toggle_nfc">alternar NFC</string>
+ <string name="app_ops_toggle_wifi">alternar Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">controlar volume do alarme</string>
+ <string name="app_ops_use_audio_focus">controlar o foco de áudio</string>
+ <string name="app_ops_use_bluetooth_volume">controlar o volume do bluetooth</string>
+ <string name="app_ops_use_master_volume">controlar o volume principal</string>
+ <string name="app_ops_use_media_buttons">usar os botões multimédia</string>
+ <string name="app_ops_use_media_volume">controlar o volume multimédia</string>
+ <string name="app_ops_use_notification_volume">controlar o volume de notificação</string>
+ <string name="app_ops_use_ring_volume">controlar o volume da campainha</string>
+ <string name="app_ops_use_vibrate">usar a reação tátil</string>
+ <string name="app_ops_use_voice_volume">controlar o volume das chamadas de voz</string>
+ <string name="app_ops_write_mms">escrever uma mensagem MMS</string>
+ <string name="app_ops_write_sms">escrever uma mensagem SMS</string>
+ <string name="app_ops_use_fingerprint">usar a impressão digital</string>
+ <string name="app_ops_add_voicemail">adicionar um correio de voz</string>
+ <string name="app_ops_read_phone_state">aceder ao estado do telefone</string>
+ <string name="app_ops_scan_wifi">procurar redes Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">mudar a imagem de fundo</string>
+ <string name="app_ops_assist_structure">usar estrutura de assistência</string>
+ <string name="app_ops_assist_screenshot">realizar uma captura de ecrã</string>
+ <string name="app_ops_use_body_sensors">usar os sensores corporais</string>
+ <string name="app_ops_read_cell_broadcasts">ler transmissões celulares</string>
+ <string name="app_ops_mock_location">simular a sua localização</string>
+ <string name="app_ops_read_external_storage">ler do armazenamento externo</string>
+ <string name="app_ops_write_external_storage">escrever no armazenamento externo</string>
+ <string name="app_ops_turn_on_screen">ligar o ecrã</string>
+ <string name="app_ops_get_accounts">obter contas do dispositivo</string>
+ <string name="app_ops_wifi_change">alterar o estado do Wi-Fi</string>
+ <string name="app_ops_su">obter acesso root</string>
+ <string name="lock_to_app_toast_no_navbar">Para soltar este ecrã, toque e segure o botão Voltar.</string>
+ <string name="live_display_auto">Automático</string>
+ <string name="live_display_auto_summary">Ajusta automaticamente a temperatura de cor do ecrã após o pôr do sol e o nascer do sol</string>
+ <string name="live_display_off">Desligado</string>
+ <string name="live_display_off_summary">Desativar todos os ajustes</string>
+ <string name="live_display_day">Dia</string>
+ <string name="live_display_day_summary">Usar apenas as definições de dia</string>
+ <string name="live_display_night">Noite</string>
+ <string name="live_display_night_summary">Usar apenas as definições de noite</string>
+ <string name="live_display_outdoor">Exterior (sol brilhante)</string>
+ <string name="live_display_outdoor_summary">Usar apenas as definições de exterior</string>
+ <string name="live_display_hint">LiveDisplay pode ajudar a reduzir a fadiga ocular e ajudar-te a dormir à noite. Clique aqui para experimentar!</string>
+ <string name="tethered_notification_no_device_message">Nenhum dispositivo conectado</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivo conectado</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> dispositivos conectados</string>
+ <string name="notify_package_component_protected_title">Início de atividades bloqueado</string>
+ <string name="notify_package_component_protected_text">A abertura de <xliff:g id="app_name">%1$s</xliff:g> está protegida. Toque para se autenticar e poder iniciar a aplicação.</string>
+ <string name="notify_battery_fully_charged_title">Bateria completamente carregada</string>
+ <string name="notify_battery_fully_charged_text">Desligue o carregador do dispositivo para aumentar a vida útil da bateria.</string>
+</resources>
diff --git a/core/res/res/values-ro/cm_strings.xml b/core/res/res/values-ro/cm_strings.xml
new file mode 100644
index 0000000..2640c3f
--- /dev/null
+++ b/core/res/res/values-ro/cm_strings.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Captură de ecran</string>
+ <string name="permlab_receiveProtectedSms">primește SMS-uri protejate</string>
+ <string name="permdesc_receiveProtectedSms">Permite aplicației să primească un SMS protejat.</string>
+ <string name="permlab_modifyProtectedSmsList">modifică lista de SMS-uri protejate</string>
+ <string name="permdesc_modifyProtectedSmsList">Permite aplicației să modifice lista adreselor SMS protejate.</string>
+ <string name="permgrouplab_security">Securitate</string>
+ <string name="permgroupdesc_security">Permisiunile legate de informațiile de securitate ale dispozitivului.</string>
+ <string name="permlab_readPhoneBlacklist">citește lista neagră a telefonului</string>
+ <string name="permdesc_readPhoneBlacklist">Permite unei aplicații să citească informații despre numerele de telefon care sunt blocate pentru primirea de apeluri sau de mesaje.</string>
+ <string name="permlab_changePhoneBlacklist">schimbă lista neagră a telefonului</string>
+ <string name="permdesc_changePhoneBlacklist">Permite unei aplicații să schimbe numere de telefon care sunt blocate pentru primirea de apeluri sau mesaje.</string>
+ <string name="permlab_setKeyguardWallpaper">setare fundal ecran de blocare</string>
+ <string name="permdesc_setKeyguardWallpaper">Permite unei aplicații să schimbe imaginea de fundal a ecranului de blocare.</string>
+ <string name="global_action_reboot">Repornire</string>
+ <string name="global_action_current_user">Actual</string>
+ <string name="reboot_reboot">Repornire</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Descărcare</string>
+ <string name="reboot_soft">Repornirea sistemului</string>
+ <string name="reboot_title">Repornire</string>
+ <string name="reboot_confirm" product="tablet">Tableta va reporni.</string>
+ <string name="reboot_confirm" product="default">Telefonul dvs. va reporni.</string>
+ <string name="reboot_progress">Repornire\u2026</string>
+ <string name="app_killed_message">Aplicație oprită</string>
+ <string name="adb_net_active_notification_title">ADB prin rețea activ</string>
+ <string name="adb_both_active_notification_title">ADB prin USB &amp; rețea activ</string>
+ <string name="adb_active_generic_notification_message">Apasă pentru dezactivarea depanării.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; rețea</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Rețea</string>
+ <string name="permlab_interceptPackageLaunch">interceptează lansarea aplicației</string>
+ <string name="stylus_app_not_installed">%s nu este instalată</string>
+ <string name="silent_mode_priority">Prioritate</string>
+ <string name="silent_mode_none">Nimic</string>
+ <string name="notify_turn_wifi_off_title">Oprește Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">activează sau dezactivează Privacy Guard</string>
+ <string name="permdesc_changePrivacyGuardState">Permite aplicației să stabilească dacă o altă aplicație rulează cu garda de confidențialitate. Când o aplicație rulează cu garda de confidențialitate, nu va avea acces la date personale, cum ar fi contacte, jurnalul de apeluri sau mesaje.</string>
+ <string name="privacy_guard_notification">Protejarea datelor activată</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> nu va putea accesa datele personale</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> dorește să <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Memorează alegerea mea</string>
+ <string name="app_ops_access_camera">accesează camera</string>
+ <string name="app_ops_access_location">accesează locația</string>
+ <string name="app_ops_access_notifications">citește notificările</string>
+ <string name="app_ops_activate_vpn">activați un VPN</string>
+ <string name="app_ops_auto_start">lansează la pornire</string>
+ <string name="app_ops_delete_call_log">șterge lista de apeluri</string>
+ <string name="app_ops_delete_contacts">șterge lista de contacte</string>
+ <string name="app_ops_delete_mms">șterge mesajele MMS</string>
+ <string name="app_ops_delete_sms">șterge mesajele SMS</string>
+ <string name="app_ops_draw_on_top">lansează ferestre deasupra</string>
+ <string name="app_ops_get_usage_stats">obține statistici de utilizare a aplicației</string>
+ <string name="app_ops_keep_device_awake">ține dispozitivul deschis</string>
+ <string name="app_ops_make_phone_call">inițiază un apel telefonic</string>
+ <string name="app_ops_modify_calendar">actualizează calendarul</string>
+ <string name="app_ops_modify_call_log">actualizează jurnalul de apeluri</string>
+ <string name="app_ops_modify_clipboard">modifică clipboard</string>
+ <string name="app_ops_modify_contacts">actualizează contacte</string>
+ <string name="app_ops_modify_settings">actualizează setări de sistem</string>
+ <string name="app_ops_mute_unmute_microphone">activează/dezactivează microfonul</string>
+ <string name="app_ops_play_audio">redă sunet</string>
+ <string name="app_ops_post_notification">trimite o notificare</string>
+ <string name="app_ops_project_media">proiect media</string>
+ <string name="app_ops_read_calendar">citește calendarul</string>
+ <string name="app_ops_read_call_log">citește jurnalul de apeluri</string>
+ <string name="app_ops_read_clipboard">citește clipboard-ul</string>
+ <string name="app_ops_read_contacts">citește contactele</string>
+ <string name="app_ops_read_mms">citește mesajele MMS</string>
+ <string name="app_ops_read_sms">citește mesajele SMS</string>
+ <string name="app_ops_receive_sms">primește un mesaj SMS</string>
+ <string name="app_ops_record_audio">înregistrare audio</string>
+ <string name="app_ops_send_mms">trimite un mesaj MMS</string>
+ <string name="app_ops_send_sms">trimite un mesaj SMS</string>
+ <string name="app_ops_start_at_bootup">începe la pornire</string>
+ <string name="app_ops_toast_window">afișează mesajele temporare</string>
+ <string name="app_ops_toggle_bluetooth">comută Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">comutare date mobile</string>
+ <string name="app_ops_toggle_nfc">Comutare NFC</string>
+ <string name="app_ops_toggle_wifi">comută Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">controlează volumul alarmei</string>
+ <string name="app_ops_use_audio_focus">controlează focalizarea audio</string>
+ <string name="app_ops_use_bluetooth_volume">controlează volumul Bluetooth</string>
+ <string name="app_ops_use_master_volume">controlează volumul master</string>
+ <string name="app_ops_use_media_buttons">folosește butoanele media</string>
+ <string name="app_ops_use_media_volume">controlează volumul media</string>
+ <string name="app_ops_use_notification_volume">controlează volumul la notificare</string>
+ <string name="app_ops_use_ring_volume">controlează volumul la sonerie</string>
+ <string name="app_ops_use_vibrate">folosește răspunsul tactil</string>
+ <string name="app_ops_use_voice_volume">controlează volumul apelului de voce</string>
+ <string name="app_ops_write_mms">scrie un mesaj MMS</string>
+ <string name="app_ops_write_sms">scrie un mesaj SMS</string>
+ <string name="app_ops_use_fingerprint">utilizează amprentă digitală</string>
+ <string name="app_ops_add_voicemail">adaugă un mesaj vocal</string>
+ <string name="app_ops_read_phone_state">citește starea telefonului</string>
+ <string name="app_ops_scan_wifi">scanează rețelele Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">schimbă imaginea de fundal</string>
+ <string name="app_ops_assist_structure">folosește structura de asistență</string>
+ <string name="app_ops_assist_screenshot">face o captură de ecran</string>
+ <string name="app_ops_use_body_sensors">utilizează senzorii corporali</string>
+ <string name="app_ops_read_cell_broadcasts">citește trasmisiunile din rețea</string>
+ <string name="app_ops_mock_location">simulează locația dvs.</string>
+ <string name="app_ops_read_external_storage">citește stocare externă</string>
+ <string name="app_ops_write_external_storage">scrie stocare externă</string>
+ <string name="app_ops_turn_on_screen">pornește ecranul</string>
+ <string name="app_ops_get_accounts">obține conturile dispozitivului</string>
+ <string name="app_ops_wifi_change">schimbă starea Wi-Fi</string>
+ <string name="app_ops_su">obțină acces root</string>
+ <string name="lock_to_app_toast_no_navbar">Pentru a anula fixarea acestui ecran, atingeți și țineți apăsat butonul Înapoi.</string>
+ <string name="live_display_auto">Automat</string>
+ <string name="live_display_auto_summary">Reglează automat temperatura de culoare de pe ecran după apus și răsărit</string>
+ <string name="live_display_off">Oprit</string>
+ <string name="live_display_off_summary">Dezactivează toate ajustările</string>
+ <string name="live_display_day">Zi</string>
+ <string name="live_display_day_summary">Utilizați numai setările de zi</string>
+ <string name="live_display_night">Noapte</string>
+ <string name="live_display_night_summary">Utilizați numai setările de noapte</string>
+ <string name="live_display_outdoor">În aer liber (soare strălucitor)</string>
+ <string name="live_display_outdoor_summary">Utilizați numai setările în aer liber</string>
+ <string name="live_display_hint">LiveDisplay poate reduce oboseala ochilor și vă poate ajuta să dormiți noaptea. Apăsați aici pentru a-l încerca!</string>
+ <string name="tethered_notification_no_device_message">Niciun dispozitiv conectat</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> dispozitiv conectat</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s </xliff:g> dispozitive conectate</string>
+ <string name="notify_package_component_protected_title">Lansarea activității blocată</string>
+ <string name="notify_battery_fully_charged_title">Acumulator încărcat complet</string>
+ <string name="notify_battery_fully_charged_text">Deconectați aparatul de la încărcător pentru a îmbunătăți longevitatea bateriei.</string>
+</resources>
diff --git a/core/res/res/values-ru/cm_strings.xml b/core/res/res/values-ru/cm_strings.xml
new file mode 100644
index 0000000..34278d0
--- /dev/null
+++ b/core/res/res/values-ru/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Скриншот</string>
+ <string name="permlab_receiveProtectedSms">Получение защищённых SMS</string>
+ <string name="permdesc_receiveProtectedSms">Приложение сможет получать входящие защищённые SMS-сообщения.</string>
+ <string name="permlab_modifyProtectedSmsList">Изменение списка защищённых SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Приложение сможет изменять список адресатов защищённых SMS-сообщений.</string>
+ <string name="permgrouplab_security">Безопасность</string>
+ <string name="permgroupdesc_security">Разрешения, относящиеся к безопасности данных на устройстве.</string>
+ <string name="permlab_readPhoneBlacklist">Просмотр чёрного списка</string>
+ <string name="permdesc_readPhoneBlacklist">Приложение сможет считывать информацию о списке абонентов, от которых заблокированы входящие звонки или сообщения.</string>
+ <string name="permlab_changePhoneBlacklist">Изменение чёрного списка</string>
+ <string name="permdesc_changePhoneBlacklist">Приложение сможет изменять список абонентов, от которых заблокированы входящие звонки или сообщения.</string>
+ <string name="permlab_setKeyguardWallpaper">Установка обоев экрана блокировки</string>
+ <string name="permdesc_setKeyguardWallpaper">Приложение сможет изменять обои экрана блокировки устройства.</string>
+ <string name="global_action_reboot">Перезагрузить</string>
+ <string name="global_action_current_user">Текущий</string>
+ <string name="reboot_reboot">Перезагрузка</string>
+ <string name="reboot_recovery">Режим восстановления</string>
+ <string name="reboot_bootloader">Загрузчик</string>
+ <string name="reboot_download">Режим обновления ПО</string>
+ <string name="reboot_soft">Перезапуск интерфейса</string>
+ <string name="reboot_title">Перезагрузка</string>
+ <string name="reboot_confirm" product="tablet">Ваш планшет будет перезагружен.</string>
+ <string name="reboot_confirm" product="default">Ваш телефон будет перезагружен.</string>
+ <string name="reboot_progress">Перезагрузка\u2026</string>
+ <string name="app_killed_message">Приложение закрыто</string>
+ <string name="adb_net_active_notification_title">Отладка по сети разрешена</string>
+ <string name="adb_both_active_notification_title">Отладка по сети и USB разрешена</string>
+ <string name="adb_active_generic_notification_message">Нажмите, чтобы отключить отладку.</string>
+ <string name="adb_active_custom_tile">Отладка <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">по сети и USB</string>
+ <string name="adb_active_custom_tile_usb">по USB</string>
+ <string name="adb_active_custom_tile_net">по сети</string>
+ <string name="permlab_interceptPackageLaunch">Перехват запуска приложений</string>
+ <string name="stylus_app_not_installed">«%s» не установлено</string>
+ <string name="silent_mode_priority">Важные</string>
+ <string name="silent_mode_none">Нет</string>
+ <string name="subscription_change_disabled_wifi_ap">Точка доступа Wi-Fi отключена из-за переключения SIM-карты</string>
+ <string name="notify_turn_wifi_off_title">Выключить Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">Включение или выключение защищённого режима</string>
+ <string name="permdesc_changePrivacyGuardState">Приложение сможет изменять состояние защищённого режима для других приложений. Когда приложение запущено в защищённом режиме, оно не получает доступ к персональным данным, таким как контакты, сообщения или журнал звонков.</string>
+ <string name="privacy_guard_notification">Защищённый режим включён</string>
+ <string name="privacy_guard_notification_detail">У «<xliff:g id="app">%1$s</xliff:g>» нет доступа к персональным данным</string>
+ <string name="privacy_guard_dialog_title">Защищённый режим</string>
+ <string name="privacy_guard_dialog_summary">Приложение «<xliff:g id="app">%1$s</xliff:g>» пытается <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Запомнить разрешение</string>
+ <string name="app_ops_access_camera">получить доступ к камере</string>
+ <string name="app_ops_access_location">получить доступ к местоположению устройства</string>
+ <string name="app_ops_access_notifications">получить доступ к уведомлениям</string>
+ <string name="app_ops_activate_vpn">активировать VPN</string>
+ <string name="app_ops_auto_start">назначить запуск при включении устройства</string>
+ <string name="app_ops_delete_call_log">удалить журнал звонков</string>
+ <string name="app_ops_delete_contacts">удалить контакты</string>
+ <string name="app_ops_delete_mms">удалить MMS-сообщения</string>
+ <string name="app_ops_delete_sms">удалить SMS-сообщения</string>
+ <string name="app_ops_draw_on_top">отображать элементы интерфейса поверх других окон</string>
+ <string name="app_ops_get_usage_stats">получать статистику использования приложений</string>
+ <string name="app_ops_keep_device_awake">запретить устройству переход в спящий режим</string>
+ <string name="app_ops_make_phone_call">выполнить телефонный звонок</string>
+ <string name="app_ops_modify_calendar">изменить данные календаря</string>
+ <string name="app_ops_modify_call_log">изменить данные журнала звонков</string>
+ <string name="app_ops_modify_clipboard">изменить содержимое буфера обмена</string>
+ <string name="app_ops_modify_contacts">изменить данные контактов</string>
+ <string name="app_ops_modify_settings">изменить системные параметры</string>
+ <string name="app_ops_mute_unmute_microphone">выключить или включить микрофон</string>
+ <string name="app_ops_play_audio">воспроизведение аудио</string>
+ <string name="app_ops_post_notification">вывести уведомление</string>
+ <string name="app_ops_project_media">выполнить трансляцию контента</string>
+ <string name="app_ops_read_calendar">считать данные календаря</string>
+ <string name="app_ops_read_call_log">считать данные списка вызовов</string>
+ <string name="app_ops_read_clipboard">считать содержимое буфера обмена</string>
+ <string name="app_ops_read_contacts">считать данные контактов</string>
+ <string name="app_ops_read_mms">считать MMS-сообщения</string>
+ <string name="app_ops_read_sms">считать SMS-сообщения</string>
+ <string name="app_ops_receive_sms">получить SMS-сообщение</string>
+ <string name="app_ops_record_audio">записать аудио</string>
+ <string name="app_ops_send_mms">отправить MMS-сообщение</string>
+ <string name="app_ops_send_sms">отправить SMS-сообщение</string>
+ <string name="app_ops_start_at_bootup">назначить запуск при включении устройства</string>
+ <string name="app_ops_toast_window">отображать всплывающие уведомления</string>
+ <string name="app_ops_toggle_bluetooth">переключить состояние Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">переключить состояние мобильного интернета</string>
+ <string name="app_ops_toggle_nfc">переключить состояние модуля NFC</string>
+ <string name="app_ops_toggle_wifi">включить или выключить Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">получить управление громкостью будильника</string>
+ <string name="app_ops_use_audio_focus">получить управление аудиофокусом</string>
+ <string name="app_ops_use_bluetooth_volume">получить управление громкостью Bluetooth-устройств</string>
+ <string name="app_ops_use_master_volume">получить управление общей громкостью</string>
+ <string name="app_ops_use_media_buttons">использовать кнопки мультимедиа</string>
+ <string name="app_ops_use_media_volume">получить управление громкостью мультимедиа</string>
+ <string name="app_ops_use_notification_volume">получить управление громкостью уведомлений</string>
+ <string name="app_ops_use_ring_volume">получить управление громкостью звонка</string>
+ <string name="app_ops_use_vibrate">использовать виброотклик</string>
+ <string name="app_ops_use_voice_volume">получить управление громкостью при разговоре</string>
+ <string name="app_ops_write_mms">создать MMS-сообщение</string>
+ <string name="app_ops_write_sms">создать SMS-сообщение</string>
+ <string name="app_ops_use_fingerprint">использовать сканер отпечатков пальцев</string>
+ <string name="app_ops_add_voicemail">добавить сообщение голосовой почты</string>
+ <string name="app_ops_read_phone_state">получить данные о состоянии телефона</string>
+ <string name="app_ops_scan_wifi">выполнить сканирование сетей Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">изменить обои</string>
+ <string name="app_ops_assist_structure">использовать структуру ассистента</string>
+ <string name="app_ops_assist_screenshot">сделать скриншот</string>
+ <string name="app_ops_use_body_sensors">использовать нательные датчики</string>
+ <string name="app_ops_read_cell_broadcasts">прочитать сообщения оповещения населения</string>
+ <string name="app_ops_mock_location">предоставить фиктивные сведения о местоположении</string>
+ <string name="app_ops_read_external_storage">прочитать данные с внешнего запоминающего устройства</string>
+ <string name="app_ops_write_external_storage">записать данные на внешнее запоминающее устройство</string>
+ <string name="app_ops_turn_on_screen">включить экран</string>
+ <string name="app_ops_get_accounts">получить информацию об аккаунтах</string>
+ <string name="app_ops_wifi_change">изменить состояние Wi-Fi</string>
+ <string name="app_ops_su">получить права суперпользователя</string>
+ <string name="lock_to_app_toast_no_navbar">Чтобы открепить экран, нажмите и удерживайте кнопку «Назад».</string>
+ <string name="live_display_auto">Автоматически</string>
+ <string name="live_display_auto_summary">Автоматическая подстройка цветовой температуры экрана после заката и восхода солнца</string>
+ <string name="live_display_off">Отключить</string>
+ <string name="live_display_off_summary">Отключить автоподстройку</string>
+ <string name="live_display_day">День</string>
+ <string name="live_display_day_summary">Только дневные настройки</string>
+ <string name="live_display_night">Ночь</string>
+ <string name="live_display_night_summary">Только ночные настройки</string>
+ <string name="live_display_outdoor">На улице (яркое солнце)</string>
+ <string name="live_display_outdoor_summary">Только уличный режим</string>
+ <string name="live_display_hint">LiveDisplay поможет снизить зрительное напряжение и улучшить сон. Нажмите здесь, чтобы попробовать!</string>
+ <string name="tethered_notification_no_device_message">Нет подключенных устройств</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> подключенное устройство</string>
+ <string name="tethered_notification_multi_device_message">Подключено устройств: <xliff:g id="count">%1$s</xliff:g></string>
+ <string name="notify_package_component_protected_title">Запуск приложения запрещён</string>
+ <string name="notify_package_component_protected_text">Приложение «<xliff:g id="app_name">%1$s</xliff:g>» заблокировано. Нажмите, чтобы ввести пароль и запустить приложение.</string>
+ <string name="notify_battery_fully_charged_title">Аккумулятор полностью заряжен</string>
+ <string name="notify_battery_fully_charged_text">Отключите устройство от сети для продления срока службы батареи.</string>
+</resources>
diff --git a/core/res/res/values-si-rLK/cm_strings.xml b/core/res/res/values-si-rLK/cm_strings.xml
new file mode 100644
index 0000000..a7a97b7
--- /dev/null
+++ b/core/res/res/values-si-rLK/cm_strings.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">තිර සේයාව</string>
+ <string name="permlab_receiveProtectedSms">ආරක්‍ෂිත SMS ලබන්න</string>
+ <string name="permdesc_receiveProtectedSms">එන ආරක්‍ෂිත SMS ලැබීමට යෙදුමට ඉඩ දෙයි.</string>
+ <string name="permlab_modifyProtectedSmsList">ආරක්‍ෂිත SMS ලැයිස්තුව විකරණය කරන්න</string>
+ <string name="permgrouplab_security">ආරක්ෂාව</string>
+ <string name="permgroupdesc_security">උපාංගයේ ආරක්ෂක තොරතුරු වලට අදාළ අනුමැති.</string>
+ <string name="permlab_readPhoneBlacklist">දුරකථන අපලේඛණය කියවීම</string>
+ <string name="permdesc_readPhoneBlacklist">පැමිණෙන ඇමතුම් හෝ පණිවිඩ සඳහා අවහිර කර ඇති ඇමතුම් අංක පිලිබඳ තොරතුරු කියවීම සඳහා යෙදුමකට අවසර දෙන්න.</string>
+ <string name="permlab_changePhoneBlacklist">දුරකථන අපලේඛණය වෙනස් කරන්න</string>
+ <string name="permdesc_changePhoneBlacklist">පැමිණෙන ඇමතුම් හෝ පණිවිඩ සඳහා අවහිර කර ඇති ඇමතුම් අංක වෙනස් කිරීම සඳහා යෙදුමකට අවසර දෙන්න.</string>
+ <string name="permlab_setKeyguardWallpaper">යතුරු රැක්මේ වෝල්පේපරය සකසන්න</string>
+ <string name="permdesc_setKeyguardWallpaper">අගුළු තිරයේ වෝල්පේපරය වෙනස්කිරීම සඳහා යෙදුමකට අවසර දෙන්න.</string>
+ <string name="global_action_reboot">යළි පණගන්වන්න</string>
+ <string name="reboot_reboot">නැවත පනගන්වන්න</string>
+ <string name="reboot_recovery">ප්‍රතිසාධන ප්‍රකාරයට</string>
+ <string name="reboot_bootloader">ඇරඹුම් ප්‍රවේශකයට</string>
+ <string name="reboot_download">බාගැනීමේ ප්‍රකාරයට</string>
+ <string name="reboot_soft">මෘදුව නැවත පනගන්වන්න</string>
+ <string name="reboot_confirm" product="tablet">ඔබගේ ටැබ්ලටය නැවත පනගැන්වෙනු ඇත.</string>
+ <string name="reboot_confirm" product="default">ඔබගේ දුරකථනය නැවත පනගැන්වෙනු ඇත.</string>
+ <string name="reboot_progress">නැවත පනගැන්වෙමින්\u2026</string>
+ <string name="adb_net_active_notification_title">ජාලය හරහා ADB සබලයි</string>
+ <string name="adb_both_active_notification_title">ජාලය &amp; USB හරහා ADB සබලයි</string>
+ <string name="adb_active_generic_notification_message">නිදොස් කරණය අබල කිරීමට ස්පර්ශ කරන්න.</string>
+ <string name="permlab_changePrivacyGuardState">පෞද්ගලිකත්වයේ මුරකරු සබලනය හෝ අබලනය</string>
+ <string name="permdesc_changePrivacyGuardState">තවත් යෙදුමක් පෞද්ගලිකත්වයේ මුරකරු සමග ධාවනය විය යුතුද නැද්ද යන්න වෙනස් කිරීම සඳහා යෙදුමට අවසර දෙන්න. යෙදුමක් පෞද්ගලිකත්වයේ මුරකරු සමග ධාවනය වන විට, එයට සම්බන්ධතා, ඇමතුම් ලොග හෝ පණිවිඩ පරිශීලනය කල නොහැක.</string>
+ <string name="privacy_guard_notification">පෞද්ගලිකත්වයේ මුරකරු සක්‍රීයයි</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g>ට පුද්ගලික දත්ත පරිශීලනය කල නොහැක</string>
+ <string name="privacy_guard_dialog_title">පෞද්ගලිකත්වයේ මුරකරු</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="op">%2$s</xliff:g> සඳහා <xliff:g id="app">%1$s</xliff:g>ට අවශ්‍යව ඇත.</string>
+ <string name="app_ops_access_camera">කැමරාව පරිශීලනය</string>
+ <string name="app_ops_access_location">ඔබගේ ස්ථානය පරිශීලනය</string>
+ <string name="app_ops_access_notifications">ඔබගේ දැනුම්දීම් කියවීම</string>
+ <string name="app_ops_keep_device_awake">ඔබගේ උපාංගය අවදිව තබාගැනීම</string>
+ <string name="app_ops_make_phone_call">දුරකථන ඇමතුමක් ලබාගැනීම</string>
+ <string name="app_ops_modify_calendar">ඔබගේ දින දර්ශකය නවීකරණය</string>
+ <string name="app_ops_modify_call_log">ඇමතුම් ලොගය නවීකරණය</string>
+ <string name="app_ops_modify_clipboard">පසුරු පුවරුව වෙනස්කිරීම</string>
+ <string name="app_ops_modify_contacts">ඔබගේ සම්බන්ධතා නවීකරණය</string>
+ <string name="app_ops_modify_settings">පද්ධති සැකසීම් නවීකරණය</string>
+ <string name="app_ops_play_audio">ශ්‍රව්‍ය ධාවනය</string>
+ <string name="app_ops_post_notification">දැනුම්දීමක් පල කිරීම</string>
+ <string name="app_ops_read_calendar">ඔබගේ දින දර්ශකය කියවීම</string>
+ <string name="app_ops_read_call_log">ඇමතුම් ලොගය කියවීම</string>
+ <string name="app_ops_read_clipboard">පසුරු පුවරුව කියවීම</string>
+ <string name="app_ops_read_contacts">ඔබගේ සම්බන්ධතා කියවීම</string>
+ <string name="app_ops_read_mms">ඔබගේ MMS පනිවිඩ කියවීම</string>
+ <string name="app_ops_read_sms">ඔබගේ කෙටි පනිවිඩ කියවීම</string>
+ <string name="app_ops_receive_sms">කෙටි පනිවිඩයක් බාර ගැනීම</string>
+ <string name="app_ops_record_audio">ශ්‍රව්‍ය රෙකෝඩනය</string>
+ <string name="app_ops_send_mms">MMS පනිවිඩයක් යැවීම</string>
+ <string name="app_ops_send_sms">කෙටි පනිවිඩයක් යැවීම</string>
+ <string name="app_ops_start_at_bootup">පණගැන්වීමේදී ධාවනය</string>
+ <string name="app_ops_toggle_bluetooth">බ්ලූටූත් ටොගලනය</string>
+ <string name="app_ops_toggle_nfc">NFC ටොගලනය</string>
+ <string name="app_ops_use_alarm_volume">ඇඟවීම් හඬ පරිමා පාලනය</string>
+ <string name="app_ops_use_audio_focus">ශ්‍රව්‍ය කේන්ද්‍රනය පාලනය</string>
+ <string name="app_ops_use_bluetooth_volume">බ්ලූටූත් හඬ පරිමා පාලනය</string>
+ <string name="app_ops_use_master_volume">ප්‍රධාන හඬ පරිමා පාලනය</string>
+ <string name="app_ops_use_media_buttons">මාධ්‍ය බොත්තම් භාවිතය</string>
+ <string name="app_ops_use_media_volume">මාධ්‍ය හඬ පරිමා පාලනය</string>
+ <string name="app_ops_use_notification_volume">දැනුම්දීම් හඬ පරිමා පාලනය</string>
+ <string name="app_ops_use_ring_volume">රින්ග්ටෝනයේ ශබ්දය පාලනය</string>
+ <string name="app_ops_use_vibrate">ස්පර්ශක කම්පන ප්‍රතිචාර භාවිතය</string>
+ <string name="app_ops_use_voice_volume">හඬ ඇමතුම් ශබ්දය පාලනය</string>
+ <string name="app_ops_write_mms">MMS පණිවිඩයක් ලිවීම</string>
+ <string name="app_ops_write_sms">කෙටි පණිවිඩයක් ලිවීම</string>
+</resources>
diff --git a/core/res/res/values-sk/cm_strings.xml b/core/res/res/values-sk/cm_strings.xml
new file mode 100644
index 0000000..62cef0c
--- /dev/null
+++ b/core/res/res/values-sk/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Snímka obrazovky</string>
+ <string name="permlab_receiveProtectedSms">prijímať chránené SMS</string>
+ <string name="permdesc_receiveProtectedSms">Umožňuje aplikácii prijímať chránené prichádzajúce SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">upraviť zoznam chránených SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Umožňuje aplikácii upraviť zoznam chránených SMS adries.</string>
+ <string name="permgrouplab_security">Zabezpečenie</string>
+ <string name="permgroupdesc_security">Povolenia súvisiace s informáciami o bezpečnosti zariadenia.</string>
+ <string name="permlab_readPhoneBlacklist">čítať čiernu listinu telefónu</string>
+ <string name="permdesc_readPhoneBlacklist">Umožňuje aplikácii čítať informácie o telefónnych číslach, ktoré sú pre prichádzajúce hovory a správy zablokované.</string>
+ <string name="permlab_changePhoneBlacklist">zmeniť čiernu listinu telefónu</string>
+ <string name="permdesc_changePhoneBlacklist">Umožňuje aplikácii zmeniť telefónne čísla, ktoré sú pre prichádzajúce hovory a správy zablokované.</string>
+ <string name="permlab_setKeyguardWallpaper">nastaviť tapetu obrazovky uzamknutia</string>
+ <string name="permdesc_setKeyguardWallpaper">Umožňuje aplikácii zmeniť tapetu obrazovky uzamknutia.</string>
+ <string name="global_action_reboot">Reštartovať</string>
+ <string name="global_action_current_user">Aktuálny</string>
+ <string name="reboot_reboot">Reštartovať</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Softvérový reštart</string>
+ <string name="reboot_title">Reštartovať</string>
+ <string name="reboot_confirm" product="tablet">Váš tablet bude reštartovaný.</string>
+ <string name="reboot_confirm" product="default">Váš telefón bude reštartovaný.</string>
+ <string name="reboot_progress">Reštartuje sa\u2026</string>
+ <string name="app_killed_message">Aplikácia bola ukončená</string>
+ <string name="adb_net_active_notification_title">ADB cez sieť povolené</string>
+ <string name="adb_both_active_notification_title">ADB cez USB a sieť povolené</string>
+ <string name="adb_active_generic_notification_message">Dotykom zakážate ladenie.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB a sieť</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Sieť</string>
+ <string name="permlab_interceptPackageLaunch">zachytiť spustenie aplikácie</string>
+ <string name="stylus_app_not_installed">Aplikácia %s nie je nainštalovaná</string>
+ <string name="silent_mode_priority">Priorita</string>
+ <string name="silent_mode_none">Žiadna</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi-Fi hotspot bol zakázaný kvôli prepnutiu karty SIM</string>
+ <string name="notify_turn_wifi_off_title">Vypnúť Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">povoliť alebo zakázať Ochranu súkromia</string>
+ <string name="permdesc_changePrivacyGuardState">Umožňuje aplikácii určiť, či má byť iná aplikácia spustená s Ochranou súkromia. Keď je aplikácia spustená s Ochranou súkromia, nemá umožnený prístup k osobným údajom ako sú kontakty, denníky hovorov, alebo správy.</string>
+ <string name="privacy_guard_notification">Aktívna ochrana súkromia</string>
+ <string name="privacy_guard_notification_detail">Aplikácii <xliff:g id="app">%1$s</xliff:g> nebude umožnený prístup k osobným údajom</string>
+ <string name="privacy_guard_dialog_title">Ochrana súkromia</string>
+ <string name="privacy_guard_dialog_summary">Aplikácia <xliff:g id="app">%1$s</xliff:g> sa pokúša <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Zapamätať voľbu</string>
+ <string name="app_ops_access_camera">prístup k fotoparátu</string>
+ <string name="app_ops_access_location">prístup k polohe</string>
+ <string name="app_ops_access_notifications">čítať oznámenia</string>
+ <string name="app_ops_activate_vpn">aktivovať VPN</string>
+ <string name="app_ops_auto_start">spustiť pri štarte</string>
+ <string name="app_ops_delete_call_log">vymazať denník hovorov</string>
+ <string name="app_ops_delete_contacts">vymazať kontakty</string>
+ <string name="app_ops_delete_mms">vymazať MMS správy</string>
+ <string name="app_ops_delete_sms">vymazať SMS správy</string>
+ <string name="app_ops_draw_on_top">vykresliť okná navrchu</string>
+ <string name="app_ops_get_usage_stats">získať štatistiky používania aplikácií</string>
+ <string name="app_ops_keep_device_awake">ponechať zariadenie prebudené</string>
+ <string name="app_ops_make_phone_call">uskutočniť telefonický hovor</string>
+ <string name="app_ops_modify_calendar">aktualizovať kalendár</string>
+ <string name="app_ops_modify_call_log">aktualizovať denník hovorov</string>
+ <string name="app_ops_modify_clipboard">upraviť schránku</string>
+ <string name="app_ops_modify_contacts">aktualizovať kontakty</string>
+ <string name="app_ops_modify_settings">aktualizovať systémové nastavenia</string>
+ <string name="app_ops_mute_unmute_microphone">stlmiť/zrušiť stlmenie mikrofónu</string>
+ <string name="app_ops_play_audio">prehrať zvuk</string>
+ <string name="app_ops_post_notification">odoslať oznámenie</string>
+ <string name="app_ops_project_media">premietať médiá</string>
+ <string name="app_ops_read_calendar">čítať údaje z kalendára</string>
+ <string name="app_ops_read_call_log">čítať údaje z denníka hovorov</string>
+ <string name="app_ops_read_clipboard">čítať údaje zo schránky</string>
+ <string name="app_ops_read_contacts">čítať kontakty</string>
+ <string name="app_ops_read_mms">čítať správy MMS</string>
+ <string name="app_ops_read_sms">čítať správy SMS</string>
+ <string name="app_ops_receive_sms">prijímať správy SMS</string>
+ <string name="app_ops_record_audio">nahrať zvuk</string>
+ <string name="app_ops_send_mms">odoslať správu MMS</string>
+ <string name="app_ops_send_sms">odoslať správu SMS</string>
+ <string name="app_ops_start_at_bootup">spustiť pri štaťte</string>
+ <string name="app_ops_toast_window">zobraziť vyskakovacie oznámenia</string>
+ <string name="app_ops_toggle_bluetooth">prepnúť bluetooth</string>
+ <string name="app_ops_toggle_nfc">prepnúť NFC</string>
+ <string name="app_ops_use_alarm_volume">ovládať hlasitosť budíka</string>
+ <string name="app_ops_use_audio_focus">ovládať zvukové zdroje</string>
+ <string name="app_ops_use_bluetooth_volume">ovládať hlasitosť bluetooh</string>
+ <string name="app_ops_use_master_volume">ovládať hlavnú hlasitosť</string>
+ <string name="app_ops_use_media_buttons">používať tlačidlá médií</string>
+ <string name="app_ops_use_media_volume">ovládať hlasitosť médií</string>
+ <string name="app_ops_use_notification_volume">ovládať hlasitosť oznámení</string>
+ <string name="app_ops_use_ring_volume">ovládať hlasitosť zvonenia</string>
+ <string name="app_ops_use_vibrate">používať dotykovú odozvu</string>
+ <string name="app_ops_use_voice_volume">ovládať hlasitosť hovoru</string>
+ <string name="app_ops_write_mms">napísať správu MMS</string>
+ <string name="app_ops_write_sms">napísať správu SMS</string>
+ <string name="app_ops_su">získať root prístup</string>
+ <string name="lock_to_app_toast_no_navbar">Na odopnutie tejto obrazovky stlačte a podržte tlačidlo Späť.</string>
+ <string name="live_display_auto">Automatické</string>
+ <string name="live_display_auto_summary">Automaticky upraviť teplotu farieb obrazovky po západe a východe slnka</string>
+ <string name="live_display_off">Vypnuté</string>
+ <string name="live_display_off_summary">Zakázať všetky úpravy</string>
+ <string name="live_display_day">Deň</string>
+ <string name="live_display_day_summary">Použiť len nastavenia pre deň</string>
+ <string name="live_display_night">Noc</string>
+ <string name="live_display_night_summary">Použiť len nastavenia pre noc</string>
+ <string name="live_display_outdoor">Vonku (jasné slnko)</string>
+ <string name="live_display_outdoor_summary">Používať len nastavenia pre vonkajšie prostredie</string>
+ <string name="live_display_hint">LiveDisplay môže pomôcť znížiť únavu očí a pomôže vám spať v noci. Kliknite sem a vyskúšajte túto funkciu!</string>
+ <string name="tethered_notification_no_device_message">Žiadne pripojené zariadenie</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> pripojené zariadenie</string>
+ <string name="tethered_notification_multi_device_message">Pripojené zariadenia: <xliff:g id="count">%1$s</xliff:g></string>
+</resources>
diff --git a/core/res/res/values-sl/cm_strings.xml b/core/res/res/values-sl/cm_strings.xml
new file mode 100644
index 0000000..6a1c843
--- /dev/null
+++ b/core/res/res/values-sl/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Zaslonska slika</string>
+ <string name="permlab_receiveProtectedSms">prejemanje zaščitenih SMS-ov</string>
+ <string name="permdesc_receiveProtectedSms">Dovoli aplikaciji prejemanje zaščitenih dohodnih SMS-ov.</string>
+ <string name="permlab_modifyProtectedSmsList">spreminjanje seznama zaščitenih SMS-ov</string>
+ <string name="permdesc_modifyProtectedSmsList">Dovoli aplikaciji spreminjanje seznama naslovov zaščitenih SMS-ov.</string>
+ <string name="permgrouplab_security">Varnost</string>
+ <string name="permgroupdesc_security">Dovoljenja, ki so povezana z varnostnimi podatki naprave.</string>
+ <string name="permlab_readPhoneBlacklist">branje črnega seznama telefona</string>
+ <string name="permdesc_readPhoneBlacklist">Dovoli aplikaciji branje podatkov o blokiranih telefonskih številkah za dohodne klice in sporočila.</string>
+ <string name="permlab_changePhoneBlacklist">spreminjanje črnega seznama telefona</string>
+ <string name="permdesc_changePhoneBlacklist">Dovoli aplikaciji spreminjanje blokiranih telefonskih številk za dohodne klice in sporočila.</string>
+ <string name="permlab_setKeyguardWallpaper">nastavitev slike ozadja keyguard</string>
+ <string name="permdesc_setKeyguardWallpaper">Dovoli aplikaciji spreminjanje slike ozadja zaslona za zaklepanje.</string>
+ <string name="global_action_reboot">Ponovno zaženi</string>
+ <string name="global_action_current_user">Trenutni</string>
+ <string name="reboot_reboot">Ponovno zaženi</string>
+ <string name="reboot_recovery">Obnovitev</string>
+ <string name="reboot_bootloader">Zagonski nalagalnik</string>
+ <string name="reboot_download">Prenos</string>
+ <string name="reboot_soft">Mehki ponovni zagon</string>
+ <string name="reboot_title">Ponovno zaženi</string>
+ <string name="reboot_confirm" product="tablet">Tablica se bo ponovno zagnala.</string>
+ <string name="reboot_confirm" product="default">Telefon se bo ponovno zagnal.</string>
+ <string name="reboot_progress">Ponovno zaganjanje \u2026</string>
+ <string name="app_killed_message">Aplikacija uničena</string>
+ <string name="adb_net_active_notification_title">ADB preko omrežja omogočen</string>
+ <string name="adb_both_active_notification_title">ADB preko USB-ja in omrežja omogočen</string>
+ <string name="adb_active_generic_notification_message">Dotaknite se, da onemogočite razhroščevanje.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB in omrežje</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Omrežje</string>
+ <string name="permlab_interceptPackageLaunch">prestrezanje zagona aplikacije</string>
+ <string name="stylus_app_not_installed">%s ni nameščen</string>
+ <string name="silent_mode_priority">Prednost</string>
+ <string name="silent_mode_none">Brez</string>
+ <string name="subscription_change_disabled_wifi_ap">Dostopna točka Wi-Fi je bila onemogočena zaradi spremembe naročnine SIM</string>
+ <string name="notify_turn_wifi_off_title">Izklopi Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">omogočanje ali onemogočanje Privacy Guarda</string>
+ <string name="permdesc_changePrivacyGuardState">Dovoli aplikaciji spreminjanje, ali se druga aplikacija izvaja s Privacy Guardom. Kadar se aplikacija izvaja s Privacy Guardom, ne bo imela dostopa do osebnih podatkov, kot so stiki, dnevniki klicev ali sporočila.</string>
+ <string name="privacy_guard_notification">Privacy Guard dejaven</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> ne bo imel dostopa do osebnih podatkov</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> bi rad <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Zapomni si mojo izbiro</string>
+ <string name="app_ops_access_camera">dostop do fotoaparata</string>
+ <string name="app_ops_access_location">dostop do lokacije</string>
+ <string name="app_ops_access_notifications">branje obvestil</string>
+ <string name="app_ops_activate_vpn">omogočanje VPN-a</string>
+ <string name="app_ops_auto_start">zagon ob vklopu</string>
+ <string name="app_ops_delete_call_log">brisanje vašega dnevnika klicev</string>
+ <string name="app_ops_delete_contacts">brisanje vaših stikov</string>
+ <string name="app_ops_delete_mms">brisanje vaših sporočil MMS</string>
+ <string name="app_ops_delete_sms">brisanje vaših sporočil SMS</string>
+ <string name="app_ops_draw_on_top">risanje oken v ospredju</string>
+ <string name="app_ops_get_usage_stats">pridobivanje uporabniške statistike aplikacije</string>
+ <string name="app_ops_keep_device_awake">ohranjanje budnosti naprave</string>
+ <string name="app_ops_make_phone_call">opravljanje klicev</string>
+ <string name="app_ops_modify_calendar">posodabljanje koledarja</string>
+ <string name="app_ops_modify_call_log">posodabljanje dnevnika klicev</string>
+ <string name="app_ops_modify_clipboard">spreminjanje odložišča</string>
+ <string name="app_ops_modify_contacts">posodabljanje vaših stikov</string>
+ <string name="app_ops_modify_settings">posodabljanje sistemskih nastavitev</string>
+ <string name="app_ops_mute_unmute_microphone">utišanje/vklop mikrofona</string>
+ <string name="app_ops_play_audio">predvajanje zvoka</string>
+ <string name="app_ops_post_notification">prikaz obvestil</string>
+ <string name="app_ops_project_media">načrtovanje predstavnosti</string>
+ <string name="app_ops_read_calendar">branje koledarja</string>
+ <string name="app_ops_read_call_log">branje dnevnika klicev</string>
+ <string name="app_ops_read_clipboard">branje odložišča</string>
+ <string name="app_ops_read_contacts">branje vaših stikov</string>
+ <string name="app_ops_read_mms">branje vaših sporočil MMS</string>
+ <string name="app_ops_read_sms">branje vaših sporočil SMS</string>
+ <string name="app_ops_receive_sms">prejemanje sporočil SMS</string>
+ <string name="app_ops_record_audio">snemanje zvoka</string>
+ <string name="app_ops_send_mms">pošiljanje sporočil MMS</string>
+ <string name="app_ops_send_sms">pošiljanje sporočil SMS</string>
+ <string name="app_ops_start_at_bootup">zagon ob vklopu</string>
+ <string name="app_ops_toast_window">prikazovanje pojavnih obvestil</string>
+ <string name="app_ops_toggle_bluetooth">preklapljanje Bluetootha</string>
+ <string name="app_ops_toggle_mobile_data">preklapljanje mobilnih podatkov</string>
+ <string name="app_ops_toggle_nfc">preklapljanje NFC-ja</string>
+ <string name="app_ops_toggle_wifi">preklapljanje omr. Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">nadzor glasnosti budilke</string>
+ <string name="app_ops_use_audio_focus">nadzor žarišča zvoka</string>
+ <string name="app_ops_use_bluetooth_volume">nadzor glasnosti Bluetooth</string>
+ <string name="app_ops_use_master_volume">nadzor glavne glasnost</string>
+ <string name="app_ops_use_media_buttons">uporaba gumbov za predstavnost</string>
+ <string name="app_ops_use_media_volume">nadzor glasnosti predstavnosti</string>
+ <string name="app_ops_use_notification_volume">nadzor glasnosti obvestil</string>
+ <string name="app_ops_use_ring_volume">nadzor glasnosti zvonjenja</string>
+ <string name="app_ops_use_vibrate">uporaba haptičnega zaznavanja</string>
+ <string name="app_ops_use_voice_volume">nadzor glasnosti klicev</string>
+ <string name="app_ops_write_mms">sestavljanje sporočil MMS</string>
+ <string name="app_ops_write_sms">sestavljanje sporočil SMS</string>
+ <string name="app_ops_use_fingerprint">uporaba prstnih odtisov</string>
+ <string name="app_ops_add_voicemail">dodajanje glasovne pošte</string>
+ <string name="app_ops_read_phone_state">dostop do stanja telefona</string>
+ <string name="app_ops_scan_wifi">preiskovanje omrežij Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">spreminjanje slike ozadja</string>
+ <string name="app_ops_assist_structure">uporaba zgradbe za pomoč</string>
+ <string name="app_ops_assist_screenshot">zajemanje zaslonskih slik</string>
+ <string name="app_ops_use_body_sensors">uporaba tipal naprave</string>
+ <string name="app_ops_read_cell_broadcasts">branje signala oddajnikov</string>
+ <string name="app_ops_mock_location">prikazovanje lažne lokacije</string>
+ <string name="app_ops_read_external_storage">branje zunanje pomnilniške naprave</string>
+ <string name="app_ops_write_external_storage">pisanje zunanje pomnilniške naprave</string>
+ <string name="app_ops_turn_on_screen">vklapljanje zaslona</string>
+ <string name="app_ops_get_accounts">pridobivanje računov naprave</string>
+ <string name="app_ops_wifi_change">spreminjanje stanja Wi-Fi</string>
+ <string name="app_ops_su">pridobitev skrbniškega dostopa</string>
+ <string name="lock_to_app_toast_no_navbar">Da odpnete ta zaslon, se dotaknite in pridržite gumb Nazaj.</string>
+ <string name="live_display_auto">Samodejno</string>
+ <string name="live_display_auto_summary">Samodejno nastavi barvno temperaturo zaslona po sončnem zahodu in vzhodu</string>
+ <string name="live_display_off">Izklopljen</string>
+ <string name="live_display_off_summary">Onemogoči vse prilagoditve</string>
+ <string name="live_display_day">Dan</string>
+ <string name="live_display_day_summary">Uporabi samo dnevne nastavitve</string>
+ <string name="live_display_night">Noč</string>
+ <string name="live_display_night_summary">Uporabi samo nočne nastavitve</string>
+ <string name="live_display_outdoor">Na prostem (močna svetloba)</string>
+ <string name="live_display_outdoor_summary">Uporabi samo nastavitve na prostem</string>
+ <string name="live_display_hint">LiveDisplay vam lahko pomaga pri zmanjšanju obremenitve oči in spanju ponoči. Kliknite tukaj, da ga preskusite!</string>
+ <string name="tethered_notification_no_device_message">Nobene naprave ni povezane</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> povezana naprava</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> povezanih naprav</string>
+ <string name="notify_package_component_protected_title">Zagon dejavnosti blokiran</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> je zaščiten pred zagonom. Kliknite za overitev in zaženite aplikacijo.</string>
+ <string name="notify_battery_fully_charged_title">Baterija napolnjena</string>
+ <string name="notify_battery_fully_charged_text">Odklopite napravo iz polnilca za izboljšanje življenjske dobe baterije.</string>
+</resources>
diff --git a/core/res/res/values-sr/cm_strings.xml b/core/res/res/values-sr/cm_strings.xml
new file mode 100644
index 0000000..3453ce3
--- /dev/null
+++ b/core/res/res/values-sr/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Снимак екрана</string>
+ <string name="permlab_receiveProtectedSms">прими заштићени SMS</string>
+ <string name="permdesc_receiveProtectedSms">Дозволи да апликације приме долазећи заштићени SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">измените заштићену SMS листу</string>
+ <string name="permdesc_modifyProtectedSmsList">Дозвољава апликацији да мења заштићену SMS листу адреса.</string>
+ <string name="permgrouplab_security">Безбедност</string>
+ <string name="permgroupdesc_security">Дозволе које се односе на безбедносне информације уређаја.</string>
+ <string name="permlab_readPhoneBlacklist">читај црну листу телефона</string>
+ <string name="permdesc_readPhoneBlacklist">Омогућава апликацији да чита информације о телефонским бројевима који су блокирани за долазне позиве или поруке.</string>
+ <string name="permlab_changePhoneBlacklist">мењај црну листу телефона</string>
+ <string name="permdesc_changePhoneBlacklist">Омогућава апликацији да промени бројеве телефона које су блокирани за долазне позиве или поруке.</string>
+ <string name="permlab_setKeyguardWallpaper">постави позадину закључаног екрана</string>
+ <string name="permdesc_setKeyguardWallpaper">Омогућава апликацији да промени позадину на закључаном екрану.</string>
+ <string name="global_action_reboot">Рестартуј</string>
+ <string name="global_action_current_user">Тренутно</string>
+ <string name="reboot_reboot">Рестартуј</string>
+ <string name="reboot_recovery">Опоравак</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Преузимање</string>
+ <string name="reboot_soft">Рестартуј интерфејс</string>
+ <string name="reboot_title">Рестартуј</string>
+ <string name="reboot_confirm" product="tablet">Tаблет ће се рестартовати.</string>
+ <string name="reboot_confirm" product="default">Tелефон ће се рестартовати.</string>
+ <string name="reboot_progress">Рестартовање\u2026</string>
+ <string name="app_killed_message">Апликација је затворена</string>
+ <string name="adb_net_active_notification_title">ADB преко мреже омогућен</string>
+ <string name="adb_both_active_notification_title">ADB преко USB &amp; мреже омогућен</string>
+ <string name="adb_active_generic_notification_message">Додирни да онемогућиш отклањање грешака.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; мрежа</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Мрежа</string>
+ <string name="permlab_interceptPackageLaunch">пресретни подизање апликације</string>
+ <string name="stylus_app_not_installed">%s није инсталирано</string>
+ <string name="silent_mode_priority">Приоритет</string>
+ <string name="silent_mode_none">Ниједан</string>
+ <string name="subscription_change_disabled_wifi_ap">Онемогућен Wi-Fi hotspot због промене SIM претплате</string>
+ <string name="notify_turn_wifi_off_title">Искључи Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">омогући или онемогући заштиту приватности</string>
+ <string name="permdesc_changePrivacyGuardState">Дозвољава апликацији да промени да ли се друга апликација покреће са заштитом приватности. Када је апликација покренута са заштитом приватности, она неће имати приступ личним подацима, као што су контакти, евиденција позива или поруке.</string>
+ <string name="privacy_guard_notification">Заштита приватности је активна</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> неће бити у могућности да приступи личним подацима</string>
+ <string name="privacy_guard_dialog_title">Заштита приватности</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> жели да <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Запамти мој избор</string>
+ <string name="app_ops_access_camera">приступ камери</string>
+ <string name="app_ops_access_location">приступ твојој локацији</string>
+ <string name="app_ops_access_notifications">прочитај твоја обавештења</string>
+ <string name="app_ops_activate_vpn">aктивирај VPN</string>
+ <string name="app_ops_auto_start">покрени при укључивању</string>
+ <string name="app_ops_delete_call_log">избриши свој дневник позива</string>
+ <string name="app_ops_delete_contacts">избриши своје контакте</string>
+ <string name="app_ops_delete_mms">избриши своје MMS поруке</string>
+ <string name="app_ops_delete_sms">избриши своје SMS поруке</string>
+ <string name="app_ops_draw_on_top">исцртај windows на врху</string>
+ <string name="app_ops_get_usage_stats">добиј статистику коришћења апликација</string>
+ <string name="app_ops_keep_device_awake">држи уређај будним</string>
+ <string name="app_ops_make_phone_call">обави телефонски позив</string>
+ <string name="app_ops_modify_calendar">ажурирај твој календар</string>
+ <string name="app_ops_modify_call_log">ажурирај евиденцију позива</string>
+ <string name="app_ops_modify_clipboard">модификуј привремену меморију</string>
+ <string name="app_ops_modify_contacts">ажурирај твоје контакте</string>
+ <string name="app_ops_modify_settings">ажурирај подешавања система</string>
+ <string name="app_ops_mute_unmute_microphone">искључи/укључи микрофон</string>
+ <string name="app_ops_play_audio">пусти аудио</string>
+ <string name="app_ops_post_notification">постави обавештење</string>
+ <string name="app_ops_project_media">пројектовање медија</string>
+ <string name="app_ops_read_calendar">прочитај твој календар</string>
+ <string name="app_ops_read_call_log">прочитај евиденцију позива</string>
+ <string name="app_ops_read_clipboard">прочитај привремену меморију</string>
+ <string name="app_ops_read_contacts">прочитај твоје контакте</string>
+ <string name="app_ops_read_mms">прочитај твоје MMS поруке</string>
+ <string name="app_ops_read_sms">прочитај твоје SMS поруке</string>
+ <string name="app_ops_receive_sms">прими SMS поруку</string>
+ <string name="app_ops_record_audio">сними звук</string>
+ <string name="app_ops_send_mms">пошаљи MMS поруку</string>
+ <string name="app_ops_send_sms">пошаљи SMS поруку</string>
+ <string name="app_ops_start_at_bootup">покрени при укључивању</string>
+ <string name="app_ops_toast_window">прикажи искачуће поруке</string>
+ <string name="app_ops_toggle_bluetooth">пребаци Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">Укључи/искључи мобилне податке</string>
+ <string name="app_ops_toggle_nfc">пребацуј NFC</string>
+ <string name="app_ops_toggle_wifi">Wi-FI прекидач</string>
+ <string name="app_ops_use_alarm_volume">контрола јачине аларма</string>
+ <string name="app_ops_use_audio_focus">контрола аудио фокуса</string>
+ <string name="app_ops_use_bluetooth_volume">контрола Bluetooth јачине</string>
+ <string name="app_ops_use_master_volume">контрола главне јачине</string>
+ <string name="app_ops_use_media_buttons">користи дугмиће за медије</string>
+ <string name="app_ops_use_media_volume">контрола јачине за медије</string>
+ <string name="app_ops_use_notification_volume">контрола јачине обавештења</string>
+ <string name="app_ops_use_ring_volume">контрола јачине звона</string>
+ <string name="app_ops_use_vibrate">користи повратне информације</string>
+ <string name="app_ops_use_voice_volume">контрола јачине гласовног позива</string>
+ <string name="app_ops_write_mms">напиши MMS поруку</string>
+ <string name="app_ops_write_sms">напиши SMS поруку</string>
+ <string name="app_ops_use_fingerprint">користи отисак прста</string>
+ <string name="app_ops_add_voicemail">додај говорну поруку</string>
+ <string name="app_ops_read_phone_state">приступ стању телефона</string>
+ <string name="app_ops_scan_wifi">Скенирај Wi-Fi мреже</string>
+ <string name="app_ops_change_wallpaper">промени тапет</string>
+ <string name="app_ops_assist_structure">користи помоћну структуру</string>
+ <string name="app_ops_assist_screenshot">направи снимак екрана</string>
+ <string name="app_ops_use_body_sensors">користи сензоре уређаја</string>
+ <string name="app_ops_read_cell_broadcasts">читај ћелију емитовања</string>
+ <string name="app_ops_mock_location">лажирај своју локацију</string>
+ <string name="app_ops_read_external_storage">читај спољно складиште</string>
+ <string name="app_ops_write_external_storage">пиши на спољно складиште</string>
+ <string name="app_ops_turn_on_screen">укључи екран</string>
+ <string name="app_ops_get_accounts">добави налог уређаја</string>
+ <string name="app_ops_wifi_change">промени Wi-Fi стање</string>
+ <string name="app_ops_su">дај root приступ</string>
+ <string name="lock_to_app_toast_no_navbar">Да искључиш овај екран додирни и држи дугме за назад.</string>
+ <string name="live_display_auto">Аутоматски</string>
+ <string name="live_display_auto_summary">Аутоматски прилагоди температуру боје екрана после сумрака и свитања</string>
+ <string name="live_display_off">Искључено</string>
+ <string name="live_display_off_summary">Онемогућити сва подешавања</string>
+ <string name="live_display_day">Дан</string>
+ <string name="live_display_day_summary">Користи само дневна подешавања</string>
+ <string name="live_display_night">Ноћ</string>
+ <string name="live_display_night_summary">Користи само ноћна подешавања</string>
+ <string name="live_display_outdoor">Напољу (јако сунце)</string>
+ <string name="live_display_outdoor_summary">Користи само подешавања за напоље</string>
+ <string name="live_display_hint">LiveDisplay може смањити напрезање очију и помоћи да спавате ноћу. Додирните да пробате!</string>
+ <string name="tethered_notification_no_device_message">Нема повезаног уређаја</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> конектован уређај</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> конектовани уређаји</string>
+ <string name="notify_package_component_protected_title">Блокирана активност покретања</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> је заштићена од покретања. Додирни да потврдиш и покрени апликацију.</string>
+ <string name="notify_battery_fully_charged_title">Батерија пуна</string>
+ <string name="notify_battery_fully_charged_text">Искључи пуњач са уређаја да би побољшао трајност батерије.</string>
+</resources>
diff --git a/core/res/res/values-sv/cm_strings.xml b/core/res/res/values-sv/cm_strings.xml
new file mode 100644
index 0000000..88e02b6
--- /dev/null
+++ b/core/res/res/values-sv/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Skärmdump</string>
+ <string name="permlab_receiveProtectedSms">ta emot skyddade SMS</string>
+ <string name="permdesc_receiveProtectedSms">Tillåter att appen tar emot ett inkommande skyddat SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">ändra lista över skyddade SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Tillåter att appen ändrar listan över skyddade SMS.</string>
+ <string name="permgrouplab_security">Säkerhet</string>
+ <string name="permgroupdesc_security">Behörigheter relaterade till enhetssäkerhet.</string>
+ <string name="permlab_readPhoneBlacklist">läsa telefonens svartlista</string>
+ <string name="permdesc_readPhoneBlacklist">Tillåter en app att läsa information kring telefonnummer som är blockerade för inkommande samtal eller meddelanden.</string>
+ <string name="permlab_changePhoneBlacklist">ändra telefonens svartlista</string>
+ <string name="permdesc_changePhoneBlacklist">Tillåter en app att ändra de telefonnummer som är blockerade för inkommande samtal eller meddelanden.</string>
+ <string name="permlab_setKeyguardWallpaper">ställa in bakgrundsbild på låsskärm</string>
+ <string name="permdesc_setKeyguardWallpaper">Tillåter en app att ändra låsskärmens bakgrundsbild.</string>
+ <string name="global_action_reboot">Omstart</string>
+ <string name="global_action_current_user">Nuvarande</string>
+ <string name="reboot_reboot">Starta om</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Mjuk omstart</string>
+ <string name="reboot_title">Starta om</string>
+ <string name="reboot_confirm" product="tablet">Din surfplatta kommer att startas om.</string>
+ <string name="reboot_confirm" product="default">Din telefon kommer att startas om.</string>
+ <string name="reboot_progress">Startar om\u2026</string>
+ <string name="app_killed_message">App tvångsavslutad</string>
+ <string name="adb_net_active_notification_title">ADB över nätverk aktiverat</string>
+ <string name="adb_both_active_notification_title">ADB över USB och nätverk aktiverat</string>
+ <string name="adb_active_generic_notification_message">Tryck på för att inaktivera felsökning.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; nätverk</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Nätverk</string>
+ <string name="permlab_interceptPackageLaunch">avbryt app-start</string>
+ <string name="stylus_app_not_installed">%s är inte installerad</string>
+ <string name="silent_mode_priority">Prioritet</string>
+ <string name="silent_mode_none">Ingen</string>
+ <string name="subscription_change_disabled_wifi_ap">Wi\u2011Fi hotspot avaktiverad på grund av ändrat SIM-abonnemang</string>
+ <string name="notify_turn_wifi_off_title">Inaktivera Wi\u2011Fi</string>
+ <string name="permlab_changePrivacyGuardState">aktivera eller inaktivera integritetsskydd</string>
+ <string name="permdesc_changePrivacyGuardState">Tillåter appen att ändra huruvida en annan app körs med integritetsskydd. När en app körs med integritetsskydd har den ingen tillgång till personlig data som kontakter, samtalslistor och meddelanden.</string>
+ <string name="privacy_guard_notification">Integritetsskydd aktivt</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> kommer inte få tillgång till personlig data</string>
+ <string name="privacy_guard_dialog_title">Integritetsskydd</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> skulle vilja <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Kom ihåg mitt val</string>
+ <string name="app_ops_access_camera">få tillgång till kamera</string>
+ <string name="app_ops_access_location">få tillgång till din plats</string>
+ <string name="app_ops_access_notifications">läsa dina aviseringar</string>
+ <string name="app_ops_activate_vpn">aktivera en VPN</string>
+ <string name="app_ops_auto_start">starta vid uppstart</string>
+ <string name="app_ops_delete_call_log">ta bort samtalsloggen</string>
+ <string name="app_ops_delete_contacts">ta bort dina kontakter</string>
+ <string name="app_ops_delete_mms">ta bort dina MMS-meddelanden</string>
+ <string name="app_ops_delete_sms">ta bort dina SMS-meddelanden</string>
+ <string name="app_ops_draw_on_top">rita fönster överst</string>
+ <string name="app_ops_get_usage_stats">få användningsstatistik för app</string>
+ <string name="app_ops_keep_device_awake">hålla din enhet vaken</string>
+ <string name="app_ops_make_phone_call">ringa</string>
+ <string name="app_ops_modify_calendar">uppdatera din kalender</string>
+ <string name="app_ops_modify_call_log">uppdatera samtalslistan</string>
+ <string name="app_ops_modify_clipboard">modifiera urklipp</string>
+ <string name="app_ops_modify_contacts">uppdatera dina kontakter</string>
+ <string name="app_ops_modify_settings">uppdatera systeminställningar</string>
+ <string name="app_ops_mute_unmute_microphone">slå på/av mikrofonen</string>
+ <string name="app_ops_play_audio">spela ljud</string>
+ <string name="app_ops_post_notification">skicka en avisering</string>
+ <string name="app_ops_project_media">projektmedia</string>
+ <string name="app_ops_read_calendar">läsa din kalender</string>
+ <string name="app_ops_read_call_log">läsa samtalslistan</string>
+ <string name="app_ops_read_clipboard">läsa urklipp</string>
+ <string name="app_ops_read_contacts">läsa dina kontakter</string>
+ <string name="app_ops_read_mms">läsa dina MMS</string>
+ <string name="app_ops_read_sms">läsa dina SMS</string>
+ <string name="app_ops_receive_sms">ta emot ett SMS</string>
+ <string name="app_ops_record_audio">spela in ljud</string>
+ <string name="app_ops_send_mms">skicka ett MMS</string>
+ <string name="app_ops_send_sms">skicka ett SMS</string>
+ <string name="app_ops_start_at_bootup">starta vid uppstart</string>
+ <string name="app_ops_toast_window">visa toast-meddelanden</string>
+ <string name="app_ops_toggle_bluetooth">växla Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">växla mobildata</string>
+ <string name="app_ops_toggle_nfc">växla NFC</string>
+ <string name="app_ops_toggle_wifi">växla Wi\u2011Fi</string>
+ <string name="app_ops_use_alarm_volume">kontrollera alarmvolym</string>
+ <string name="app_ops_use_audio_focus">kontrollera ljudfokus</string>
+ <string name="app_ops_use_bluetooth_volume">kontrollera Bluetoothvolymen</string>
+ <string name="app_ops_use_master_volume">kontrollera mastervolymen</string>
+ <string name="app_ops_use_media_buttons">använda mediaknapparna</string>
+ <string name="app_ops_use_media_volume">kontrollera mediavolymen</string>
+ <string name="app_ops_use_notification_volume">kontrollera aviseringsvolymen</string>
+ <string name="app_ops_use_ring_volume">kontrollera ringsignalsvolymen</string>
+ <string name="app_ops_use_vibrate">använda haptisk feedback</string>
+ <string name="app_ops_use_voice_volume">kontrollera samtalsvolymen</string>
+ <string name="app_ops_write_mms">skriva ett MMS</string>
+ <string name="app_ops_write_sms">skriva ett SMS</string>
+ <string name="app_ops_use_fingerprint">använd fingeravtryck</string>
+ <string name="app_ops_add_voicemail">lägg till ett röstmeddelande</string>
+ <string name="app_ops_read_phone_state">läs telefonstatus</string>
+ <string name="app_ops_scan_wifi">skanna Wi\u2011Fi-nätverk</string>
+ <string name="app_ops_change_wallpaper">ändra bakgrund</string>
+ <string name="app_ops_assist_structure">använd assistansstruktur</string>
+ <string name="app_ops_assist_screenshot">ta en skärmdump</string>
+ <string name="app_ops_use_body_sensors">använd kroppssensorer</string>
+ <string name="app_ops_read_cell_broadcasts">läs mobila sändningar</string>
+ <string name="app_ops_mock_location">ange skenplats</string>
+ <string name="app_ops_read_external_storage">läs extern lagring</string>
+ <string name="app_ops_write_external_storage">skriv extern lagring</string>
+ <string name="app_ops_turn_on_screen">aktivera skärmen</string>
+ <string name="app_ops_get_accounts">hämta enhetskonton</string>
+ <string name="app_ops_wifi_change">ändra Wi\u2011Fi status</string>
+ <string name="app_ops_su">få root-åtkomst</string>
+ <string name="lock_to_app_toast_no_navbar">För att frigöra denna skärm, tryck och håll nere Bakåt-knappen.</string>
+ <string name="live_display_auto">Automatisk</string>
+ <string name="live_display_auto_summary">Justera automatiskt skärmens färgtemperatur efter solnedgång och soluppgång</string>
+ <string name="live_display_off">Av</string>
+ <string name="live_display_off_summary">Inaktivera alla justeringar</string>
+ <string name="live_display_day">Dag</string>
+ <string name="live_display_day_summary">Använd enbart dagläge</string>
+ <string name="live_display_night">Natt</string>
+ <string name="live_display_night_summary">Använd enbart nattläge</string>
+ <string name="live_display_outdoor">Utomhus (stark sol)</string>
+ <string name="live_display_outdoor_summary">Använd endast utomhusläge</string>
+ <string name="live_display_hint">LiveDisplay kan minska överansträngning av ögon och hjälpa dig med nattsömnen. Klicka här för att prova!</string>
+ <string name="tethered_notification_no_device_message">Ingen ansluten enhet</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> ansluten enhet</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> anslutna enheter</string>
+ <string name="notify_package_component_protected_title">Aktivitetsstart blockerad</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> är skyddad från att startas. Tryck för att autentisera och starta programmet.</string>
+ <string name="notify_battery_fully_charged_title">Batteriet fulladdat</string>
+ <string name="notify_battery_fully_charged_text">Koppla bort enheten från laddaren för att förbättra batteriets livslängd.</string>
+</resources>
diff --git a/core/res/res/values-ta-rIN/cm_strings.xml b/core/res/res/values-ta-rIN/cm_strings.xml
new file mode 100644
index 0000000..415fb8f
--- /dev/null
+++ b/core/res/res/values-ta-rIN/cm_strings.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">திரைப்பிடிப்பு</string>
+ <string name="global_action_reboot">மறுதொடக்கம்</string>
+ <string name="reboot_reboot">மறுதொடக்கம்</string>
+ <string name="reboot_recovery">மீட்பு (ரெகவரி)</string>
+ <string name="reboot_bootloader">துவக்க ஏற்றி</string>
+ <string name="reboot_download">பதிவிறக்கம்</string>
+ <string name="reboot_confirm" product="tablet">உங்கள் கைக்கணினி மீண்டும் துவக்கபடும்.</string>
+ <string name="reboot_confirm" product="default">உங்கள் தொலைபேசி மீண்டும் துவக்கபடும்.</string>
+ <string name="reboot_progress">மீண்டும் துவக்க\u2026</string>
+ <string name="permdesc_changePrivacyGuardState">பயன்பாட்டை மற்றொரு பயன்பாடு தனியுரிமை பாதுகாப்பு கொண்டு இயங்குமா என்பதை மாற்ற அனுமதிக்கிறது. ஒரு பயன்பாடு தனியுரிமை பாதுகாப்பு கொண்டு இயங்கும் போது, இது போன்ற தொடர்புகள், அழைப்பு பதிவுகள், மற்றும் செய்திகள் போன்ற தனிப்பட்ட தரவுக்கான அணுகல் இருக்காது.</string>
+ <string name="privacy_guard_notification">தனியுரிமை பாதுகாப்பு செயலில்</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> தனிப்பட்ட தரவை அணுக முடியாது</string>
+ <string name="privacy_guard_dialog_title">தனியுரிமை பாதுகாப்பு</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> <xliff:g id="op">%2$s</xliff:g> விரும்புகிறது.</string>
+ <string name="app_ops_access_camera">கேமரா அணுக</string>
+ <string name="app_ops_access_location">உங்கள் இருப்பிடத்தை அணுக</string>
+ <string name="app_ops_access_notifications">உங்கள் அறிவிக்கைகள் படிக்க</string>
+ <string name="app_ops_keep_device_awake">உங்கள் கருவியை விழித்து வைக்க</string>
+ <string name="app_ops_make_phone_call">தொலைபேசியில் அழைப்பு செய்ய</string>
+ <string name="app_ops_modify_calendar">உங்கள் நாட்காட்டியில் மேம்படுத்த</string>
+ <string name="app_ops_modify_call_log">அழைப்பு பதிவு மேம்படுத்த</string>
+ <string name="app_ops_modify_clipboard">இடைநிலை பலகையை திருத்த</string>
+ <string name="app_ops_modify_contacts">உங்கள் தொடர்புகள் மேம்படுத்த</string>
+ <string name="app_ops_modify_settings">முறைமை அமைப்புகள் மேம்படுத்த</string>
+ <string name="app_ops_play_audio">ஒலி விளையாட</string>
+ <string name="app_ops_post_notification">அறிவிக்கை பதிவு செய்ய</string>
+ <string name="app_ops_read_calendar">உங்கள் நாட்காட்டியை படிக்க</string>
+ <string name="app_ops_read_call_log">அழைப்பு பதிவை படிக்க</string>
+ <string name="app_ops_read_clipboard">இடைநிலை பலகை படிக்க</string>
+ <string name="app_ops_read_contacts">உங்கள் தொடர்புகள் படிக்க</string>
+ <string name="app_ops_read_mms">உங்கள் எம்எம்எஸ் செய்திகளை படிக்க</string>
+ <string name="app_ops_read_sms">உங்கள் குறுந்தகவல் செய்திகளை படிக்க</string>
+ <string name="app_ops_receive_sms">ஒரு குறுந்தகவல் செய்தி பெற</string>
+ <string name="app_ops_record_audio">ஒலி பதிவு செய்ய</string>
+ <string name="app_ops_send_mms">ஒரு எம்எம்எஸ் செய்தி அனுப்ப</string>
+ <string name="app_ops_send_sms">ஒரு குறுந்தகவல் செய்தி அனுப்ப</string>
+ <string name="app_ops_start_at_bootup">மின்சக்தி தொடக்கத்தில் ஆரம்பிக்க</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth நிலைமாற்று</string>
+ <string name="app_ops_use_alarm_volume">அலார ஒலி கட்டுப்படுத்த</string>
+ <string name="app_ops_use_audio_focus">ஒலி கவனத்தை கட்டுப்படுத்த</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetooth ஒலியளவு கட்டுப்படுத்த</string>
+ <string name="app_ops_use_master_volume">முதன்மை ஒலியளவு கட்டுப்படுத்த</string>
+ <string name="app_ops_use_media_buttons">ஊடக பொத்தான்கள் பயன்படுத்தவும்</string>
+ <string name="app_ops_use_media_volume">ஊடக ஒலியளவு கட்டுப்படுத்த</string>
+ <string name="app_ops_use_notification_volume">அறிவித்தல் ஒலியளவு கட்டுப்படுத்த</string>
+ <string name="app_ops_use_ring_volume">ரிங்டோன் ஒலியளவு கட்டுப்படுத்த</string>
+ <string name="app_ops_use_vibrate">தொடு உணர்வியல் பின்னூட்டம் பயன்படுத்தவும்</string>
+ <string name="app_ops_use_voice_volume">குரல் அழைப்பு ஒலியை கட்டுப்படுத்த</string>
+ <string name="app_ops_write_mms">ஒரு எம்எம்எஸ் தகவலை எழுது</string>
+ <string name="app_ops_write_sms">ஒரு எஸ்எம்எஸ் செய்தி எழுது</string>
+</resources>
diff --git a/core/res/res/values-th/cm_strings.xml b/core/res/res/values-th/cm_strings.xml
new file mode 100644
index 0000000..ca087e8
--- /dev/null
+++ b/core/res/res/values-th/cm_strings.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">ถ่ายภาพหน้าจอ</string>
+ <string name="permlab_receiveProtectedSms">รับ SMS ที่ได้รับการปกป้อง</string>
+ <string name="permdesc_receiveProtectedSms">อนุญาตให้แอปรับ SMS ที่ได้รับการปกป้อง</string>
+ <string name="permlab_modifyProtectedSmsList">แก้ไขรายการ SMS ที่ได้รับการปกป้อง</string>
+ <string name="permdesc_modifyProtectedSmsList">อนุญาตให้แอปแก้ไขรายการที่อยู่ SMS ที่ได้รับการปกป้อง</string>
+ <string name="permgrouplab_security">ความปลอดภัย</string>
+ <string name="permgroupdesc_security">สิทธิ์ที่เกี่ยวข้องกับข้อมูลความปลอดภัยของอุปกรณ์</string>
+ <string name="permlab_readPhoneBlacklist">อ่านรายชื่อบัญชีดำ</string>
+ <string name="permdesc_readPhoneBlacklist">อนุญาตให้แอปอ่านข้อมูลหมายเลขโทรศัพท์ที่ถูกบล็อคสำหรับสายการโทรเข้าหรือข้อความ</string>
+ <string name="permlab_changePhoneBlacklist">เปลี่ยนรายชื่อบัญชีดำ</string>
+ <string name="permdesc_changePhoneBlacklist">อนุญาตให้แอปเปลี่ยนหมายเลขที่ถูกบล็อคสำหรับสายการโทรเข้าหรือข้อความ</string>
+ <string name="permlab_setKeyguardWallpaper">ตั้งภาพล็อคหน้าจอ</string>
+ <string name="permdesc_setKeyguardWallpaper">อนุญาตให้แอปเปลี่ยนภาพล็อคหน้าจอได้</string>
+ <string name="global_action_reboot">เริ่มระบบใหม่</string>
+ <string name="global_action_current_user">ปัจจุบัน</string>
+ <string name="reboot_reboot">เริ่มระบบใหม่</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">ดาวน์โหลด</string>
+ <string name="reboot_soft">เริ่มระบบแบบซอฟต์รีบู๊ต</string>
+ <string name="reboot_title">เริ่มระบบใหม่</string>
+ <string name="reboot_confirm" product="tablet">แท็บเล็ตของคุณจะเริ่มระบบใหม่</string>
+ <string name="reboot_confirm" product="default">โทรศัพท์ของคุณจะเริ่มระบบใหม่</string>
+ <string name="reboot_progress">กำลังเริ่มระบบใหม่\u2026</string>
+ <string name="app_killed_message">ปิดแอป</string>
+ <string name="adb_net_active_notification_title">ADB บนเครือข่ายถูกเปิดใช้งาน</string>
+ <string name="adb_both_active_notification_title">ADB บน USB และ &amp; เครือข่ายถูกเปิดใช้งาน</string>
+ <string name="adb_active_generic_notification_message">แตะเพื่อปิดการแก้ไขข้อบกพร่อง</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; เครือข่าย</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">เครือข่าย</string>
+ <string name="permlab_interceptPackageLaunch">ขัดขวางการเปิดแอป</string>
+ <string name="stylus_app_not_installed">%s ไม่ถูกติดตั้ง</string>
+ <string name="silent_mode_priority">ระดับความสำคัญ</string>
+ <string name="silent_mode_none">ไม่มี</string>
+ <string name="subscription_change_disabled_wifi_ap">ปิดฮอตสปอต Wi-Fi เนื่องจากการเปลี่ยนแปลงการสมัครซิมการ์ด</string>
+ <string name="notify_turn_wifi_off_title">ปิด Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">เปิดหรือปิดการป้องกันความเป็นส่วนตัว</string>
+ <string name="permdesc_changePrivacyGuardState">อนุญาตให้แอปเปลี่ยนแปลงไม่ว่าแอปอื่นทำงานโดยใช้การป้องกันความเป็นส่วนตัวหรือไม่ก็ตาม เมื่อแอปกำลังทำงานโดยใช้การป้องกันความเป็นส่วนตัว แอปจะไม่สามารถเข้าถึงข้อมูลส่วนบุคคล เช่น รายชื่อติดต่อ ประวัติการโทร หรือข้อความได้</string>
+ <string name="privacy_guard_notification">การป้องกันความเป็นส่วนตัวทำงาน</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> จะไม่สามารถเข้าถึงข้อมูลส่วนตัวได้</string>
+ <string name="privacy_guard_dialog_title">รักษาความเป็นส่วนตัว</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> ต้องการ <xliff:g id="op">%2$s</xliff:g></string>
+ <string name="permission_remember_choice">จำตัวเลือกของฉัน</string>
+ <string name="app_ops_access_camera">เข้าถึงกล้อง</string>
+ <string name="app_ops_access_location">เข้าถึงตำแหน่งที่ตั้งของคุณ</string>
+ <string name="app_ops_access_notifications">อ่านการแจ้งเตือน</string>
+ <string name="app_ops_activate_vpn">เปิดใช้งาน VPN</string>
+ <string name="app_ops_auto_start">เริ่มเมื่อเปิดเครื่อง</string>
+ <string name="app_ops_delete_call_log">ลบประวัติการโทรของคุณ</string>
+ <string name="app_ops_delete_contacts">ลบรายชื่อติดต่อของคุณ</string>
+ <string name="app_ops_delete_mms">ลบข้อความ MMS ของคุณ</string>
+ <string name="app_ops_delete_sms">ลบข้อความ SMS ของคุณ</string>
+ <string name="app_ops_draw_on_top">วาดหน้าต่างทับ</string>
+ <string name="app_ops_get_usage_stats">รับสถิติการใช้งานแอป</string>
+ <string name="app_ops_keep_device_awake">เปิดจอค้าง</string>
+ <string name="app_ops_make_phone_call">โทรออก</string>
+ <string name="app_ops_modify_calendar">อัปเดตปฏิทิน</string>
+ <string name="app_ops_modify_call_log">อัปเดตประวัติการโทร</string>
+ <string name="app_ops_modify_clipboard">ปรับแต่งคลิปบอร์ด</string>
+ <string name="app_ops_modify_contacts">อัปเดตรายชื่อติดต่อ</string>
+ <string name="app_ops_modify_settings">อัปเดตการตั้งค่าระบบ</string>
+ <string name="app_ops_mute_unmute_microphone">ปิด/เปิด ไมโครโฟน</string>
+ <string name="app_ops_play_audio">เล่นเสียง</string>
+ <string name="app_ops_post_notification">โพสต์การแจ้งเตือน</string>
+ <string name="app_ops_project_media">สื่อโครงการ</string>
+ <string name="app_ops_read_calendar">อ่านปฏิทิน</string>
+ <string name="app_ops_read_call_log">อ่านประวัติการโทร</string>
+ <string name="app_ops_read_clipboard">อ่านคลิปบอร์ด</string>
+ <string name="app_ops_read_contacts">อ่านรายชื่อติดต่อ</string>
+ <string name="app_ops_read_mms">อ่านข้อความ MMS</string>
+ <string name="app_ops_read_sms">อ่านข้อความ SMS</string>
+ <string name="app_ops_receive_sms">รับข้อความ SMS</string>
+ <string name="app_ops_record_audio">บันทึกเสียง</string>
+ <string name="app_ops_send_mms">ส่งข้อความ MMS</string>
+ <string name="app_ops_send_sms">ส่งข้อความ SMS</string>
+ <string name="app_ops_start_at_bootup">เริ่มเมื่อเปิดเครื่อง</string>
+ <string name="app_ops_toast_window">แสดงแถบข้อความ</string>
+ <string name="app_ops_toggle_bluetooth">สลับบลูทูธ</string>
+ <string name="app_ops_toggle_nfc">สลับ NFC</string>
+ <string name="app_ops_toggle_wifi">สลับ WiFi</string>
+ <string name="app_ops_use_alarm_volume">ควบคุมระดับเสียงนาฬิกาปลุก</string>
+ <string name="app_ops_use_audio_focus">ควบคุมการโฟกัสเสียง</string>
+ <string name="app_ops_use_bluetooth_volume">ควบคุมระดับเสียงบลูทูธ</string>
+ <string name="app_ops_use_master_volume">ควบคุมระดับเสียงหลัก</string>
+ <string name="app_ops_use_media_buttons">ใช้ปุ่มสื่อ</string>
+ <string name="app_ops_use_media_volume">ควบคุมระดับเสียงสื่อ</string>
+ <string name="app_ops_use_notification_volume">ควบคุมระดับเสียงแจ้งเตือน</string>
+ <string name="app_ops_use_ring_volume">ควบคุมระดับเสียงเรียกเข้า</string>
+ <string name="app_ops_use_vibrate">ใช้สั่นเมื่อแตะ</string>
+ <string name="app_ops_use_voice_volume">ควบคุมเสียงสนทนา</string>
+ <string name="app_ops_write_mms">เขียนข้อความ MMS</string>
+ <string name="app_ops_write_sms">เขียนข้อความ SMS</string>
+ <string name="app_ops_use_fingerprint">ใช้ลายนิ้วมือ</string>
+ <string name="app_ops_add_voicemail">เพิ่มการฝากข้อความ</string>
+ <string name="app_ops_read_phone_state">เข้าถึงสถานะโทรศัพท์</string>
+ <string name="app_ops_scan_wifi">ค้นหาเครือข่าย Wi-Fi</string>
+ <string name="app_ops_change_wallpaper">เปลี่ยนรูปพื้นหลัง</string>
+ <string name="app_ops_assist_structure">ใช้โครงสร้างช่วย</string>
+ <string name="app_ops_assist_screenshot">ถ่ายภาพหน้าจอ</string>
+ <string name="app_ops_use_body_sensors">ใช้เซนเซอร์ตรวจร่างกาย</string>
+ <string name="app_ops_read_cell_broadcasts">อ่านการติดต่อเครือข่าย</string>
+ <string name="app_ops_mock_location">จำลองที่ตั้ง</string>
+ <string name="app_ops_read_external_storage">อ่านที่เก็บข้อมูลภายนอก</string>
+ <string name="app_ops_write_external_storage">เขียนที่เก็บข้อมูลภายนอก</string>
+ <string name="app_ops_turn_on_screen">เปิดหน้าจอ</string>
+ <string name="app_ops_get_accounts">เข้าถึงบัญชีของอุปกรณ์</string>
+ <string name="app_ops_wifi_change">เปลี่ยนแปลงสถานะ Wi-Fi</string>
+ <string name="app_ops_su">รับสิทธิผู้ดูแลระบบ</string>
+ <string name="lock_to_app_toast_no_navbar">เพื่อยกเลิกการปักหมุดหน้าจอนี้ กดปุ่มกลับค้างไว้</string>
+ <string name="live_display_auto">อัตโนมัติ</string>
+ <string name="live_display_auto_summary">ตั้งอุณหภูมิสีจออัตโนมัติหลังดวงอาทิตย์ขึ้นและตก</string>
+ <string name="live_display_off">ปิด</string>
+ <string name="live_display_off_summary">ปิดการปรับแต่งทั้งหมด</string>
+ <string name="live_display_day">กลางวัน</string>
+ <string name="live_display_day_summary">ใช้การตั้งค่ากลางวันเท่านั้น</string>
+ <string name="live_display_night">กลางคืน</string>
+ <string name="live_display_night_summary">ใช้การตั้งค่ากลางคืนเท่านั้น</string>
+ <string name="live_display_outdoor">กลางแจ้ง (แดดจ้า)</string>
+ <string name="live_display_outdoor_summary">ใช้การตั้งค่ากลางแจ้งเท่านั้น</string>
+ <string name="live_display_hint">LiveDisplay สามารถช่วยลดอาการปวดตา และช่วยให้คุณนอนหลับในเวลากลางคืน คลิกที่นี่เพื่อลองใช้!</string>
+ <string name="tethered_notification_no_device_message">ไม่มีอุปกรณ์เชื่อมต่อ</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> อุปกรณ์เชื่อมต่ออยู่</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> อุปกรณ์เชื่อมต่ออยู่</string>
+ <string name="notify_package_component_protected_title">การเปิดกิจจรรมถูกบล็อก</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> ถูกป้องกันจากการเปิด แตะเพื่อยืนยันและเปิดแอป</string>
+</resources>
diff --git a/core/res/res/values-tr/cm_strings.xml b/core/res/res/values-tr/cm_strings.xml
new file mode 100644
index 0000000..1cd22e5
--- /dev/null
+++ b/core/res/res/values-tr/cm_strings.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ekran görüntüsü</string>
+ <string name="permlab_receiveProtectedSms">korumalı SMS al</string>
+ <string name="permdesc_receiveProtectedSms">Uygulamaya korumalı bir SMS alma izni verir.</string>
+ <string name="permlab_modifyProtectedSmsList">korumalı SMS listesini değiştir</string>
+ <string name="permdesc_modifyProtectedSmsList">Uygulamaya korumalı SMS adres listesini değiştirme izni verir.</string>
+ <string name="permgrouplab_security">Güvenlik</string>
+ <string name="permgroupdesc_security">Cihaz güvenlik bilgisi ile ilgili izinler.</string>
+ <string name="permlab_readPhoneBlacklist">telefon kara listesini oku</string>
+ <string name="permdesc_readPhoneBlacklist">Bir uygulamanın gelen çağrıları ya da mesajları engellenmiş telefon numaralarını okumasına izin verir.</string>
+ <string name="permlab_changePhoneBlacklist">telefon kara listesini değiştir</string>
+ <string name="permdesc_changePhoneBlacklist">Bir uygulamanın gelen çağrıları ya da mesajları engellenmiş telefon numaralarını değiştirmesine izin verir.</string>
+ <string name="permlab_setKeyguardWallpaper">tuş kilidi duvar kağıdını ayarla</string>
+ <string name="permdesc_setKeyguardWallpaper">Bir uygulamanın kilit ekranı duvar kağıdını değiştirmesine izin verir.</string>
+ <string name="global_action_reboot">Yeniden başlat</string>
+ <string name="global_action_current_user">Şimdiki</string>
+ <string name="reboot_reboot">Yeniden başlat</string>
+ <string name="reboot_recovery">Kurtarma modu (Recovery)</string>
+ <string name="reboot_bootloader">Ön yükleyici (Bootloader)</string>
+ <string name="reboot_download">İndir</string>
+ <string name="reboot_soft">Yazılımsal yeniden başlatma</string>
+ <string name="reboot_title">Yeniden Başlat</string>
+ <string name="reboot_confirm" product="tablet">Tabletiniz yeniden başlatılacak.</string>
+ <string name="reboot_confirm" product="default">Telefonunuz yeniden başlatılacak.</string>
+ <string name="reboot_progress">Yeniden başlatılıyor\u2026</string>
+ <string name="app_killed_message">Uyg. sonlandırıldı</string>
+ <string name="adb_net_active_notification_title">Ağ üzerinden ADB etkin</string>
+ <string name="adb_both_active_notification_title">USB &amp; Ağ üzerinden ADB etkin</string>
+ <string name="adb_active_generic_notification_message">Hata ayıklamayı devre dışı bırakmak için dokunun.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; ağ</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Ağ</string>
+ <string name="permlab_interceptPackageLaunch">uygulama başlangıcını önle</string>
+ <string name="stylus_app_not_installed">%s yüklü değil</string>
+ <string name="silent_mode_priority">Öncelik</string>
+ <string name="silent_mode_none">Yok</string>
+ <string name="subscription_change_disabled_wifi_ap">SIM abonelik değişikliği nedeniyle Wi-Fi internet paylaşımı devre dışı bırakıldı</string>
+ <string name="notify_turn_wifi_off_title">Wi-Fi\'yi kapat</string>
+ <string name="permlab_changePrivacyGuardState">Gizlilik Korumasını etkinleştir ya da devre dışı bırak</string>
+ <string name="permdesc_changePrivacyGuardState">Uygulamaya başka bir uygulamanın Gizlilik Korumasını kullanıp kullanamayacağını belirleme olanağı verir. Bir uygulama Gizlilik Koruması ile çalışırken; kişiler, arama kayıtları ya da mesajlar gibi kişisel bilgilere ulaşamaz.</string>
+ <string name="privacy_guard_notification">Gizlilik Koruması aktif</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> kişisel bilgilere ulaşamayacak</string>
+ <string name="privacy_guard_dialog_title">Gizlilik Koruması</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> <xliff:g id="op">%2$s</xliff:g> iznini kullanmak istiyor.</string>
+ <string name="permission_remember_choice">Seçimimi hatırla</string>
+ <string name="app_ops_access_camera">kameraya eriş</string>
+ <string name="app_ops_access_location">konuma erişim</string>
+ <string name="app_ops_access_notifications">bildirimleri oku</string>
+ <string name="app_ops_activate_vpn">VPN\'yi etkinleştir</string>
+ <string name="app_ops_auto_start">açılışta başla</string>
+ <string name="app_ops_delete_call_log">arama kaydını sil</string>
+ <string name="app_ops_delete_contacts">kişileri sil</string>
+ <string name="app_ops_delete_mms">MMS mesajlarınızı silin</string>
+ <string name="app_ops_delete_sms">SMS\'leri sil</string>
+ <string name="app_ops_draw_on_top">pencereleri üstte göster</string>
+ <string name="app_ops_get_usage_stats">uyg. kullanım istatistiklerini al</string>
+ <string name="app_ops_keep_device_awake">cihazı uyanık tut</string>
+ <string name="app_ops_make_phone_call">telefon görüşmesi yap</string>
+ <string name="app_ops_modify_calendar">takvimini güncelle</string>
+ <string name="app_ops_modify_call_log">arama kaydını güncelle</string>
+ <string name="app_ops_modify_clipboard">panoyu değiştir</string>
+ <string name="app_ops_modify_contacts">kişileri güncelle</string>
+ <string name="app_ops_modify_settings">sistem ayarlarını güncelle</string>
+ <string name="app_ops_mute_unmute_microphone">mikrofonu aç/kapa</string>
+ <string name="app_ops_play_audio">ses çal</string>
+ <string name="app_ops_post_notification">bildirim gönder</string>
+ <string name="app_ops_project_media">ortamı yansıt</string>
+ <string name="app_ops_read_calendar">takvimi oku</string>
+ <string name="app_ops_read_call_log">arama kaydını oku</string>
+ <string name="app_ops_read_clipboard">panoyu oku</string>
+ <string name="app_ops_read_contacts">kişileri oku</string>
+ <string name="app_ops_read_mms">MMS mesajlarınızı okuyun</string>
+ <string name="app_ops_read_sms">SMS mesajlarını oku</string>
+ <string name="app_ops_receive_sms">SMS mesajı al</string>
+ <string name="app_ops_record_audio">ses kaydet</string>
+ <string name="app_ops_send_mms">MMS mesajı gönder</string>
+ <string name="app_ops_send_sms">SMS mesajı gönder</string>
+ <string name="app_ops_start_at_bootup">açılışta başla</string>
+ <string name="app_ops_toast_window">bildirim mesajları göster</string>
+ <string name="app_ops_toggle_bluetooth">Bluetooth\'u açıp kapat</string>
+ <string name="app_ops_toggle_nfc">NFC\'yi aç kapa</string>
+ <string name="app_ops_toggle_wifi">Wi-Fi aç kapa</string>
+ <string name="app_ops_use_alarm_volume">alarm sesini kontrol et</string>
+ <string name="app_ops_use_audio_focus">ses odağını kontrol et</string>
+ <string name="app_ops_use_bluetooth_volume">Bluetooth sesini kontrol et</string>
+ <string name="app_ops_use_master_volume">ana ses düzeyini kontrol et</string>
+ <string name="app_ops_use_media_buttons">ortam tuşlarını kullan</string>
+ <string name="app_ops_use_media_volume">ortam sesini kontrol et</string>
+ <string name="app_ops_use_notification_volume">bildirim sesini kontrol et</string>
+ <string name="app_ops_use_ring_volume">zil sesini kontrol et</string>
+ <string name="app_ops_use_vibrate">dokunmatik geri bildirim kullan</string>
+ <string name="app_ops_use_voice_volume">Sesli arama seviyesini kontrol et</string>
+ <string name="app_ops_write_mms">MMS mesajı yaz</string>
+ <string name="app_ops_write_sms">SMS mesajı yaz</string>
+ <string name="app_ops_use_fingerprint">parmak izi kullan</string>
+ <string name="app_ops_add_voicemail">bir sesli mesaj ekle</string>
+ <string name="app_ops_read_phone_state">telefon durumuna eriş</string>
+ <string name="app_ops_scan_wifi">Wi-Fi ağlarını tara</string>
+ <string name="app_ops_change_wallpaper">duvar kağıdını değiştir</string>
+ <string name="app_ops_assist_structure">destek yapısı kullan</string>
+ <string name="app_ops_assist_screenshot">ekran görüntüsü al</string>
+ <string name="app_ops_use_body_sensors">vücut sensörü kullan</string>
+ <string name="app_ops_read_cell_broadcasts">hücre yayınları oku</string>
+ <string name="app_ops_mock_location">sahte konum bildir</string>
+ <string name="app_ops_read_external_storage">harici depolamayı oku</string>
+ <string name="app_ops_write_external_storage">harici depolama alanına yaz</string>
+ <string name="app_ops_turn_on_screen">ekranı aç</string>
+ <string name="app_ops_get_accounts">cihaz hesaplarını al</string>
+ <string name="app_ops_wifi_change">Wi-Fi durumunu değiştir</string>
+ <string name="app_ops_su">root erişimi al</string>
+ <string name="lock_to_app_toast_no_navbar">Bu ekranı kaldırmak için Geri tuşuna dokunun ve tutun.</string>
+ <string name="live_display_auto">Otomatik</string>
+ <string name="live_display_auto_summary">Gün batımı ve doğumundan sonra ekranın renk sıcaklığını otomatik ayarlar</string>
+ <string name="live_display_off">Kapalı</string>
+ <string name="live_display_off_summary">Tüm ayarlamaları devre dışı bırak</string>
+ <string name="live_display_day">Gündüz</string>
+ <string name="live_display_day_summary">Sadece gündüz ayarlarını kullan</string>
+ <string name="live_display_night">Gece</string>
+ <string name="live_display_night_summary">Sadece gece ayarlarını kullan</string>
+ <string name="live_display_outdoor">Açık alan (parlak güneş)</string>
+ <string name="live_display_outdoor_summary">Sadece açık alan ayarlarını kullan</string>
+ <string name="live_display_hint">LiveDisplay göz yorgunluğunuzu azaltıp geceleri uyumanıza yardımcı olabilir. Denemek için buraya tıklayın!</string>
+ <string name="tethered_notification_no_device_message">Bağlı cihaz yok</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s </xliff:g> cihaz bağlı</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> cihaz bağlı</string>
+</resources>
diff --git a/core/res/res/values-ug/cm_strings.xml b/core/res/res/values-ug/cm_strings.xml
new file mode 100644
index 0000000..5332e1f
--- /dev/null
+++ b/core/res/res/values-ug/cm_strings.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">ئېكراندىن تۇتۇلغان سۈرەت</string>
+ <string name="permlab_receiveProtectedSms">قوغدالغان قىسقا ئۇچۇرنى قوبۇل قىلىش</string>
+ <string name="permdesc_receiveProtectedSms">ئەپنىڭ قوغدالغان قىسقا ئۇچۇرنى قوبۇللىشىغا يول قويىدۇ.</string>
+ <string name="permlab_modifyProtectedSmsList">قوغدالغان قىسقا ئۇچۇر تىزىمىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_modifyProtectedSmsList">ئەپنىڭ قوغدالغان قىسقا ئۇچۇر ئادرېسىنىڭ تىزىمىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permgrouplab_security">بىخەتەرلىك</string>
+ <string name="permgroupdesc_security">ئۈسكۈنە بىخەتەرلىك ئۇچۇرىغا مۇناسىۋەتلىك ھوقۇقلار.</string>
+ <string name="permlab_readPhoneBlacklist">تېلېفون قارا تىزىمىنى ئوقۇش</string>
+ <string name="permdesc_readPhoneBlacklist">ئەپنىڭ كەلگەن تېلېفون ياكى ئۇچۇرلارنىڭ چەكلەنگەن تېلېفون نومۇر ئۇچۇرلىرىنى ئوقۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_changePhoneBlacklist">تېلېفون قارا تىزىمىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_changePhoneBlacklist">كەلگەن تېلېفون ياكى ئۇچۇرنىڭ چەكلەنگەن نومۇر ئۇچۇرلىرىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_setKeyguardWallpaper">قۇلۇپ ئېكران تام قەغىزىنى تەڭشەيدۇ</string>
+ <string name="permdesc_setKeyguardWallpaper">ئەپنىڭ قۇلۇپ ئېكران تام قەغىزىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="global_action_reboot">قايتا قوزغات</string>
+ <string name="global_action_current_user">نۆۋەتتىكى</string>
+ <string name="reboot_reboot">قايتا قوزغات</string>
+ <string name="reboot_recovery">ئەسلىگە كەلتۈر</string>
+ <string name="reboot_bootloader">قوزغىتىش يۈكلىگۈچ</string>
+ <string name="reboot_download">چۈشۈر</string>
+ <string name="reboot_soft">يۇمشاق قايتا قوزغىتىش</string>
+ <string name="reboot_title">قايتا قوزغات</string>
+ <string name="reboot_confirm" product="tablet">تاختا كومپيۇتېرىڭىز قايتا قوزغىلىدۇ.</string>
+ <string name="reboot_confirm" product="default">تېلېفونىڭىز قايتا قوزغىلىدۇ.</string>
+ <string name="reboot_progress">قايتا قوزغىتىۋاتىدۇ\u2026</string>
+ <string name="app_killed_message">ئەپ ئاخىرلاشتۇرۇلدى</string>
+ <string name="adb_net_active_notification_title">تور ھالقىغان ADB قوزغىتىلدى</string>
+ <string name="adb_both_active_notification_title">USB ۋە تور ADB قوزغىتىلدى</string>
+ <string name="adb_active_generic_notification_message">چېكىلسە سازلاشنى چەكلەيدۇ.</string>
+ <string name="permlab_interceptPackageLaunch">ئەپ قوزغىتىشنى توسىدۇ</string>
+ <string name="stylus_app_not_installed">%s تېخى ئورنىتىلمىغان</string>
+ <string name="permlab_changePrivacyGuardState">شەخسىيەت قوغداشنى قوزغىتىدۇ ياكى چەكلەيدۇ</string>
+ <string name="permdesc_changePrivacyGuardState">ئەپنىڭ باشقا ئەپنى شەخسىيەت قوغداش ھالىتىدە ئىجرا قىلىشىغا يول قويىدۇ. ئەپ شەخسىيەت قوغداش ھالىتىدە ئىجرا قىلىنسا، ئۇ ئالاقەداشلار، چاقىرىش خاتىرىسى ياكى ئۇچۇرلارغا ئوخشاش شەخسىي سانلىق مەلۇماتلارنى زىيارەت قىلىش ھوقۇقى بولمايدۇ.</string>
+ <string name="privacy_guard_notification">شەخسىيەت قوغداش ئاكتىپ</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> شەخسىي سانلىق مەلۇماتلارنى زىيارەت قىلالمايدۇ</string>
+ <string name="privacy_guard_dialog_title">شەخسىيەت قوغداش</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> نىڭ قىلماقچى بولغىنى <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">تاللىشىمنى ئەستە تۇت</string>
+ <string name="app_ops_access_camera">كامېراغا ئېرىشىدۇ</string>
+ <string name="app_ops_access_location">ئورنىڭىزغا ئېرىشىدۇ</string>
+ <string name="app_ops_access_notifications">ئۇقتۇرۇشىڭىزنى ئوقۇيدۇ</string>
+ <string name="app_ops_activate_vpn">بىر VPN نى قوزغىتىدۇ</string>
+ <string name="app_ops_auto_start">قوزغالغاندا باشلا</string>
+ <string name="app_ops_delete_call_log">چاقىرىش خاتىرىڭىزنى ئۆچۈرىدۇ</string>
+ <string name="app_ops_delete_contacts">ئالاقەداشلىرىڭىزنى ئۆچۈرىدۇ</string>
+ <string name="app_ops_delete_mms">سىزنىڭ MMS ئۇچۇرلىرىڭىزنى ئۆچۈرىدۇ</string>
+ <string name="app_ops_delete_sms">سىزنىڭ قىسقا ئۇچۇرلىرىڭىزنى ئۆچۈرىدۇ</string>
+ <string name="app_ops_draw_on_top">كۆزنەكلەرنى ئۈستىدە كۆرسىتىدۇ</string>
+ <string name="app_ops_get_usage_stats">ئەپ ئىشلىتىش ئەھۋالىنىڭ ئىستاتىستىكىسىغا ئېرىشىدۇ</string>
+ <string name="app_ops_keep_device_awake">ئۈسكۈنىنى ئويغاق تۇتىدۇ</string>
+ <string name="app_ops_make_phone_call">تېلېفون نومۇر بۇرايدۇ</string>
+ <string name="app_ops_modify_calendar">يىلنامەڭىزنى يېڭىلايدۇ</string>
+ <string name="app_ops_modify_call_log">چاقىرىش خاتىرىڭىزنى يېڭىلايدۇ</string>
+ <string name="app_ops_modify_clipboard">چاپلاش تاختىسىنى ئۆزگەرتىدۇ</string>
+ <string name="app_ops_modify_contacts">ئالاقەداشلىرىڭىزنى يېڭىلايدۇ</string>
+ <string name="app_ops_modify_settings">سىستېما تەڭشەكلىرىنى يېڭىلايدۇ</string>
+ <string name="app_ops_mute_unmute_microphone">مىكروفون ئاۋازى ئۈنلۈك/ئۈنسىز</string>
+ <string name="app_ops_play_audio">ئۈن چال</string>
+ <string name="app_ops_post_notification">ئۇقتۇرۇش يوللايدۇ</string>
+ <string name="app_ops_project_media">ۋاسىتىنى قويىدۇ</string>
+ <string name="app_ops_read_calendar">يىلنامەڭىزنى ئوقۇيدۇ</string>
+ <string name="app_ops_read_call_log">چاقىرىش خاتىرىسىنى ئوقۇيدۇ</string>
+ <string name="app_ops_read_clipboard">چاپلاش تاختىسىنى ئوقۇيدۇ</string>
+ <string name="app_ops_read_contacts">ئالاقەداشلىرىڭىزنى ئوقۇيدۇ</string>
+ <string name="app_ops_read_mms">سىزنىڭ MMS ئۇچۇرلىرىڭىزنى ئوقۇيدۇ</string>
+ <string name="app_ops_read_sms">قىسقا ئۇچۇرلىرىڭىزنى ئوقۇيدۇ</string>
+ <string name="app_ops_receive_sms">قىسقا ئۇچۇرلارنى قوبۇللايدۇ</string>
+ <string name="app_ops_record_audio">ئۈنگە ئالىدۇ</string>
+ <string name="app_ops_send_mms">بىر MMS ئۇچۇرى يوللايدۇ</string>
+ <string name="app_ops_send_sms">بىر قىسقا ئۇچۇر يوللايدۇ</string>
+ <string name="app_ops_start_at_bootup">قوزغالغاندا باشلايدۇ</string>
+ <string name="app_ops_toast_window">قاڭقىش ئۇچۇرىنى كۆرسىتىدۇ</string>
+ <string name="app_ops_toggle_bluetooth">كۆكچىشنى ئاچ تاقا</string>
+ <string name="app_ops_toggle_nfc">NFC ئاچ تاقا</string>
+ <string name="app_ops_use_alarm_volume">قوڭغۇراق ئاۋازىنى تىزگىنلەيدۇ</string>
+ <string name="app_ops_use_audio_focus">ئاۋاز فوكۇسىنى تىزگىنلەيدۇ</string>
+ <string name="app_ops_use_bluetooth_volume">كۆكچىش ئاۋازىنى تىزگىنلەيدۇ</string>
+ <string name="app_ops_use_master_volume">ئاساسىي ئاۋازنى تىزگىنلەش</string>
+ <string name="app_ops_use_media_buttons">ۋاسىتە توپچىلىرىنى ئىشلەت</string>
+ <string name="app_ops_use_media_volume">ۋاسىتە ئاۋازىنى تىزگىنلەش</string>
+ <string name="app_ops_use_notification_volume">ئۇقتۇرۇش ئاۋازىنى تىزگىنلەش</string>
+ <string name="app_ops_use_ring_volume">قوڭغۇراق ئاۋازىنى تىزگىنلەش</string>
+ <string name="app_ops_use_vibrate">سېزىم ئىنكاسىنى ئىشلەت</string>
+ <string name="app_ops_use_voice_volume">ئاۋازلىق چاقىرىش ئاۋازىنى تىزگىنلە</string>
+ <string name="app_ops_write_mms">MMS ئۇچۇرى ياز</string>
+ <string name="app_ops_write_sms">SMS ئۇچۇر ياز</string>
+ <string name="app_ops_su">root ھوقۇقىغا ئېرىشىدۇ</string>
+ <string name="live_display_auto">ئاپتوماتىك</string>
+ <string name="live_display_auto_summary">كۈن چىققان ۋە كۈن پاتقاندىن كېيىن ئېكران رەڭ تېمپېراتورىسىنى ئۆزلۈكىدىن تەڭشەيدۇ</string>
+ <string name="live_display_off">تاقاق</string>
+ <string name="live_display_off_summary">بارلىق تەڭشەشلەرنى چەكلەيدۇ</string>
+ <string name="live_display_day">كۈندۈز</string>
+ <string name="live_display_day_summary">كۈندۈز تەڭشەكلىرىنىلا ئىشلىتىدۇ</string>
+ <string name="live_display_night">كېچە</string>
+ <string name="live_display_night_summary">كېچە تەڭشەكلىرىنىلا ئىشلىتىدۇ</string>
+ <string name="live_display_outdoor">تالا (قۇياش نۇرى)</string>
+ <string name="live_display_outdoor_summary">تالا تەڭشەكلىرىنىلا ئىشلىتىدۇ</string>
+ <string name="live_display_hint">LiveDisplay كۆزنىڭ چارچىشىنى يېنىكلىتىشكە ياردەم بېرىدۇ، كېچىدە ئۇخلىشىڭىزغا ياردەم بېرىدۇ. سىناش ئۈچۈن بۇ جاينى چېكىڭ!</string>
+ <string name="tethered_notification_no_device_message">باغلانغان ئۈسكۈنە يوق</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> ئۈسكۈنە باغلاندى</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> ئۈسكۈنە باغلاندى</string>
+</resources>
diff --git a/core/res/res/values-ug/strings.xml b/core/res/res/values-ug/strings.xml
new file mode 100644
index 0000000..768ccd5
--- /dev/null
+++ b/core/res/res/values-ug/strings.xml
@@ -0,0 +1,1147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="byteShort">B</string>
+ <string name="kilobyteShort">KB</string>
+ <string name="megabyteShort">MB</string>
+ <string name="gigabyteShort">GB</string>
+ <string name="terabyteShort">TB</string>
+ <string name="petabyteShort">PB</string>
+ <string name="untitled">&lt;ماۋزۇسىز&gt;</string>
+ <string name="emptyPhoneNumber">(تېلېفون نومۇرى يوق)</string>
+ <string name="defaultVoiceMailAlphaTag">ئۈنخەت</string>
+ <string name="defaultMsisdnAlphaTag">MSISDN1</string>
+ <string name="mmiError">باغلىنىشتا مەسىلە كۆرۈلدى ياكى MMI كودى خاتا.</string>
+ <string name="mmiFdnError">پەقەت مۇقىم نومۇرغىلا بۇ مەشغۇلاتنى ئىجرا قىلىدۇ.</string>
+ <string name="serviceEnabled">مۇلازىمەت قوزغىتىلدى.</string>
+ <string name="serviceEnabledFor">مۇلازىمەت تۆۋەندىكى تۈر ئۈچۈن قوزغىتىلدى:</string>
+ <string name="serviceDisabled">مۇلازىمەت چەكلەندى.</string>
+ <string name="serviceRegistered">خەتلەش مۇۋەپپەقىيەتلىك.</string>
+ <string name="serviceErased">مۇۋەپپەقىيەتلىك ئۆچۈردى.</string>
+ <string name="passwordIncorrect">ئىم خاتا.</string>
+ <string name="mmiComplete">MMI تاماملاندى.</string>
+ <string name="badPin">سىز كىرگۈزگەن كونا PIN خاتا.</string>
+ <string name="badPuk">سىز كىرگۈزگەن PUK خاتا.</string>
+ <string name="mismatchPin">سىز كىرگۈزگەن PIN ماس كەلمىدى.</string>
+ <string name="invalidPin">4-8 خانىلىق PIN نى كىرگۈزۈڭ.</string>
+ <string name="invalidPuk">8 خانە ۋە ئۇنىڭدىن كۆپ PUK2 نى كىرگۈزۈڭ.</string>
+ <string name="needPuk">SIM كارتا PUK نۇمۇرىدا قۇلۇپلانغان. ئېچىش ئۈچۈن PUK نۇمۇرىنى كىرگۈزۈڭ.</string>
+ <string name="needPuk2">SIM كارتىنى ئېچىش ئۈچۈن PUK2 نۇمۇرىنى كىرگۈزۈڭ.</string>
+ <string name="enablePin">مۇۋەپپەقىيەتلىك بولمىدى. SIM/RUIM قۇلۇپى قوزغىتىلدى.</string>
+ <string name="imei">IMEI</string>
+ <string name="meid">MEID</string>
+ <string name="ClipMmi">كەلگەن تېلېفون نومۇر</string>
+ <string name="ClirMmi">ئۇرۇلغان تېلېفون نومۇر</string>
+ <string name="CfMmi">كەلگەن تېلېفوننى ئۇلاپ يەتكۈزۈش</string>
+ <string name="CwMmi">چاقىرىشنى كۈتۈش</string>
+ <string name="BaMmi">چاقىرىشنى چەكلەش</string>
+ <string name="PwdMmi">ئىم ئۆزگەرتىش</string>
+ <string name="PinMmi">PIN ئۆزگەرت</string>
+ <string name="CnipMmi">كەلگەن نومۇرنى كۆرسىتىش</string>
+ <string name="CnirMmi">كەلگەن نومۇرنى كۆرسىتىشنى چەكلەش</string>
+ <string name="ThreeWCMmi">ئۈچ تەرەپ سۆزلىشىش</string>
+ <string name="RuacMmi">ئېلىشنى خالىمايدىغان تېلېفۇنلارنى ئۈزىۋېتىش</string>
+ <string name="CndMmi">چاقىرغان نومۇرنى يەتكۈزۈش</string>
+ <string name="DndMmi">ئاۋارە قىلماڭ</string>
+ <string name="CLIRDefaultOnNextCallOn">كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسەتمەيدۇ ئەمما كېيىنكى قېتىملىق سۆزلىشىشتە كۆرسىتىدۇ.</string>
+ <string name="CLIRDefaultOnNextCallOff">كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسەتمەيدۇ ئەمما كېيىنكى قېتىملىق سۆزلىشىشتە كۆرسەتمەيدۇ.</string>
+ <string name="CLIRDefaultOffNextCallOn">كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسىتىدۇ ئەمما كېيىنكى قېتىملىق سۆزلىشىشتە كۆرسەتمەيدۇ.</string>
+ <string name="CLIRDefaultOffNextCallOff">كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسىتىدۇ كېيىنكى قېتىملىق سۆزلىشىشتىمۇ كۆرسىتىدۇ.</string>
+ <string name="serviceNotProvisioned">مۇلازىمەت تەمىنلەنمىگەن</string>
+ <string name="CLIRPermanent">چاقىرغۇچى كىملىك تەڭشىكىنى ئۆزگەرتەلمەيسىز</string>
+ <string name="RestrictedChangedTitle">زىيارەت چەكلىمىسى ئۆزگەردى</string>
+ <string name="RestrictedOnData">سانلىق مەلۇمات مۇلازىمىتى چەكلەندى.</string>
+ <string name="RestrictedOnEmergency">جىددىي مۇلازىمەت چەكلەندى.</string>
+ <string name="RestrictedOnNormal">ئاۋاز مۇلازىمىتى چەكلەندى.</string>
+ <string name="RestrictedOnAllVoice">بارلىق ئاۋاز مۇلازىمىتى چەكلەندى.</string>
+ <string name="RestrictedOnSms">قىسقا ئۇچۇر مۇلازىمىتى توختىتىلدى.</string>
+ <string name="RestrictedOnVoiceData">ئاۋاز/سانلىق مەلۇمات مۇلازىمىتى توختىتىلدى.</string>
+ <string name="RestrictedOnVoiceSms">ئاۋاز/قىسقا ئۇچۇر مۇلازىمىتى توختىتىلدى.</string>
+ <string name="RestrictedOnAll">بارلىق ئاۋاز/سانلىق مەلۇمات/قىسقا ئۇچۇر مۇلازىمىتى توختىتىلدى.</string>
+ <string name="serviceClassVoice">ئاۋاز</string>
+ <string name="serviceClassData">سانلىق مەلۇمات</string>
+ <string name="serviceClassFAX">فاكس</string>
+ <string name="serviceClassSMS">قىسقا ئۇچۇر</string>
+ <string name="serviceClassDataAsync">قەدەمداشسىز</string>
+ <string name="serviceClassDataSync">قەدەمداش</string>
+ <string name="serviceClassPacket">بوغچا</string>
+ <string name="serviceClassPAD">PAD</string>
+ <string name="roamingText0">كەزمە كۆرسەتكۈچ ئوچۇق</string>
+ <string name="roamingText1">كەزمە كۆرسەتكۈچ تاقاق</string>
+ <string name="roamingText2">كەزمە كۆرسەتكۈچ چاقناۋاتىدۇ</string>
+ <string name="roamingText3">يېقىن ئەتراپ سىرتىدا</string>
+ <string name="roamingText4">بىنا سىرتىدا</string>
+ <string name="roamingText5">كەزمە - مايىللىق سىستېما</string>
+ <string name="roamingText6">كەزمە - ئىشلىتىلىشچان سىستېما</string>
+ <string name="roamingText7">كەزمە - ئىتتىپاقداش ھەمكارلاشقۇچىلار</string>
+ <string name="roamingText8">كەزمە - ئالىي ھەمكارلاشقۇچىلار</string>
+ <string name="roamingText9">كەزمە - تولۇق مۇلازىمەت ئىقتىدارى</string>
+ <string name="roamingText10">كەزمە - قىسمەن مۇلازىمەت ئىقتىدارى</string>
+ <string name="roamingText11">كەزمە لەۋھە ئوچۇق</string>
+ <string name="roamingText12">كەزمە لەۋھە تاقاق</string>
+ <string name="roamingTextSearching">مۇلازىمەت ئىزدەۋاتىدۇ</string>
+ <string name="cfTemplateNotForwarded"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:ئۇلاپ يۆتكىيەلمىدى</string>
+ <string name="cfTemplateForwarded"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g></string>
+ <string name="cfTemplateForwardedTime"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> دىن <xliff:g id="TIME_DELAY">{2}</xliff:g> سېكۇنت كېيىن</string>
+ <string name="cfTemplateRegistered"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:ئۇلاپ يۆتكىيەلمىدى</string>
+ <string name="cfTemplateRegisteredTime"><xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:ئۇلاپ يۆتكىيەلمىدى</string>
+ <string name="fcComplete">ئىقتىدار كودى تاماملاندى.</string>
+ <string name="fcError">باغلىنىشتا مەسىلە كۆرۈلدى ياكى ئىقتىدار كودى ئىناۋەتسىز.</string>
+ <string name="httpErrorOk">جەزملە</string>
+ <string name="httpError">تور خاتالىقى كۆرۈلدى.</string>
+ <string name="httpErrorLookup">بۇ تور ئادرېسىنى تاپالمىدى.</string>
+ <string name="httpErrorUnsupportedAuthScheme">بۇ تور بېكەتنىڭ سالاھىيەت دەلىللەش لايىھەسىنى قوللىمايدۇ.</string>
+ <string name="httpErrorAuth">سالاھىيەت دەلىللىيەلمەيدۇ.</string>
+ <string name="httpErrorProxyAuth">ۋاكالەتچى مۇلازىمېتىر ئارقىلىق سالاھىيەت دەلىللەش مەغلۇپ بولدى.</string>
+ <string name="httpErrorConnect">مۇلازىمېتىرغا باغلىنالمىدى . </string>
+ <string name="httpErrorIO">مۇلازىمىتىر بىلەن ئالاقە قىلالمىدى. سەل تۇرۇپ قايتا سىناڭ.</string>
+ <string name="httpErrorTimeout">مۇلازىمىتىرغا ئۇلىنىش مۆھلىتى ئېشىپ كەتتى.</string>
+ <string name="httpErrorRedirectLoop">بۇ بەتتە نۇرغۇنلىغان مۇلازىمېتىر قايتا نىشانلاش بار.</string>
+ <string name="httpErrorUnsupportedScheme">بۇ كېلىشىمنى قوللىمايدۇ.</string>
+ <string name="httpErrorFailedSslHandshake">بىخەتەر باغلىنىش قۇرالمايدۇ.</string>
+ <string name="httpErrorBadUrl">تور بەتنى ئاچالمايدۇ چۈنكى تور ئادرېس ئىناۋەتسىز.</string>
+ <string name="httpErrorFile">بۇ ھۆججەتنى زىيارەت قىلالمايدۇ.</string>
+ <string name="httpErrorFileNotFound">ئىلتىماس قىلغان ھۆججەتنى تاپالمىدى.</string>
+ <string name="httpErrorTooManyRequests">بىر تەرەپ قىلىۋاتقان ئىلتىماس بەك كۆپ. سەل تۇرۇپ قايتا سىناڭ.</string>
+ <string name="notification_title"><xliff:g id="ACCOUNT">%1$s</xliff:g> نىڭ تىزىمغا كىرىش خاتالىقى</string>
+ <string name="contentServiceSync">قەدەمداش</string>
+ <string name="contentServiceSyncNotificationTitle">قەدەمداش</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc">نۇرغۇن <xliff:g id="CONTENT_TYPE">%s</xliff:g> ئۆچۈرۈش.</string>
+ <string name="low_memory" product="tablet">تاختا كومپيۇتېر ساقلىغۇچىسى توشتى. بەزى ھۆججەتلەرنى ئۆچۈرۈپ بوشلۇق بىكارلاڭ.</string>
+ <string name="low_memory" product="default">تېلېفون ساقلىغۇچىسى توشتى. بەزى ھۆججەتلەرنى ئۆچۈرۈپ بوشلۇق بىكارلاڭ.</string>
+ <string name="ssl_ca_cert_warning">تور نازارەت قىلىنغان بولۇشى مۇمكىن</string>
+ <string name="ssl_ca_cert_noti_by_unknown">يوچۇن ئۈچىنچى تەرەپنىڭ نازارىتىدە</string>
+ <string name="ssl_ca_cert_noti_managed"><xliff:g id="MANAGING_DOMAIN">%s</xliff:g> نازارىتىدە</string>
+ <string name="me">مەن</string>
+ <string name="power_dialog" product="tablet">تاختا كومپيۇتېر تاللانمىلار</string>
+ <string name="power_dialog" product="default">تېلېفون تاللانما</string>
+ <string name="silent_mode">ئۈنسىز ھالەت</string>
+ <string name="turn_on_radio">سىمسىز تورنى ئاچ</string>
+ <string name="turn_off_radio">سىمسىز تورنى تاقا</string>
+ <string name="screen_lock">ئېكران قۇلۇپلا</string>
+ <string name="power_off">تاقا</string>
+ <string name="silent_mode_silent">قوڭغۇراق تاقاق</string>
+ <string name="silent_mode_vibrate">قوڭغۇراق تىترەت</string>
+ <string name="silent_mode_ring">قوڭغۇراق ئوچۇق</string>
+ <string name="shutdown_progress">تاقاۋاتىدۇ…</string>
+ <string name="shutdown_confirm" product="tablet">تاختا كومپيۇتېرىڭىز تاقىلىدۇ.</string>
+ <string name="shutdown_confirm" product="default">تېلېفونىڭىز تاقىلىدۇ.</string>
+ <string name="shutdown_confirm_question">تاقامسىز؟</string>
+ <string name="reboot_safemode_title">قايتا قوزغىتىپ بىخەتەر ھالەتكە كىرىدۇ</string>
+ <string name="reboot_safemode_confirm">قايتا قوزغىتىپ بىخەتەر ھالەتكە كىرەمسىز؟ بۇنداق بولغاندا سىز ئورناتقان ئۈچىنچى تەرەپ ئەپلەر توختىتىلىدۇ. قايتا قوزغاتسىڭىز ئاندىن بۇ ئەپلەر ئەسلىگە كېلىدۇ.</string>
+ <string name="recent_tasks_title">يېقىنقى</string>
+ <string name="no_recent_tasks">يېقىنقى ئەپلەر يوق</string>
+ <string name="global_actions" product="tablet">تاختا كومپيۇتېر تاللانمىلار</string>
+ <string name="global_actions" product="default">تېلېفون تاللانما</string>
+ <string name="global_action_lock">ئېكران قۇلۇپلا</string>
+ <string name="global_action_power_off">تاقا</string>
+ <string name="global_action_bug_report">خاتالىق دوكلاتى</string>
+ <string name="bugreport_title">خاتالىق دوكلاتى يوللاش</string>
+ <string name="bugreport_message">نۆۋەتتىكى ئۈسكۈنىڭىزنىڭ ھالىتىگە ئائىت ئۇچۇرلارنى توپلاپ، تورخەت ئۇچۇرى يوللايدۇ. يوللاشقا لازىملىق خاتالىق دوكلاتىنى قوزغىتىپ تەييارلاشقا بىر ئاز ۋاقىت كېتىشى مۇمكىن. سەۋرىچانلىق بىلەن كۈتۈڭ.</string>
+ <string name="global_action_toggle_silent_mode">ئۈنسىز ھالەت</string>
+ <string name="global_action_silent_mode_on_status">ئاۋاز تاقاق</string>
+ <string name="global_action_silent_mode_off_status">ئاۋاز ئوچۇق</string>
+ <string name="global_actions_toggle_airplane_mode">ئايروپىلان ھالىتى</string>
+ <string name="global_actions_airplane_mode_on_status">ئايروپىلان ھالىتى ئوچۇق</string>
+ <string name="global_actions_airplane_mode_off_status">ئايروپىلان ھالىتى تاقاق</string>
+ <string name="status_bar_notification_info_overflow">999+</string>
+ <string name="safeMode">بىخەتەر ھالەت</string>
+ <string name="android_system_label">Android سىستېما</string>
+ <string name="permgrouplab_calendar">يىلنامە</string>
+ <string name="permgrouplab_sms">قىسقا ئۇچۇر</string>
+ <string name="permgrouplab_storage">ساقلىغۇچ</string>
+ <string name="permgrouplab_microphone">مىكروفون</string>
+ <string name="permgroupdesc_microphone">ئاۋاز ئېلىش</string>
+ <string name="permgrouplab_camera">كامېرا</string>
+ <string name="permgrouplab_phone">تېلېفون</string>
+ <string name="capability_title_canRetrieveWindowContent">كۆزنەك مەزمۇنىنى ئىزدەيدۇ</string>
+ <string name="capability_desc_canRetrieveWindowContent">سىز ئۆزئارا تەسىرلىشىۋاتقان كۆزنەكنىڭ مەزمۇنىنى تەكشۈرىدۇ.</string>
+ <string name="capability_title_canRequestTouchExploration">چېكىلگەندىكى كۆرگۈنى قوزغىتىدۇ</string>
+ <string name="capability_desc_canRequestTouchExploration">ئۈسكۈنە ئىشلەتكۈچى چەككەندىكى مەزمۇننى ئۈنلۈك ئوقۇيالايدۇ، ئىشلەتكۈچى قول ئىشارىتى ئارقىلىق ئېكرانغا كۆز يۈگۈرتەلەيدۇ.</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility">تور بەت قوشۇمچە كۈچەيتىلگەن ئىقتىدارنى ئاچ</string>
+ <string name="capability_desc_canRequestEnhancedWebAccessibility">ئەپ مەزمۇنىنى زىيارەت قىلىشقا قولايلىق بولۇشى ئۈچۈن قوليازما ئورنىتىدۇ.</string>
+ <string name="capability_title_canRequestFilterKeyEvents">كىرگۈزگەن تېكىستىڭىزنى كۆزىتىدۇ</string>
+ <string name="capability_desc_canRequestFilterKeyEvents">ئىناۋەتلىك كارتا نومۇرى ۋە ئىمغا ئوخشاش شەخسىي ئۇچۇرلارنىمۇ ئۆز ئىچىگە ئالىدۇ.</string>
+ <string name="permlab_statusBar">ھالەت بالداقنى چەكلەش ياكى ئۆزگەرتىش.</string>
+ <string name="permdesc_statusBar">ئەپنىڭ ھالەت بالداقنى چەكلىشىگە ياكى سىستېما سىنبەلگىسىنى قوشۇش ۋە ئۆچۈرۈشىگە يول قويىدۇ.</string>
+ <string name="permlab_statusBarService">ھالەت بالداق</string>
+ <string name="permdesc_statusBarService">ئەپنىڭ ھالەت بالداقتا تۇرۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_expandStatusBar">ھالەت بالداقنى يايىدۇ/قاتلايدۇ</string>
+ <string name="permdesc_expandStatusBar">ئەپنىڭ ھالەت بالداقنى يېيىش ياكى قاتلىشىغا يول قويىدۇ.</string>
+ <string name="permlab_install_shortcut">قىسقا يول ئورنىتىش</string>
+ <string name="permdesc_install_shortcut">ئەپنىڭ ئىشلەتكۈچى ئارىلاشمىغان ئەھۋالدا قىسقا يول قۇرۇشقا يول قويىدۇ.</string>
+ <string name="permlab_uninstall_shortcut">قىسقا يول ئۆچۈر</string>
+ <string name="permdesc_uninstall_shortcut">ئەپنىڭ ئىشلەتكۈچى ئارىلاشمىغان ئەھۋالدا قىسقا يولنى ئۆچۈرۈشىگە يول قويىدۇ.</string>
+ <string name="permlab_processOutgoingCalls">سىرتقا نومۇر بۇراشنى قايتا تەڭشەيدۇ</string>
+ <string name="permdesc_processOutgoingCalls">ئەپنىڭ ئۇرۇلغان تېلېفۇننى بىر تەرەپ قىلىش ۋە نۇمۇرنى ئۆزگەرتىپ ئۇرۇشىغا يول قويىدۇ. بۇ ھوقۇق ئەپنىڭ ئۇرۇلغان تېلېفۇننى كۆزىتىشى، قايتا ئۇرۇشى ھەتتا چەكلەپ قۇيۇشىغا يول قويۇشى مۇمكىن.</string>
+ <string name="permlab_receiveSms">قىسقا ئۇچۇر (SMS) قوبۇللايدۇ</string>
+ <string name="permdesc_receiveSms">ئەپنىڭ ئۇچۇر قۇبۇل قىلىشى ۋە بىر تەرەپ قىلىشىغا يول قويىدۇ. بۇ ئىقتىداردا ئەپلەر ئۇچۇرلىرىڭىزنى نازارەت قىلىشى ياكى سىزگە كۆرسەتمەي ئۆچۈرۈۋېتىشى مۇمكىن.</string>
+ <string name="permlab_receiveMms">قىسقا ئۇچۇر (MMS) قوبۇللايدۇ</string>
+ <string name="permdesc_receiveMms">ئەپنىڭ كۆپ ۋاستە ئۇچۇر (MMS) قۇبۇل قىلىشى ۋە بىر تەرەپ قىلىشىغا يول قويىدۇ. بۇ ئىقتىداردا ئەپلەر ئۇچۇرلىرىڭىزنى نازارەت قىلىشى ياكى سىزگە كۆرسەتمەي ئۆچۈرۈۋېتىشى مۇمكىن.</string>
+ <string name="permlab_readCellBroadcasts">ئىجتىمائى رايون تارقاتقان ئۇچۇرلارنى ئوقۇيدۇ</string>
+ <string name="permlab_subscribedFeedsRead">مۇشتەرى بولغان خەۋەر بېتىنى ئوقۇيدۇ</string>
+ <string name="permdesc_subscribedFeedsRead">ئەپنىڭ نۆۋەتتە قەدەمداشلانغان خەۋەر بېتىگە مۇناسىۋەتلىك تەپسىلىي ئۇچۇرىنى ئوقۇشىغا يول قويىدۇ.</string>
+ <string name="permdesc_sendSms">ئەپنىڭ ئۇچۇر يوللىشىغا يول قويىدۇ. زەھەرخەندە ئەپلەر رۇخسىتىڭىزسىز ئۇچۇر يوللاپ، سىزنى چىقىم قىلدۇرىدۇ.</string>
+ <string name="permlab_readSms">تېكىست ئۇچۇرىڭىزنى ئوقۇيدۇ (قىسقا ئۇچۇر ياكى كۆپ ۋاستە ئۇچۇر)</string>
+ <string name="permdesc_readSms" product="tablet">ئەپنىڭ تاختا كومپيۇتېر ياكى SIM كارتىدىكى ئۇچۇرلارنى ئۇقۇشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ بارلىق قىسقا ئۇچۇرلارنى ئوقۇۋالالايدۇ، قىسقا ئۇچۇر مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ.</string>
+ <string name="permdesc_readSms" product="default">ئەپنىڭ تېلېفون ياكى SIM كارتىدىكى ئۇچۇرلارنى ئۇقۇشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ بارلىق قىسقا ئۇچۇرلارنى ئوقۇۋالالايدۇ، قىسقا ئۇچۇر مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ.</string>
+ <string name="permlab_receiveWapPush">تېكىست ئۇچۇر قوبۇللايدۇ (WAP)</string>
+ <string name="permdesc_receiveWapPush">ئەپنىڭ WAP ئۇچۇر قۇبۇل قىلىشى ۋە بىر تەرەپ قىلىشىغا يول قويىدۇ. بۇ ئىقتىداردا ئەپلەر ئۇچۇرلىرىڭىزنى نازارەت قىلىشى ياكى سىزگە كۆرسەتمەي ئۆچۈرۈۋېتىشى مۇمكىن.</string>
+ <string name="permlab_getTasks">ئىجرا قىلىنىۋاتقان ئەپلەرنى ئىزدەيدۇ</string>
+ <string name="permdesc_getTasks">ئەپنىڭ نۆۋەتتىكى ۋە يىقىنقى ئىجرا قىلىنغان ۋەزىپە ئۇچۇرلىرىنى ئىزدىشىگە يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ بۇ ئۈسكۈنىدە قانداق ئەپلەرنىڭ ئىشلىتىلگەنلىكى ھەققىدىكى ئۇچۇرلارنى بىلەلەيدۇ.</string>
+ <string name="permlab_reorderTasks">ئىجرا قىلىنىۋاتقان پىروگراممىلارنى قايتا تەرتىپلەيدۇ</string>
+ <string name="permdesc_reorderTasks">ئەپنىڭ ۋەزىپىنى ئالدى سۇپا ياكى ئارقا سۇپىغا يۆتكىشىگە يول قويىدۇ. بۇ ئەپ سىزدىن بىسوراق مەشغۇلاتنى ئۆز ئالدىغا ئىجرا قىلىدۇ.</string>
+ <string name="permlab_enableCarMode">ماشىنىدا يۈرۈش ھالىتىنى قوزغىتىدۇ</string>
+ <string name="permdesc_enableCarMode">ئەپنىڭ ماشىنىدا يۈرۈش ھالىتىنى قوزغىتىشىغا يول قويىدۇ.</string>
+ <string name="permlab_killBackgroundProcesses">باشقا ئەپلەرنى تاقايدۇ</string>
+ <string name="permdesc_killBackgroundProcesses">ئەپنىڭ ئارقا سۇپىدا ئىجرا قىلىنىۋاتقان باشقا ئەپلەرنى ئاخىرلاشتۇرۇشىغا يول قويىدۇ. بۇ ھوقۇق باشقا ئەپلەرنىڭ ئىجرا قىلىنىشىنى توختىتىشنى كەلتۈرۈپ چىقىرىدۇ.</string>
+ <string name="permlab_systemAlertWindow">باشقا ئەپلەرنىڭ ئۈستىدە كۆرسىتىدىغان مەزمۇن</string>
+ <string name="permdesc_systemAlertWindow">بۇ ئەپنىڭ باشقا ئەپنىڭ ئۈستىدە ياكى ئىشلەتكۈچى ئارايۈزىنىڭ مۇئەييەن بۆلىكىگە سىزىشىغا يول قويىدۇ. بۇنداق بولغاندا بارلىق ئەپلەرنىڭ ئارايۈزىگە كاشىلا قىلىشى ياكى سىز باشقا ئەپلەردە كۆرگەن مەزمۇن ئۆزگىرىپ كېتىشى مۇمكىن.</string>
+ <string name="permlab_persistentActivity">ئەپنى ھەمىشە ئىجرا قىلدۇرىدۇ</string>
+ <string name="permdesc_persistentActivity" product="tablet">ئەپنىڭ مەلۇم بۆلىكىنىڭ ئەسلەكتە داۋاملىق ئىجرا قىلىنىشىغا يول قويىدۇ. بۇنداق بولغاندا باشقا ئەپلەر ئىشلىتىدىغان ئەسلەكنى چەكلەپ، تاختا كومپيۇتېرنىڭ ئىجرا قىلىش سۈرئىتىنى ئاستىلىتىۋېتىدۇ.</string>
+ <string name="permdesc_persistentActivity" product="default">ئەپنىڭ مەلۇم بۆلىكىنىڭ ئەسلەكتە داۋاملىق ئىجرا قىلىنىشىغا يول قويىدۇ. بۇنداق بولغاندا باشقا ئەپلەر ئىشلىتىدىغان ئەسلەكنى چەكلەپ، تېلېفوننىڭ ئىجرا قىلىش سۈرئىتىنى ئاستىلىتىۋېتىدۇ.</string>
+ <string name="permlab_getPackageSize">ئەپنىڭ ساقلاش بوشلۇقىنى ھىسابلايدۇ</string>
+ <string name="permdesc_getPackageSize">ئەپنىڭ ئۆزىنىڭ كودى، سانلىق مەلۇماتى ۋە غەملەك بوشلۇقىنى ئىزدىشىگە يول قويىدۇ.</string>
+ <string name="permlab_writeSettings">سىستېما تەڭشەكلىرىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_writeSettings">ئەپنىڭ سىستېما تەڭشەك سانلىق مەلۇماتىنى ئۆزگەرتىشىگە يول قويىدۇ. زەھەرخەندە ئەپلەر بۇ ئارقىلىق سىستىما سەپلىمىڭىزنى بۇزىدۇ.</string>
+ <string name="permlab_receiveBootCompleted">قوزغالغاندا ئىجرا قىلىدۇ</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet">ئەپنىڭ سىستېما قوزغىتىلغاندا ئاپتۇماتىك قوزغىلىشىغا يول قويىدۇ. بۇنداق بولغاندا تاختا كومپيۇتېر قوزغىلىش ۋاقتى ئۇزىراپ كېتىدۇ، ئەپ ئوچۇق تۇرغاندا تاختا كومپيۇتېر سۈرئىتىگىمۇ تەسىر يىتىدۇ.</string>
+ <string name="permdesc_receiveBootCompleted" product="default">ئەپنىڭ سىستېما قوزغىتىلغاندا ئاپتۇماتىك قوزغىلىشىغا يول قويىدۇ. بۇنداق بولغاندا تېلېفون قوزغىلىش ۋاقتى ئۇزىراپ كېتىدۇ، ئەپ ئوچۇق تۇرغاندا تېلېفون سۈرئىتىگىمۇ تەسىر يىتىدۇ.</string>
+ <string name="permlab_broadcastSticky">مۇقىم ئاڭلىتىشنى يوللايدۇ</string>
+ <string name="permdesc_broadcastSticky" product="tablet">ئەپنىڭ ئاڭلىتىش تۈگىگەندىن كېيىنمۇ ساقلىنىپ قالىدىغان مۇقىم ئاڭلىتىشنى يوللىشىغا يول قويىدۇ. بۇ ئىقتىدارنى كۆپ ئىشلەتكەندە ئەسلەكنى كۆپ ئىگىلىۋېلىپ تاختا كومپيۇتېر سۈرئىتىنى ئاستىلىتىۋېتىدۇ ياكى مۇقىملىقىنى تۆۋەنلىۋېتىدۇ.</string>
+ <string name="permdesc_broadcastSticky" product="default">ئەپنىڭ ئاڭلىتىش تۈگىگەندىن كېيىنمۇ ساقلىنىپ قالىدىغان مۇقىم ئاڭلىتىشنى يوللىشىغا يول قويىدۇ. بۇ ئىقتىدارنى كۆپ ئىشلەتكەندە ئەسلەكنى كۆپ ئىگىلىۋېلىپ تېلېفون سۈرئىتىنى ئاستىلىتىۋېتىدۇ ياكى مۇقىملىقىنى تۆۋەنلىۋېتىدۇ.</string>
+ <string name="permlab_readContacts">ئالاقەداشلىرىڭىزنى ئوقۇيدۇ</string>
+ <string name="permdesc_readContacts" product="tablet">ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئوقۇشىغا يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا ئالاقەداش سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن.\"</string>
+ <string name="permdesc_readContacts" product="default">ئەپنىڭ تېلېفوندا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئوقۇشىغا يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا ئالاقەداش سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن.</string>
+ <string name="permlab_writeContacts">ئالاقەداشلىرىڭىزنى تەھرىرلەيدۇ</string>
+ <string name="permdesc_writeContacts" product="tablet">ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئۆزگەرتىشىگە يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ئۆچۈرۈۋېتەلەيدۇ.</string>
+ <string name="permdesc_writeContacts" product="default">ئەپنىڭ تېلېفوندا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئۆزگەرتىشىگە يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ئۆچۈرۈۋېتەلەيدۇ.</string>
+ <string name="permlab_readCallLog">چاقىرىش خاتىرىسىنى ئوقۇيدۇ</string>
+ <string name="permdesc_readCallLog" product="tablet">ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان چاقىرىش خاتىرىسىنى ئوقۇشىغا يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر چاقىرىش خاتىرىسى سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن.</string>
+ <string name="permdesc_readCallLog" product="default">ئەپنىڭ تېلېفوندا ساقلانغان چاقىرىش خاتىرىسىنى ئوقۇشىغا يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر چاقىرىش خاتىرىسى سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن.</string>
+ <string name="permlab_writeCallLog">چاقىرىش خاتىرىسىنى يازىدۇ</string>
+ <string name="permdesc_writeCallLog" product="tablet">ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان چاقىرىش خاتىرىسىنى ئۆزگەرتىشىگە يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ئۆزگەرتىۋېتىشى مۇمكىن.</string>
+ <string name="permdesc_writeCallLog" product="default">ئەپنىڭ تېلېفوندا ساقلانغان چاقىرىش خاتىرىسىنى ئۆزگەرتىشىگە يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ئۆزگەرتىۋېتىشى مۇمكىن.</string>
+ <string name="permlab_readCalendar">يىلنامەدىكى پائالىيەت ۋە مەخپىي ئۇچۇرلارنى ئوقۇيدۇ</string>
+ <string name="permdesc_readCalendar" product="tablet">ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان يىلنامەدىكى پائالىيەت ئۇچۇرلىرىنى ئۇقۇشىغا يول قويىدۇ، دوست ياكى ئىشداشلىرىڭىزنىڭ پائالىيەتلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ يىنامە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىرلەپ ياكى ساقلىيالايدۇ، بۇ ئۇچۇرلار مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ.</string>
+ <string name="permdesc_readCalendar" product="default">ئەپنىڭ تېلېفوندا ساقلانغان يىلنامەدىكى پائالىيەت ئۇچۇرلىرىنى ئۇقۇشىغا يول قويىدۇ، دوست ياكى ئىشداشلىرىڭىزنىڭ پائالىيەتلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ يىنامە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىرلەپ ياكى ساقلىيالايدۇ، بۇ ئۇچۇرلار مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ.</string>
+ <string name="permlab_writeCalendar">يىلنامەدىكى پائالىيەتلىرىڭىزنى قوشۇپ ئۆزگەرتىدۇ ھەمدە ئىگىسى خەۋەرسىز ئەھۋالدا قارشى تەرەپنىڭ تورخەت يوللىشىنى ئىلتىماس قىلىدۇ.</string>
+ <string name="permlab_accessLocationExtraCommands">زىيادە ئورۇن ئۇچۇرىغا ئېرىشىش پىروگرامما بۇيرۇق زىيارىتى</string>
+ <string name="permlab_accessFineLocation">دەل ئورنى (GPS ۋە تور ئاساسىدا)</string>
+ <string name="permdesc_accessFineLocation">ئەپنىڭ يەرشارى ئورۇن بەلگىلەش سىستېمىسى (GPS) ياكى تارقىتىش مۇنارى ۋە Wi-Fi غا ئوخشاش تور ئورنى ئۇچۇر مەنبەسى ئارقىلىق دەل ئورنىڭىزنىڭ ئۇچۇرىغا ئېرىشىشىگە يول قويىدۇ. ئۈسكۈنىدە ئورۇن مۇلازىمىتىنى قوزغاتسىڭىز ئاندىن ئەپ سىزنىڭ ئورۇن ئۇچۇرىڭىزغا ئېرىشەلەيدۇ. ئەپ بۇ خىل مۇلازىمەت ئارقىلىق دەل ئورنىڭىزنى جەزملەيدۇ، بۇنداق بولغاندا ئەپ تېخىمۇ كۆپ توك سەرپ قىلىشى مۇمكىن.</string>
+ <string name="permlab_accessCoarseLocation">تەخمىنىي ئورنى(تور ئاساسىدا) </string>
+ <string name="permdesc_accessCoarseLocation">ئەپنىڭ تارقىتىش مۇنارى ۋە Wi-Fi غا ئوخشاش تور ئورنى ئۇچۇر مەنبەسى ئارقىلىق تەخمىنىي ئورنىڭىزنىڭ ئۇچۇرىغا ئېرىشىشىگە يول قويىدۇ. ئۈسكۈنىدە ئورۇن مۇلازىمىتىنى قوزغاتسىڭىز ئاندىن ئەپ سىزنىڭ ئورۇن ئۇچۇرىڭىزغا ئېرىشەلەيدۇ. ئەپ بۇ خىل مۇلازىمەت ئارقىلىق تەخمىنىي ئورنىڭىزنى جەزملەيدۇ، بۇنداق بولغاندا ئەپ تېخىمۇ كۆپ توك سەرپ قىلىشى مۇمكىن.</string>
+ <string name="permlab_modifyAudioSettings">ئاۋاز تەڭشىكىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_modifyAudioSettings">ئەپنىڭ سىستېمىنىڭ ئاۋاز كۈچى، ئاۋاز چىقىرىدىغان ياڭراتقۇ قاتارلىق بارلىق ئومۇمىيەت ئاۋاز تەڭشىكىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_recordAudio">ئاۋاز ئېلىش</string>
+ <string name="permdesc_recordAudio">ئەپنىڭ مىكروفون ئارقىلىق ئاۋاز ئېلىشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ سىز جەزملىمەي تۇرۇپلا خالىغان ۋاقىتتا ئاۋاز ئالالايدۇ.</string>
+ <string name="permlab_camera">رەسىم تارتىپ ۋە سىنغا ئالىدۇ</string>
+ <string name="permdesc_camera">ئەپنىڭ كامېرا ئارقىلىق رەسىم تارتىشى ۋە سىنغا ئېلىشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ سىز جەزملىمەي تۇرۇپلا خالىغان ۋاقىتتا كامېرانى ئىشلىتەلەيدۇ.</string>
+ <string name="permlab_vibrate">تىترەتكۈچ تىزگىنى</string>
+ <string name="permdesc_vibrate">ئەپنىڭ تىترەتكۈچنى باشقۇرۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_flashlight">چاقماق چىراغ باشقۇرۇش</string>
+ <string name="permdesc_flashlight">ئەپنىڭ چاقماق چىراغ باشقۇرۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_callPhone">تېلېفون نۇمۇرىنى بىۋاستە بۇرايدۇ</string>
+ <string name="permdesc_callPhone">ئەپنىڭ سىزنىڭ ۋاسىتىڭىزسىز تېلېفون ئۇرۇشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ تېلېفون ئۇرۇشى ياكى تېلېفون ھەققىڭىزنى ئاشۇرۇۋېتىشى مۇمكىن. دىققەت: بۇ ھوقۇق پىروگراممىنىڭ جىددى قۇتقۇزۇش تېلېفۇنى ئۇرۇشىغا رۇخسەت قىلمايدۇ. زەھەرخەندە ئەپلەر سىز جەزملىمەي تۇرۇپمۇ تېلېفون ئۇرۇش ئارقىلىق مۇناسىپ ھەق كەلتۈرۈپ چىقىرىدۇ.</string>
+ <string name="permlab_readPhoneState">تېلېفوننىڭ ھالىتى ۋە سالاھىيىتىنى ئوقۇيدۇ</string>
+ <string name="permdesc_readPhoneState">ئەپنىڭ ئۈسكۈنىنىڭ تېلېفون ئىقتىدارىنى زىيارەت قىلىشىغا يول قويىدۇ. ئەپ تېلېفوننىڭ نۇمۇرىنى، رەت نۇمۇرىنى، تېلېفوننىڭ سۆزلىشىشۋاتقانلىقىنى، قارشى تەرەپنىڭ نۇمۇرىنى جەزملەش ھوقۇقى بولىدۇ. </string>
+ <string name="permlab_wakeLock" product="tablet">تاختا كومپيۇتېرنى ئۇيقۇ ھالىتىدىن چەكلەيدۇ</string>
+ <string name="permlab_wakeLock" product="default">تېلېفوننى ئۇيقۇ ھالىتىدىن چەكلەيدۇ</string>
+ <string name="permdesc_wakeLock" product="tablet">ئەپنىڭ تاختا كومپيۇتېرنىڭ ئۇيقۇ ھالىتىگە كىرىشىنى چەكلىشىگە يول قويىدۇ.</string>
+ <string name="permdesc_wakeLock" product="default">ئەپنىڭ تېلېفوننىڭ ئۇيقۇ ھالىتىگە كىرىشىنى چەكلىشىگە يول قويىدۇ.</string>
+ <string name="permlab_transmitIr">ئىنفرا قىزىل نۇر تارقىتىدۇ</string>
+ <string name="permdesc_transmitIr" product="tablet">ئەپنىڭ تاختا كومپيۇتېرنىڭ ئىنفرا قىزىل نۇرلۇق تارقاتقۇچىسىنى ئىشلىتىشىگە يول قويىدۇ.</string>
+ <string name="permdesc_transmitIr" product="default">ئەپنىڭ تېلېفوننىڭ ئىنفرا قىزىل نۇرلۇق تارقاتقۇچىسىنى ئىشلىتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_setWallpaper">تام قەغەز تەڭشىكى</string>
+ <string name="permdesc_setWallpaper">ئەپنىڭ سىستېما تام قەغەزنى تەڭشىشىگە يول قويىدۇ.</string>
+ <string name="permlab_setWallpaperHints">تام قەغەز چوڭلۇقىنى تەڭشەيدۇ</string>
+ <string name="permdesc_setWallpaperHints">ئەپنىڭ تام قەغەزنىڭ چوڭ-كىچىكلىكىنىڭ ئەسكەرتىشىنى تەڭشىشىگە يول قويىدۇ.</string>
+ <string name="permlab_setTimeZone">ۋاقىت رايون تەڭشىكى</string>
+ <string name="permdesc_setTimeZone" product="tablet">ئەپنىڭ تاختا كومپيۇتېر ۋاقىت رايونىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permdesc_setTimeZone" product="default">ئەپنىڭ تېلېفون ۋاقىت رايونىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_getAccounts">ئۈسكۈنىدىكى ھېساباتنى ئىزدەيدۇ</string>
+ <string name="permdesc_getAccounts" product="tablet">ئەپنىڭ تاختا كومپيۇتېردا ئەسلى بار بولغان مەلۇملۇق ھىسابات تىزىمىغا ئېرىشىشىگە يول قويىدۇ. ئۇنىڭدا ئورنىتىلغان ئەپلەر قۇرغان بارلىق ھېساباتلار بولۇشى مۇمكىن.</string>
+ <string name="permdesc_getAccounts" product="default">ئەپنىڭ تېلېفوندا ئەسلى بار بولغان مەلۇملۇق ھىسابات تىزىمىغا ئېرىشىشىگە يول قويىدۇ. ئۇنىڭدا ئورنىتىلغان ئەپلەر قۇرغان بارلىق ھېساباتلار بولۇشى مۇمكىن.</string>
+ <string name="permlab_accessNetworkState">تور باغلىنىشىنى كۆرسىتىدۇ</string>
+ <string name="permdesc_accessNetworkState">ئەپنىڭ مەۋجۇت ۋە باغلانغان تورغا ئوخشاش تورغا ئائىت ئۇچۇرلىرىنى كۆرۈشىگە يول قويىدۇ. </string>
+ <string name="permlab_createNetworkSockets">تورنى تولۇق زىيارەت ھوقۇقى</string>
+ <string name="permdesc_createNetworkSockets">ئەپنىڭ تور socket قۇرۇپ، ئۆزلەشتۈرگەن تور كېلىشىمى ئىشلىتىشىگە يول قويىدۇ. توركۆرگۈ ۋە باشقا بەزى ئەپلەرگە ئىنتېرنېتقا سانلىق مەلۇمات يوللاش يولى بىلەن تەمىنلەيدۇ شۇڭلاشقا ئەپ بۇ ھوقۇققا ئېرىشمەي تۇتۇپمۇ ئىنتېرنېتقا سانلىق مەلۇمات يوللىيالايدۇ.</string>
+ <string name="permlab_changeNetworkState">تور باغلىنىشچانلىقىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_changeNetworkState">ئەپنىڭ تور باغلىنىش ھالىتىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_changeTetherState">باغلاقنىڭ ئۇلىنىشىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_changeTetherState">ئەپنىڭ تور باغلىنىش ھالىتىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_accessWifiState">بۇ Wi-Fi باغلىنىشلىرىنى كۆرسىتىدۇ</string>
+ <string name="permdesc_accessWifiState">ئەپنىڭ Wi-FI ئۈسكۈنە ئاتى ۋە Wi-FI قوزغالغان ياكى قوزغالمىغانلىقىغا ئوخشاش Wi-FI تورىغا ئائىت ئۇچۇرلىرىنى كۆرۈشىگە يول قويىدۇ. </string>
+ <string name="permlab_changeWifiState">بۇ WiFi غا باغلاپ ۋە ئۈزىدۇ</string>
+ <string name="permdesc_changeWifiState">ئەپنىڭ Wi-Fi ئېغىزىنى ئۇلاش ياكى ئۈزۈش ھەمدە Wi-Fi تورىنىڭ ئۈسكۈنە سەپلىمىسىنى ئۆزگەرتىشىگە يول قويىدۇ.</string>
+ <string name="permlab_changeWifiMulticastState">Wi-Fi كۆپ قاناللىق ئاڭلىتىشقا يول قويىدۇ</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet">ئەپنىڭ كۆپ قاناللىق ئاڭلىتىش ئارقىلىق Wi-FI تورىدىكى تاختا كومپيۇتېرىڭىزلا ئەمەس بەلكى ھەممە ئۈسكۈنىلەرنىڭ سانلىق مەلۇمات بوغچىسىنى قوبۇللاپ ۋە يوللاشقا يول قويىدۇ. بۇ مەشغۇلاتنىڭ توك سەرپىياتى كۆپ قاناللىق بولمىغان ئاڭلىتىشنىڭكىدىن يۇقىرى.</string>
+ <string name="permdesc_changeWifiMulticastState" product="default">ئەپنىڭ كۆپ قاناللىق ئاڭلىتىش ئارقىلىق Wi-FI تورىدىكى تېلېفونىڭىزلا ئەمەس بەلكى ھەممە ئۈسكۈنىلەرنىڭ سانلىق مەلۇمات بوغچىسىنى قوبۇللاپ ۋە يوللاشقا يول قويىدۇ. بۇ مەشغۇلاتنىڭ توك سەرپىياتى كۆپ قاناللىق بولمىغان ئاڭلىتىشنىڭكىدىن يۇقىرى.</string>
+ <string name="permlab_bluetoothAdmin">كۆكچىش تەڭشەك زىيارىتى</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet">ئەپنىڭ تاختا كومپيۇتېر كۆكچىشنى سەپلىشىگە، قوشنا ئۈسكۈنىلەرنى بايقىشىغا ۋە يىراق مۇساپىلىق پەرلەشكە يول قويىدۇ.</string>
+ <string name="permdesc_bluetoothAdmin" product="default">ئەپنىڭ تېلېفون كۆكچىشنى سەپلىشىگە، قوشنا ئۈسكۈنىلەرنى بايقىشىغا ۋە يىراق مۇساپىلىق پەرلەشكە يول قويىدۇ.</string>
+ <string name="permlab_accessWimaxState">بۇ WiMAX كە باغلاپ ۋە ئۈزىدۇ</string>
+ <string name="permdesc_accessWimaxState">ئەپنىڭ WiMAX قوزغالغان ياكى قوزغالمىغانلىقى ۋە باغلانغان خالىغان WiMAX تورىنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى جەزملىشىگە يول قويىدۇ.</string>
+ <string name="permlab_changeWimaxState">WiMAX ھالىتىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_changeWimaxState" product="tablet">ئەپنىڭ تاختا كومپيۇتېرنى WiMAX تورىغا باغلىشى ۋە ئۈزۈشىگە يول قويىدۇ.</string>
+ <string name="permdesc_changeWimaxState" product="default">ئەپنىڭ تېلېفوننى WiMAX تورىغا باغلىشى ۋە ئۈزۈشىگە يول قويىدۇ.</string>
+ <string name="permlab_bluetooth">كۆكچىش ئۈسكۈنە بىلەن جۈپلىنىدۇ</string>
+ <string name="permdesc_bluetooth" product="tablet">ئەپنىڭ تاختا كومپيۇتېر كۆكچىش سەپلىمىسىنى تەكشۈرۈپ كۆرۈپ، چۈپلەنگەن ماس ئۈسكۈنىگە باغلىنىشىغا يول قويىدۇ.</string>
+ <string name="permdesc_bluetooth" product="default">ئەپنىڭ تېلېفون كۆكچىش سەپلىمىسىنى تەكشۈرۈپ كۆرۈپ، چۈپلەنگەن ماس ئۈسكۈنىگە باغلىنىشىغا يول قويىدۇ.</string>
+ <string name="permlab_nfc">يېقىن دائىرىدىكى ئالاقە تىزگىنى</string>
+ <string name="permdesc_nfc">ئەپنىڭ يېقىن ئەتراپتىكى ئالاقە(NFC) بەلگە، كارتا ۋە ئوقۇغۇچ بىلەن ئالاقە قىلىشىغا يول قويىدۇ،</string>
+ <string name="permlab_disableKeyguard">ئېكران قۇلۇپنى چەكلەيدۇ</string>
+ <string name="permdesc_disableKeyguard">ئەپنىڭ كۇنۇپكا قۇلۇپى ۋە ئىم بىلەن باغلانغان بىخەتەرلىك تەڭشىكىنى توختىتىشىغا يول قويىدۇ. مەسىلەن، تېلېفوندا كەلگەندە كۇنۇپكا قۇلۇپىنى توختىتىپ، سۆزلىشىش تاماملانغاندا كۇنۇپكا قۇلۇپىنى قايتا قوزغىتىدۇ.</string>
+ <string name="permlab_readSyncSettings">قەدەمداش تەڭشىكىنى ئوقۇيدۇ</string>
+ <string name="permdesc_readSyncSettings">ئەپنىڭ مەلۇم بىر ھېساباتنىڭ قەدەمداش تەڭشىكىنى ئوقۇشىغا يول قويىدۇ. مەسىلەن، بۇ ھوقۇق ئالاقەداش ئەپنىڭ مەلۇم ھېسابات بىلەن قەدەمداشلانغان ياكى قەدەمداشلانمىغانلىقىنى جەزملەيدۇ.</string>
+ <string name="permlab_writeSyncSettings">قەدەمداشنى ئاچىدۇ ياكى ياپىدۇ</string>
+ <string name="permdesc_writeSyncSettings">ئەپنىڭ مەلۇم بىر ھېساباتنىڭ قەدەمداش تەڭشىكىنى ئۆزگەرتىشىگە يول قويىدۇ. مەسىلەن، بۇ ھوقۇق ئالاقەداش ئەپنىڭ مەلۇم ھېسابات بىلەن قەدەمداشلاشنى قوزغىتىشقا ئىشلىتىلىدۇ.</string>
+ <string name="permlab_readSyncStats">قەدەمداش سىتاتىستىكا ئۇچۇرىنى ئوقۇيدۇ</string>
+ <string name="permdesc_readSyncStats">ئەپنىڭ مەلۇم بىر ھېساباتنىڭ قەدەمداش سىتاتىستىكا ئۇچۇرىنى ئوقۇشىغا يول قويىدۇ، ھەرىكەتچان تارىخ خاتىرىسى ۋە قەدەمداش سانلىق مەلۇمات مىقدارىنى قەدەمداشلاشنى ئۆز ئىچىگە ئالىدۇ.</string>
+ <string name="permlab_sdcardRead" product="nosdcard">سىزنىڭ USB ساقلىغۇچىڭىزدىكى مەزمۇنلارنى ئوقۇيدۇ</string>
+ <string name="permlab_sdcardRead" product="default">سىزنىڭ SD كارتىڭىزدىكى مەزمۇنلارنى ئوقۇيدۇ</string>
+ <string name="permdesc_sdcardRead" product="nosdcard">ئەپنىڭ USB ساقلىغۇچىڭىزدىكى مەزمۇنلارنى ئوقۇشىغا يول قويىدۇ.</string>
+ <string name="permdesc_sdcardRead" product="default">ئەپنىڭ SD كارتىڭىزدىكى مەزمۇنلارنى ئوقۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_sdcardWrite" product="nosdcard">USB ساقلىغۇچىڭىزدىكى مەزمۇنلارنى ئۆزگەرتىدۇ ياكى ئۆچۈرىدۇ.</string>
+ <string name="permlab_sdcardWrite" product="default">SD كارتىڭىزدىكى مەزمۇنلارنى ئۆزگەرتىدۇ ياكى ئۆچۈرىدۇ.</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard">ئەپنىڭ USB ساقلىغۇچقا يېزىشىغا يول قويىدۇ.</string>
+ <string name="permdesc_sdcardWrite" product="default">ئەپنىڭ SD كارتىغا يېزىشىغا يول قويىدۇ.</string>
+ <string name="permlab_readNetworkUsageHistory">تور ئىشلىتىش ئەھۋالىنىڭ تارىخىنى ئوقۇيدۇ</string>
+ <string name="permdesc_readNetworkUsageHistory">ئەپنىڭ مۇئەييەن تور ۋە ئەپنىڭ تور ئىشلىتىش ئەھۋالىنىڭ تارىخىنى ئوقۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_manageNetworkPolicy">تور تەدبىرىنى باشقۇرىدۇ</string>
+ <string name="permdesc_manageNetworkPolicy">ئەپنىڭ تور تەدبىرىنى باشقۇرۇشىغا ۋە ئەپكە قارىتىلغان قائىدە بەلگىلىشىگە يول قويىدۇ.</string>
+ <string name="permlab_modifyNetworkAccounting">تور ئىشلىتىش ئەھۋالىنىڭ تارىخىنى خاتىرىلەش ئۇسۇلىنى ئۆزگەرتىدۇ</string>
+ <string name="permdesc_modifyNetworkAccounting">ئەپكە نىسبەتەن تور ئىشلىتىش ئەھۋالىنى خاتىرىلەش ئۇسۇلىنى ئۆزگەرتىشكە يول قويىدۇ. ئادەتتىكى پىروگراممىلار بۇ ھوقۇقنى ئىشلىتەلمەيدۇ.</string>
+ <string name="permlab_accessNotifications">زىيارەت ئۇقتۇرۇشى</string>
+ <string name="permdesc_accessNotifications">بۇ ئەپنىڭ باشقا ئەپلەر تارقاتقان ئۇقتۇرۇشلارنى ئۆز ئىچىگە ئالغان ئۇقتۇرۇشلارنى ئىزدەش، تەكشۈرۈش ھەمدە تازىلىشىغا يول قويىدۇ.</string>
+ <string name="permlab_bindNotificationListenerService">ئۇقتۇرۇش تىڭشاش مۇلازىمىتىگە باغلايدۇ</string>
+ <string name="permdesc_bindNotificationListenerService">ئىشلەتكۈچىنىڭ ئۇقتۇرۇش تىڭشاش مۇلازىمىتىنى يۇقىرى قاتلام ئېغىزىغا باغلىشىغا يول قويىدۇ. ئادەتتىكى ئەپلەر بۇ ھوقۇققا موھتاج بولمايدۇ.</string>
+ <string name="permlab_invokeCarrierSetup">مۇلازىمەت تەمىنلىگۈچى سەپلىگەن ئەپنى يۆتكەپ ئىشلىتىدۇ</string>
+ <string name="permdesc_invokeCarrierSetup">ئەپنىڭ مۇلازىمەت تەمىنلىگۈچى سەپلىگەن ئەپنى يۆتكەپ ئىشلىتىشىگە يول قويىدۇ. ئادەتتىكى ئەپلەر بۇ ھوقۇققا مۇھتاج بولمايدۇ.</string>
+ <string name="permlab_accessNetworkConditions">تور ئەھۋالىنىڭ تەكشۈرۈش ئۇچۇرىنى تىڭشايدۇ</string>
+ <string name="permdesc_accessNetworkConditions">ئەپنىڭ تور ئەھۋالىنىڭ تەكشۈرۈش ئۇچۇرىنى تىڭشىشىغا يول قويىدۇ. ئادەتتىكى ئەپلەر بۇ ھوقۇققا مۇھتاج بولمايدۇ.</string>
+ <string name="policylab_limitPassword">ئىم قائىدە تەڭشىكى</string>
+ <string name="policylab_watchLogin">ئېكران قۇلۇپىنى ئېچىشنى سىناش قېتىم سانى نازارەتچىسى</string>
+ <string name="policydesc_watchLogin" product="tablet">ئېكراننى قۇلۇپلاشتىن ئىلگىرى ئىم كىرگۈزۈش قېتىم سانىنى نازارەت قىلىدۇ؛ ئەگەر ئىم كىرگۈزۈش قېتىم سانى بەك كۆپ بولۇپ كەتسە تاختا كومپيۇتېرنى قۇلۇپلايدۇ ياكى تاختا كومپيۇتېردىكى ھەممە سانلىق مەلۇماتلارنى ئۆچۈرىدۇ.</string>
+ <string name="policydesc_watchLogin" product="default">ئېكراننى قۇلۇپلاشتىن ئىلگىرى ئىم كىرگۈزۈش قېتىم سانىنى نازارەت قىلىدۇ؛ ئەگەر ئىم كىرگۈزۈش قېتىم سانى بەك كۆپ بولۇپ كەتسە تېلېفوننى قۇلۇپلايدۇ ياكى تېلېفوندىكى ھەممە سانلىق مەلۇماتلارنى ئۆچۈرىدۇ.</string>
+ <string name="policylab_forceLock">ئېكراننى قۇلۇپلايدۇ</string>
+ <string name="policydesc_forceLock">ئېكران قۇلۇپلاش ئۇسۇلى ۋە ۋاقىت تىزگىنى</string>
+ <string name="policylab_wipeData">ھەممە سانلىق مەلۇماتنى ئۆچۈرىدۇ</string>
+ <string name="policydesc_wipeData" product="tablet">تاختا كومپيۇتېرنىڭ سانلىق مەلۇماتلىرىنى ئاگاھلاندۇرمايلا ئۆچۈرىدۇ، خۇددى زاۋۇت تەڭشىكىنى ئەسلىگە قايتۇرغان مەشغۇلاتتەك.</string>
+ <string name="policydesc_wipeData" product="default">تېلېفوننىڭ سانلىق مەلۇماتلىرىنى ئاگاھلاندۇرمايلا ئۆچۈرىدۇ، خۇددى زاۋۇت تەڭشىكىنى ئەسلىگە قايتۇرغان مەشغۇلاتتەك.</string>
+ <string name="policylab_setGlobalProxy">ئۈسكۈنىنىڭ ئومۇمىيەت ۋاكالەتچى تەڭشىكى</string>
+ <string name="policylab_encryptedStorage">ساقلىغۇچ شىفىرلاش تەڭشىكى</string>
+ <string name="policydesc_encryptedStorage">لازىملىق ساقلايدىغان ئەپ سانلىق مەلۇماتلىرىنى شىفىرلايدۇ</string>
+ <string name="policylab_disableCamera">كامېرانى چەكلە</string>
+ <string name="policydesc_disableCamera">ھەممە ئۈسكۈنە كامېراسىنى ئىشلىتىشنى چەكلەيدۇ</string>
+ <string-array name="phoneTypes">
+ <item>ئۆي</item>
+ <item>كۆچمە</item>
+ <item>ئىش</item>
+ <item>ئىش فاكىس</item>
+ <item>ئوي فاكىس</item>
+ <item>چاقىرغۇ</item>
+ <item>باشقا</item>
+ <item>ئىختىيارىي</item>
+ </string-array>
+ <string-array name="emailAddressTypes">
+ <item>ئۆي</item>
+ <item>ئىش</item>
+ <item>باشقا</item>
+ <item>ئىختىيارىي</item>
+ </string-array>
+ <string-array name="postalAddressTypes">
+ <item>ئۆي</item>
+ <item>ئىش</item>
+ <item>باشقا</item>
+ <item>ئىختىيارىي</item>
+ </string-array>
+ <string-array name="imAddressTypes">
+ <item>ئۆي</item>
+ <item>ئىش</item>
+ <item>باشقا</item>
+ <item>ئىختىيارىي</item>
+ </string-array>
+ <string-array name="organizationTypes">
+ <item>ئىش</item>
+ <item>باشقا</item>
+ <item>ئىختىيارىي</item>
+ </string-array>
+ <string-array name="imProtocols">
+ <item>AIM</item>
+ <item>Windows Live</item>
+ <item>Yahoo</item>
+ <item>Skype</item>
+ <item>QQ</item>
+ <item>Google Talk</item>
+ <item>ICQ</item>
+ <item>Jabber</item>
+ </string-array>
+ <string name="phoneTypeCustom">ئىختىيارىيي</string>
+ <string name="phoneTypeHome">ئۆي</string>
+ <string name="phoneTypeMobile">كۆچمە</string>
+ <string name="phoneTypeWork">ئىش</string>
+ <string name="phoneTypeFaxWork">ئىش فاكىس</string>
+ <string name="phoneTypeFaxHome">ئوي فاكىس</string>
+ <string name="phoneTypePager">چاقىرغۇ</string>
+ <string name="phoneTypeOther">باشقا</string>
+ <string name="phoneTypeCallback">قايتۇرما چاقىرىق</string>
+ <string name="phoneTypeCar">ماشىنا</string>
+ <string name="phoneTypeCompanyMain">شىركەت باش ئاپپاراتى</string>
+ <string name="phoneTypeIsdn">ISDN</string>
+ <string name="phoneTypeMain">ئاساسىي تىزىملىك</string>
+ <string name="phoneTypeOtherFax">باشقا فاكىس</string>
+ <string name="phoneTypeRadio">سىمسىز ئالاقە</string>
+ <string name="phoneTypeTelex">تېلېگرامما</string>
+ <string name="phoneTypeTtyTdd">TTY/TDD</string>
+ <string name="phoneTypeWorkMobile">خىزمەت تېلېفونى</string>
+ <string name="phoneTypeWorkPager">خىزمەت چاقىرغۇ</string>
+ <string name="phoneTypeAssistant">ياردەمچى</string>
+ <string name="phoneTypeMms">MMS</string>
+ <string name="eventTypeCustom">ئىختىيارىيلاشقان</string>
+ <string name="eventTypeBirthday">تۇغۇلغان كۈن</string>
+ <string name="eventTypeAnniversary">يىللىق خاتىرە كۈن</string>
+ <string name="eventTypeOther">باشقا</string>
+ <string name="emailTypeCustom">ئىختىيارىي</string>
+ <string name="emailTypeHome">ئۆي</string>
+ <string name="emailTypeWork">ئىش</string>
+ <string name="emailTypeOther">باشقا</string>
+ <string name="emailTypeMobile">كۆچمە</string>
+ <string name="postalTypeCustom">ئىختىيارىي</string>
+ <string name="postalTypeHome">ئۆي</string>
+ <string name="postalTypeWork">ئىش</string>
+ <string name="postalTypeOther">باشقا</string>
+ <string name="imTypeCustom">ئىختىيارىي</string>
+ <string name="imTypeHome">ئۆي</string>
+ <string name="imTypeWork">ئىش</string>
+ <string name="imTypeOther">باشقا</string>
+ <string name="imProtocolCustom">ئىختىيارىي</string>
+ <string name="imProtocolAim">AIM</string>
+ <string name="imProtocolMsn">Windows Live</string>
+ <string name="imProtocolYahoo">Yahoo</string>
+ <string name="imProtocolSkype">Skype</string>
+ <string name="imProtocolQq">QQ</string>
+ <string name="imProtocolGoogleTalk">Hangouts</string>
+ <string name="imProtocolIcq">ICQ</string>
+ <string name="imProtocolJabber">Jabber</string>
+ <string name="imProtocolNetMeeting">تور يېغىنى </string>
+ <string name="orgTypeWork">ئىش</string>
+ <string name="orgTypeOther">باشقا</string>
+ <string name="orgTypeCustom">ئىختىيارىي</string>
+ <string name="relationTypeCustom">ئىختىيارىيلاشقان</string>
+ <string name="relationTypeAssistant">ياردەمچى</string>
+ <string name="relationTypeBrother">قېرىنداش</string>
+ <string name="relationTypeChild">بالا</string>
+ <string name="relationTypeDomesticPartner">ئۆيداش</string>
+ <string name="relationTypeFather">ئاتا</string>
+ <string name="relationTypeFriend">دوست</string>
+ <string name="relationTypeManager">باشقۇرغۇچى</string>
+ <string name="relationTypeMother">ئانا</string>
+ <string name="relationTypeParent">ئاتا-ئانا</string>
+ <string name="relationTypePartner">ھەمراھ</string>
+ <string name="relationTypeReferredBy">تونۇشتۇرغۇچى</string>
+ <string name="relationTypeRelative">نىسپىي</string>
+ <string name="relationTypeSister">ئاچا-سىڭىل</string>
+ <string name="relationTypeSpouse">جورا</string>
+ <string name="sipAddressTypeCustom">ئىختىيارىيلاشقان</string>
+ <string name="sipAddressTypeHome">ئۆي</string>
+ <string name="sipAddressTypeWork">ئىش</string>
+ <string name="sipAddressTypeOther">باشقا</string>
+ <string name="quick_contacts_not_available">بۇ مەزمۇننى كۆرسىتىدىغان ئەپ تېپىلمىدى.</string>
+ <string name="keyguard_password_enter_pin_code">PIN كودىنى كىرگۈزۈڭ</string>
+ <string name="keyguard_password_enter_puk_code">PUK ۋە يېڭى PIN كودىنى كىرگۈزۈڭ</string>
+ <string name="keyguard_password_enter_puk_prompt">PUK كودى</string>
+ <string name="keyguard_password_enter_pin_prompt">يېڭى PIN كودى</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">\"بۇ جاينى چېكىپ ئىم كىرگۈزۈڭ\"</font></string>
+ <string name="keyguard_password_enter_password_code">قۇلۇپ ئېچىش ئۈچۈن ئىم كىرگۈزۈڭ</string>
+ <string name="keyguard_password_enter_pin_password_code">PIN كىرگۈزۈپ قۇلۇپ ئېچىڭ</string>
+ <string name="keyguard_password_wrong_pin_code">PIN كودى خاتا.</string>
+ <string name="keyguard_label_text">قۇلۇپ ئېچىشتا، ئاۋۋال Menu نى بېسىپ ئاندىن 0 نى بېسىڭ.</string>
+ <string name="emergency_call_dialog_number_for_display">جىددىي قۇتقۇزۇش ياكى ساقچىغا مەلۇم قىلىش تېلېفۇنى</string>
+ <string name="lockscreen_carrier_default">مۇلازىمەت يوق</string>
+ <string name="lockscreen_screen_locked">ئىكران قۇلۇپلانغان.</string>
+ <string name="lockscreen_instructions_when_pattern_enabled">Menu نى بېسىپ قۇلۇپ ئېچىڭ ياكى جىددىي قۇتقۇزۇشنى چاقىرىڭ.</string>
+ <string name="lockscreen_instructions_when_pattern_disabled">Menu نى بېسىپ قۇلۇپنى ئېچىڭ.</string>
+ <string name="lockscreen_pattern_instructions">قۇلۇپ ئېچىش ئەندىزىسىنى سىزىڭ</string>
+ <string name="lockscreen_return_to_call">چاقىرىشقا قايتىش</string>
+ <string name="lockscreen_pattern_correct">توغرا!</string>
+ <string name="lockscreen_pattern_wrong">قايتا سىنا</string>
+ <string name="lockscreen_password_wrong">قايتا سىنا</string>
+ <string name="faceunlock_multiple_failures">چىرايدا قۇلۇپ ئاچقۇچنى سىناش قېتىم سانىنىڭ يۇقىرى چېكىدىن ئېشىپ كەتتى</string>
+ <string name="lockscreen_missing_sim_message_short">SIM كارتا يوق</string>
+ <string name="lockscreen_missing_sim_message" product="tablet">تاختا كومپيۇتېردا SIM كارتا يوق.</string>
+ <string name="lockscreen_missing_sim_message" product="default">تېلېفوندا SIM كارتا يوق.</string>
+ <string name="lockscreen_missing_sim_instructions">SIM كارتا قىستۇرۇڭ.</string>
+ <string name="lockscreen_missing_sim_instructions_long">SIM كارتا يوقالغان ياكى ئوقۇغىلى بولمايدۇ. SIM كارتا قىستۇرۇڭ.</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short">SIM كارتىنى ئىشلەتكىلى بولمايدۇ.</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions">سىزنىڭ SIM كارتىڭىز مەڭگۈلۈك توختىتىلدى.\nسىمسىز تور مۇلازىمىتى تەمىنلىگۈچىڭىز بىلەن ئالاقە قىلىپ، يېڭىدىن بىر SIM كارتىغا ئېرىشىڭ.</string>
+ <string name="emergency_calls_only" msgid="2485604591272668370">جىددىي تېلېفونلا ئۇرغىلى بولىدۇ</string>
+ <string name="lockscreen_network_locked_message">تور قۇلۇپلانغان</string>
+ <string name="lockscreen_sim_puk_locked_message">SIM كارتا PUK نۇمۇر ئارقىلىق قۇلۇپلانغان.</string>
+ <string name="lockscreen_sim_puk_locked_instructions">ئىشلەتكۈچىلەر قوللانمىسىنى كۆرۈڭ ياكى مۇلازىمەتچى بىلەن ئالاقىلىشىڭ.</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message">SIM كارتا قۇلۇپىنى ئېچىۋاتىدۇ…</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message">سىز قۇلۇپ ئېچىش ئىمنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا كىرگۈزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message">سىز PIN نى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا كىرگۈزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما Google ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ. "\n\n "يەنە <xliff:g id="NUMBER_2">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما Google ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تېلېفون قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ."\n\n" يەنە <xliff:g id="NUMBER_2">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet">سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تاختا كومپيۇتېرنى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ.</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default">سىز تېلېفون قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تېلېفوننى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ.</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tablet">سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. تاختا كومپيۇتېر زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، </string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default">سىز تېلېفون قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. تېلېفون زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، </string>
+ <string name="lockscreen_too_many_failed_attempts_countdown"><xliff:g id="NUMBER">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="lockscreen_forgot_pattern_button_text">ئەندىزىنى ئۇنتۇپسىزمۇ؟</string>
+ <string name="lockscreen_glogin_forgot_pattern">ھىسابات قۇلۇپى ئېچىلدى</string>
+ <string name="lockscreen_glogin_too_many_attempts">ئەندىزىسىنى سىناش قېتىم سانى بەك كۆپ بولۇپ كەتتى</string>
+ <string name="lockscreen_glogin_instructions">قۇلۇپ ئېچىشتا، Google ھېساباتىڭىزدا تىزىمغا كىرىڭ</string>
+ <string name="lockscreen_glogin_username_hint">ئىشلەتكۈچى ئاتى(تورخەت)</string>
+ <string name="lockscreen_glogin_password_hint">ئىم</string>
+ <string name="lockscreen_glogin_submit_button">تىزىمغا كىر</string>
+ <string name="lockscreen_glogin_invalid_input">ئىشلەتكۈچى ئاتى ۋە ياكى ئىم خاتا.</string>
+ <string name="lockscreen_glogin_account_recovery_hint">\"ئىشلەتكۈچى ئاتىڭىز ياكى ئىمنى ئۇنۇتتىڭىزمۇ؟\"\n\"google.com/accounts/recovery زىيارەت قىلىڭ.\"<b/></string>
+ <string name="lockscreen_glogin_checking_password">تەكشۈرۈۋاتىدۇ…</string>
+ <string name="lockscreen_unlock_label">قۇلۇپ ئاچ</string>
+ <string name="lockscreen_sound_on_label">ئاۋاز ئوچۇق</string>
+ <string name="lockscreen_sound_off_label">ئاۋاز تاقاق</string>
+ <string name="lockscreen_access_pattern_start">ئەندىزە سىزىڭ</string>
+ <string name="lockscreen_access_pattern_cleared">ئەندىزە تازىلاندى</string>
+ <string name="lockscreen_access_pattern_cell_added">كاتەكچە قوشۇلدى</string>
+ <string name="lockscreen_access_pattern_detected">ئەندىزە تامام</string>
+ <string name="lockscreen_access_pattern_area" msgid="">ئەندىزە دائىرىسى.</string>
+ <string name="keyguard_accessibility_widget_changed">%1$s. %3$d نىڭ ئەپچىسى %2$d.</string>
+ <string name="keyguard_accessibility_add_widget">ئەپچە قوش</string>
+ <string name="keyguard_accessibility_widget_empty_slot">بوش</string>
+ <string name="keyguard_accessibility_unlock_area_expanded">قۇلۇپ ئېچىش رايونى يېيىلدى.</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed">قۇلۇپ ئېچىش رايونى قاتلاندى.</string>
+ <string name="keyguard_accessibility_widget"><xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ئەپچە. </string>
+ <string name="keyguard_accessibility_user_selector">ئىشلەتكۈچى تاللىغۇچ</string>
+ <string name="keyguard_accessibility_status">ھالەت</string>
+ <string name="keyguard_accessibility_camera">كامېرا</string>
+ <string name="keygaurd_accessibility_media_controls">ۋاستە تىزگىنلەر</string>
+ <string name="keyguard_accessibility_widget_reorder_start">ئەپچە قايتا تەرتىپلەش باشلاندى.</string>
+ <string name="keyguard_accessibility_widget_reorder_end">ئەپچە قايتا تەرتىپلەش ئاخىرلاشتى.</string>
+ <string name="keyguard_accessibility_widget_deleted"><xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ئۆچۈرۈلگەن ئەپچە .</string>
+ <string name="keyguard_accessibility_expand_lock_area">قۇلۇپ ئېچىش دائىرىسىنى يايىدۇ.</string>
+ <string name="keyguard_accessibility_slide_unlock">سۈرۈلسە قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_pattern_unlock">ئەدىزەدە قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_face_unlock">چىرايدا قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_pin_unlock">بۇ Pin دا قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_password_unlock">ئىمدا قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_pattern_area">ئەندىزە دائىرىسى.</string>
+ <string name="keyguard_accessibility_slide_area">سۈرۈش دائىرىسى</string>
+ <string name="password_keyboard_label_symbol_key">\?123</string>
+ <string name="password_keyboard_label_alpha_key">ABC</string>
+ <string name="password_keyboard_label_alt_key">ALT</string>
+ <string name="granularity_label_character">ھەرپ</string>
+ <string name="granularity_label_word">سۆز</string>
+ <string name="granularity_label_link">ئۇلانما</string>
+ <string name="granularity_label_line">سىزىق</string>
+ <string name="hour_ampm">"<xliff:g id="AMPM">%P</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>"</string>
+ <string name="hour_cap_ampm">"<xliff:g id="AMPM">%p</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>"</string>
+ <string name="factorytest_failed">زاۋۇتتىن چىقىش سىنىقى مەغلۇب بولدى.</string>
+ <string name="factorytest_not_system">پەقەت \system\app گە ئورنىتىلغان بوغچىلارلا FACTORY-TEST مەشقۇلاتىنى قوللايدۇ.</string>
+ <string name="factorytest_no_action">FACTORY_TEST مەشغۇلاتىنى قوللايدىغان بوغچا تېپىلمىدى.</string>
+ <string name="factorytest_reboot">قايتا قوزغات</string>
+ <string name="js_dialog_title">مەزكۇر <xliff:g id="TITLE">%S</xliff:g> بەتتە دېيىلگىنى:</string>
+ <string name="js_dialog_title_default">JavaScript</string>
+ <string name="js_dialog_before_unload_title">يېتەكلەشنى جەزملە</string>
+ <string name="js_dialog_before_unload_positive_button">بۇ بەتتىن ئايرىل</string>
+ <string name="js_dialog_before_unload_negative_button">بۇ بەتتە تۇرۇپ تۇر</string>
+ <string name="js_dialog_before_unload"><xliff:g id="MESSAGE">%s</xliff:g>\"\n\n\"راستلا بۇ بەتتىن ئايرىلامسىز؟</string>
+ <string name="save_password_label">جەزملە</string>
+ <string name="double_tap_toast">ئەسكەرتىش: قوش چەكسىڭىز چوڭىيىدۇ ۋە كىچىكلەيدۇ.</string>
+ <string name="autofill_this_form">ئۆزلۈكىدىن تولدۇر</string>
+ <string name="setup_autofill">ئۆزلۈكىدىن تولدۇرۇش تەڭشىكى</string>
+ <string name="autofill_address_summary_name_format">$1$2$3</string>
+ <string name="autofill_address_summary_separator">« ،»</string>
+ <string name="autofill_address_summary_format">$1$2$3</string>
+ <string name="autofill_attention_ignored_re">attention|attn</string>
+ <string name="autofill_region_ignored_re">province|region|other<!-- es -->|provincia<!-- pt-BR, pt-PT -->|bairro|suburb</string>
+ <string name="autofill_company_re">company|business|organization|organisation|department<!-- de-DE -->|firma|firmenname<!-- es -->|empresa<!-- fr-FR -->|societe|société<!-- it-IT -->|ragione.?sociale<!-- ja-JP -->|会社<!-- ru -->|название.?компании<!-- zh-CN -->|单位|公司</string>
+ <string name="autofill_address_line_1_re">address.?line|address1|addr1|street<!-- de-DE -->|strasse|straße|hausnummer|housenumber<!-- en-GB -->|house.?name<!-- es -->|direccion|dirección<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所1<!-- pt-BR, pt-PT -->|morada|endereço<!-- ru -->|Адрес<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_1_label_re">address<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所<!-- zh-CN -->|地址</string>
+ <string name="autofill_address_line_2_re">address.?line2|address2|addr2|street|suite|unit<!-- de-DE -->|adresszusatz|ergänzende.?angaben<!-- es -->|direccion2|colonia|adicional<!-- fr-FR -->|addresssuppl|complementnom|appartement<!-- it-IT -->|indirizzo2<!-- ja-JP -->|住所2</string>
+ <string name="autofill_address_line_3_re">address.?line3|address3|addr3|street|line3<!-- es -->|municipio<!-- fr-FR -->|batiment|residence<!-- it-IT -->|indirizzo3</string>
+ <string name="autofill_country_re">country|location<!-- ja-JP -->|国<!-- zh-CN -->|国家</string>
+ <string name="autofill_zip_code_re">zip|postal|post code|pcode|^1z$<!-- de-DE -->|postleitzahl<!-- es -->|cp<!-- fr-FR -->|cdp<!-- it-IT -->|cap<!-- ja-JP -->|郵便番号<!-- pt-BR, pt-PT -->|codigo|codpos|cep<!-- ru -->|Почтовый.?Индекс<!--zh-CN -->|邮政编码|邮编<!-- zh-TW -->|郵遞區號</string>
+ <string name="autofill_zip_4_re">zip|^-$|post2<!-- pt-BR, pt-PT -->|codpos2</string>
+ <string name="autofill_city_re">city|town<!-- de-DE -->|ort|stadt<!-- en-AU -->|suburb<!-- es -->|ciudad|provincia|localidad|poblacion<!-- fr-FR -->|ville|commune<!-- it-IT -->|localita<!-- ja-JP -->|市区町村<!-- pt-BR, pt-PT -->|cidade<!-- ru -->|Город<!-- zh-CN -->|市<!-- zh-TW -->|分區</string>
+ <string name="autofill_state_re">state|county|region|province<!-- de-DE -->|land<!-- en-UK -->|county|principality<!-- ja-JP -->|都道府県<!-- pt-BR, pt-PT -->|estado|provincia<!-- ru -->|область<!-- zh-CN -->|省<!-- zh-TW -->|地區</string>
+ <string name="autofill_address_type_same_as_re">ئوخشاش</string>
+ <string name="autofill_address_type_use_my_re">مېنىڭكىنى</string>
+ <string name="autofill_billing_designator_re">ھېسابات</string>
+ <string name="autofill_shipping_designator_re">پاراخوت</string>
+ <string name="autofill_email_re">e.?mail<!-- ja-JP -->|メールアドレス<!-- ru -->|Электронной.?Почты<!-- zh-CN -->|邮件|邮箱<!-- zh-TW -->|電郵地址</string>
+ <string name="autofill_username_re">user.?name|user.?id<!-- de-DE -->|vollständiger.?name<!-- zh-CN -->|用户名</string>
+ <string name="autofill_name_re">^name|full.?name|your.?name|customer.?name|firstandlastname<!-- es -->|nombre.*y.*apellidos<!-- fr-FR -->|^nom<!-- ja-JP -->|お名前|氏名<!-- pt-BR, pt-PT -->|^nome<!-- zh-CN -->|姓名</string>
+ <string name="autofill_name_specific_re">^name<!-- fr-FR -->|^nom<!-- pt-BR, pt-PT -->|^nome</string>
+ <string name="autofill_first_name_re">irst.*name|initials|fname|first$<!-- de-DE -->|vorname<!-- es -->|nombre<!-- fr-FR -->|forename|prénom|prenom<!-- ja-JP -->|名<!-- pt-BR, pt-PT -->|nome<!-- ru -->|Имя</string>
+ <string name="autofill_middle_initial_re">middle.*initial|m\\.i\\.|mi$</string>
+ <string name="autofill_middle_name_re">middle.*name|mname|middle$<!-- es -->|apellido.?materno|lastlastname</string>
+ <string name="autofill_last_name_re">last.*name|lname|surname|last$<!-- de-DE -->|nachname<!-- es -->|apellidos<!-- fr-FR -->|famille|^nom<!-- it-IT -->|cognome<!-- ja-JP -->|姓<!-- pt-BR, pt-PT -->|morada|apelidos|surename|sobrenome<!-- ru -->|Фамилия</string>
+ <string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfono<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string>
+ <string name="autofill_area_code_re">area.*code|acode|area</string>
+ <string name="autofill_phone_prefix_re">prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
+ <string name="autofill_phone_suffix_re">suffix</string>
+ <string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string>
+ <string name="autofill_name_on_card_re">card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|karteninhaber<!-- es -->|nombre.*tarjeta<!-- fr-FR -->|nom.*carte<!-- it-IT -->|nome.*cart<!-- ja-JP -->|名前<!-- ru -->|Имя.*карты<!-- zh-CN -->|信用卡开户名|开户名|持卡人姓名<!-- zh-TW -->|持卡人姓名</string>
+ <string name="autofill_name_on_card_contextual_re">ئىسىم</string>
+ <string name="autofill_card_cvc_re">verification|card identification|cvn|security code|cvv code|cvc</string>
+ <string name="autofill_card_number_re">number|card.?#|card.?no|ccnum<!-- de-DE -->|nummer<!-- es -->|credito|numero|número<!-- fr-FR -->|numéro<!-- ja-JP -->|カード番号<!-- ru -->|Номер.*карты<!-- zh-CN -->|信用卡号|信用卡号码<!-- zh-TW -->|信用卡卡號</string>
+ <string name="autofill_expiration_month_re">expir|exp.*month|exp.*date|ccmonth<!-- de-DE -->|gueltig|gültig|monat<!-- es -->|fecha<!-- fr-FR -->|date.*exp<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|月</string>
+ <string name="autofill_expiration_date_re">exp|^/|year<!-- de-DE -->|ablaufdatum|gueltig|gültig|yahr<!-- es -->|fecha<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|年|有效期</string>
+ <string name="autofill_card_ignored_re">^card</string>
+ <string name="autofill_fax_re">fax<!-- fr-FR -->|télécopie|telecopie<!-- ja-JP -->|ファックス<!-- ru -->|факс<!-- zh-CN -->|传真<!-- zh-TW -->|傳真</string>
+ <string name="autofill_country_code_re">country.*code|ccode|_cc</string>
+ <string name="autofill_area_code_notext_re">^\\($</string>
+ <string name="autofill_phone_prefix_separator_re">^-$|^\\)$</string>
+ <string name="autofill_phone_suffix_separator_re">^-$</string>
+ <string name="autofill_province">ئۆلكە</string>
+ <string name="autofill_postal_code">پوچتا نومۇر</string>
+ <string name="autofill_state">ئۆلكە</string>
+ <string name="autofill_zip_code">پوچتا نومۇرى</string>
+ <string name="autofill_county">دۆلەت</string>
+ <string name="autofill_island">ئارال</string>
+ <string name="autofill_district">رايون</string>
+ <string name="autofill_department">تارماق</string>
+ <string name="autofill_prefecture">تەۋە رايون</string>
+ <string name="autofill_parish">مەمۇرىي رايون</string>
+ <string name="autofill_area">دائىرە</string>
+ <string name="autofill_emirate">خەلىپەلىك</string>
+ <string name="permlab_readHistoryBookmarks">تور خەتكۈچى ۋە تارىخ خاتىرىڭىزنى ئوقۇيدۇ</string>
+ <string name="permdesc_readHistoryBookmarks">ئەپنىڭ توركۆرگۈدىكى بارلىق ئادرېس ۋە خەتكۈچلەرنى ئوقۇشىغا يول قويىدۇ. دىققەت: بۇ ھوقۇق ئۈچىنچى تەرەپ توركۆرگۈ ياكى تور بەت كۆرۈش ئىقتىدارى بار باشقا ئەپكە ماس كەلمەسلىكى مۇمكىن</string>
+ <string name="permlab_writeHistoryBookmarks">تور خەتكۈچى ۋە تارىخ خاتىرىسى يازىدۇ</string>
+ <string name="permlab_setAlarm">قوڭغۇراق تەڭشەك</string>
+ <string name="permlab_addVoicemail">ئۈنخەت قوش</string>
+ <string name="permdesc_addVoicemail">ئەپنىڭ ئۈنخەت ساندۇقىڭىزنىڭ قوبۇللاش ساندۇقىغا ئۇچۇر قوشۇشىغا يول قويىدۇ.</string>
+ <string name="permlab_writeGeolocationPermissions">توركۆرگۈنىڭ جۇغراپىيەلىك ئورۇن ھوقۇقىنى ئۆزگەرت</string>
+ <string name="permdesc_writeGeolocationPermissions">ئەپنىڭ توركۆرگۈنىڭ جۇغراپىيەلىك ئورۇن ھوقۇقىنى ئۆزگەرتىشىگە يول قويىدۇ. زەھەرخەندە ئەپلەر بۇ ئارقىلىق توركۆرگۈنىڭ ئورنىنى خالىغان تور بىكەتكە يوللايدۇ.</string>
+ <string name="save_password_message">توركۆرگۈ ئىمنى ساقلىۋالسۇنمۇ؟</string>
+ <string name="save_password_notnow">ھازىرچە ياق</string>
+ <string name="save_password_remember">ئەستە تۇت</string>
+ <string name="save_password_never">ھەرگىز</string>
+ <string name="open_permission_deny">بۇ بەتنى ئېچىش ھوقۇقىڭىز يوق.</string>
+ <string name="text_copied">تېكىست كېسىپ چاپلاش تاختىسىغا كۆچۈرۈلدى.</string>
+ <string name="more_item_label">تېخىمۇ كۆپ</string>
+ <string name="prepend_shortcut_label">Menu+</string>
+ <string name="menu_space_shortcut_label">بوشلۇق</string>
+ <string name="menu_enter_shortcut_label">Enter</string>
+ <string name="menu_delete_shortcut_label">ئۆچۈر</string>
+ <string name="search_go">ئىزدە</string>
+ <string name="searchview_description_search">ئىزدە</string>
+ <string name="searchview_description_query">سۈرۈشتۈرۈش ئىزدە</string>
+ <string name="searchview_description_clear">سۈرۈشتۈرۈش تازىلا</string>
+ <string name="searchview_description_submit">سۈرۈشتۈرۈش تاپشۇر</string>
+ <string name="searchview_description_voice">تاۋۇش ئىزدەش</string>
+ <string name="enable_explore_by_touch_warning_title">چېكىلگەندىكى كۆرگۈنى قوزغىتامدۇ؟</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet"><xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> چېكىلگەندىكى كۆرگۈ ئىقتىدارى ئېچىلغاندا، چەككەن مەزمۇننىڭ چۈشەندۈرۈشىنى ئاڭلىيالايسىز ياكى كۆرەلەيسىز. يەنە قول ئىشارىتى مەشغۇلاتى ئارقىلىق تاختا كومپيۇتېر بىلەن ئۆز ئارا تەسىرلىشەلەيسىز.</string>
+ <string name="enable_explore_by_touch_warning_message" product="default"><xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> چېكىلگەندىكى كۆرگۈ ئىقتىدارى ئېچىلغاندا، چەككەن مەزمۇننىڭ چۈشەندۈرۈشىنى ئاڭلىيالايسىز ياكى كۆرەلەيسىز. يەنە قول ئىشارىتى مەشغۇلاتى ئارقىلىق تېلېفون بىلەن ئۆز ئارا تەسىرلىشەلەيسىز.</string>
+ <string name="oneMonthDurationPast">1 ئاي ئىلگىرى</string>
+ <string name="beforeOneMonthDurationPast">1</string>
+ <string name="last_month">ئالدىنقى ئاي</string>
+ <string name="older">كونىراق</string>
+ <string name="preposition_for_date"><xliff:g id="DATE">%s</xliff:g> دىكى</string>
+ <string name="preposition_for_time"><xliff:g id="TIME">%s</xliff:g> دا</string>
+ <string name="preposition_for_year"><xliff:g id="YEAR">%s</xliff:g> دا</string>
+ <string name="day">كۈن</string>
+ <string name="days">كۈن</string>
+ <string name="hour">سائەت</string>
+ <string name="hours">سائەت</string>
+ <string name="minute">مىنۇت</string>
+ <string name="minutes">مىنۇت</string>
+ <string name="second">سېكۇنت</string>
+ <string name="seconds">سېكۇنت</string>
+ <string name="week">ھەپتە</string>
+ <string name="weeks">ھەپتە</string>
+ <string name="year">يىل</string>
+ <string name="years">يىل</string>
+ <string name="VideoView_error_title">سىن مەسىلىسى</string>
+ <string name="VideoView_error_text_invalid_progressive_playback">كەچۈرۈڭ، بۇ سىننى مەزكۇر ئۈسكۈنىدە قويۇشقا ماس كەلمەيدۇ.</string>
+ <string name="VideoView_error_text_unknown">سىننى قويالمايدۇ</string>
+ <string name="VideoView_error_button">جەزملە</string>
+ <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>,<xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="noon">"چۈش"</string>
+ <string name="Noon">"چۈش"</string>
+ <string name="midnight">"يېرىم كېچە"</string>
+ <string name="Midnight">"يېرىم كېچە"</string>
+ <string name="elapsed_time_short_format_mm_ss"><xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g></string>
+ <string name="elapsed_time_short_format_h_mm_ss"><xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g></string>
+ <string name="selectAll">ھەممىنى تاللا</string>
+ <string name="cut">كەس</string>
+ <string name="copy">كۆچۈر</string>
+ <string name="paste">چاپلا</string>
+ <string name="replace">ئالماشتۇر…</string>
+ <string name="delete">ئۆچۈر</string>
+ <string name="copyUrl">تور ئادرېس كۆچۈر</string>
+ <string name="selectTextMode">تېكىست تاللا</string>
+ <string name="textSelectionCABTitle">تېكىست تاللاش</string>
+ <string name="addToDictionary">لۇغەتكە قوش</string>
+ <string name="deleteText">ئۆچۈر</string>
+ <string name="inputMethod">كىرگۈزگۈچ</string>
+ <string name="editTextMenuTitle">تېكىست مەشغۇلاتى</string>
+ <string name="low_internal_storage_view_title">ساقلىغۇچ تۈگەي دەپ قالدى</string>
+ <string name="low_internal_storage_view_text">سىستېمىنىڭ بەزى ئىقتىدارلىرى ئىشلىمەسلىكى مۇمكىن</string>
+ <string name="app_running_notification_title"><xliff:g id="APP_NAME">%1$s</xliff:g> ئىجرا قىلىنىۋاتىدۇ.</string>
+ <string name="app_running_notification_text">چېكىلسە تەپسىلاتىنى بىلگىلى بولىدۇ ياكى ئەپنى توختىتىدۇ.</string>
+ <string name="ok">جەزملە</string>
+ <string name="cancel">ۋاز كەچ</string>
+ <string name="yes">جەزملە</string>
+ <string name="no">ۋاز كەچ</string>
+ <string name="dialog_alert_title">دىققەت</string>
+ <string name="loading">يۈكلەۋاتىدۇ…</string>
+ <string name="capital_on">ئوچۇق</string>
+ <string name="capital_off">تاقاق</string>
+ <string name="whichApplication">ئىشلىتىدىغان ئەپنى تاللاڭ</string>
+ <string name="alwaysUse">كۆڭۈلدىكى ئەھۋالدا مۇشۇ خىل ئۇسۇلنى ئىشلىتىدۇ.</string>
+ <string name="clearDefaultHintMsg">سىستېما تەڭشەكلەر &gt; ئەپلەر &gt; چۈشۈرگەنلەردىن كۆڭۈلدىكى تەڭشەكنى تازىلايدۇ.</string>
+ <string name="chooseActivity">مەشغۇلات تاللاڭ</string>
+ <string name="chooseUsbActivity">بۇ USB ئۈسكۈنە ئۈچۈن ئەپ تاللاڭ</string>
+ <string name="noApplications">بۇ مەشغۇلاتنى ئىجرا قىلىدىغان ئەپ يوق.</string>
+ <string name="aerr_application">ناھايىتى ئەپسۇس، <xliff:g id="APPLICATION">%1$s</xliff:g> توختىدى.</string>
+ <string name="aerr_process">ناھايىتى ئەپسۇس، <xliff:g id="PROCESS">%1$s</xliff:g> جەريان توختىدى.</string>
+ <string name="anr_activity_application"><xliff:g id="APPLICATION">%2$s</xliff:g> ئىنكاس يوق.\n\nئۇنى تاقامسىز؟</string>
+ <string name="anr_activity_process"><xliff:g id="ACTIVITY">%1$s</xliff:g> پائالىيەتتە ئىنكاس يوق.\n\nئۇنى تاقامسىز؟</string>
+ <string name="anr_application_process"><xliff:g id="APPLICATION">%1$s</xliff:g> ئىنكاس يوق. ئۇنى تاقامسىز؟</string>
+ <string name="anr_process"><xliff:g id="PROCESS">%1$s</xliff:g> جەرياندا ئىنكاس يوق.\n\nئۇنى تاقامسىز؟</string>
+ <string name="force_close">جەزملە</string>
+ <string name="report">دوكلات</string>
+ <string name="wait">كۈت</string>
+ <string name="webpage_unresponsive">بۇ بەتنىڭ ئىنكاسى ئاستىلاپ كەتتى.\n\nئۇنى تاقامسىز؟</string>
+ <string name="launch_warning_title">ئەپ قايتا نىشانلاندى</string>
+ <string name="launch_warning_replace"><xliff:g id="APP_NAME">%1$s</xliff:g> ئىجرا قىلىنىۋاتىدۇ.</string>
+ <string name="launch_warning_original"><xliff:g id="APP_NAME">%1$s</xliff:g> قوزغىتىلدى.</string>
+ <string name="screen_compat_mode_scale">نىسبىتى</string>
+ <string name="screen_compat_mode_show">ھەمىشە كۆرسەت</string>
+ <string name="screen_compat_mode_hint">سىستېما تەڭشەكلەر &gt; ئەپلەر &gt; چۈشۈرگەنلەردىن بۇ ھالەتنى قايتا قوزغىتىدۇ.</string>
+ <string name="smv_application"><xliff:g id="APPLICATION">%1$s</xliff:g> ئەپ (جەريان: <xliff:g id="PROCESS">%2$s</xliff:g>) ئۆزلۈكىدىن ئىجرا قىلىدىغان مەجبۇرىي ھالەت تەدبىرىگە خىلاپلىق قىلدى.</string>
+ <string name="smv_process"><xliff:g id="PROCESS">%1$s</xliff:g> جەريان ئۆزلۈكىدىن ئىجرا قىلىدىغان مەجبۇرىي ھالەت تەدبىرىگە خىلاپلىق قىلدى</string>
+ <string name="android_upgrading_title">Android يۈكسىلىۋاتىدۇ…</string>
+ <string name="android_upgrading_apk"><xliff:g id="NUMBER_1">%2$d</xliff:g> ئەپتىن <xliff:g id="NUMBER_0">%1$d</xliff:g> نى ئەلالاشتۇرۇۋاتىدۇ.</string>
+ <string name="android_upgrading_starting_apps">ئەپنى قوزغىتىۋاتىدۇ.</string>
+ <string name="android_upgrading_complete">قوزغىتىشنى تاماملاۋاتىدۇ.</string>
+ <string name="heavy_weight_notification"><xliff:g id="APP">%1$s</xliff:g> ئىجرا قىلىنىۋاتىدۇ</string>
+ <string name="heavy_weight_notification_detail">چېكىلسە ئەپكە ئالمىشىدۇ</string>
+ <string name="heavy_weight_switcher_title">ئەپ ئالماشتۇرامدۇ؟</string>
+ <string name="heavy_weight_switcher_text">باشقا بىر ئەپ ئىجرا قىلىنىۋاتىدۇ، يېڭى ئەپ ئىجرا قىلىش ئۈچۈن شۇ ئەپنى توختىتىشىڭىز كېرەك.</string>
+ <string name="old_app_action"><xliff:g id="OLD_APP">%1$s</xliff:g> غا قايت</string>
+ <string name="old_app_description">يېڭى ئەپنى قوزغاتما.</string>
+ <string name="new_app_action"><xliff:g id="OLD_APP">%1$s</xliff:g> نى قوزغات</string>
+ <string name="new_app_description">كونا ئەپنى ساقلىمايلا توختات.</string>
+ <string name="sendText">تېكىستكە ئېلىپ بېرىلىدىغان مەشغۇلاتنى تاللاڭ</string>
+ <string name="volume_ringtone">قوڭغۇراق ئاۋازى</string>
+ <string name="volume_music">ۋاسىتە ئاۋازى</string>
+ <string name="volume_music_hint_playing_through_bluetooth">كۆكچىشتا قويۇۋاتىدۇ</string>
+ <string name="volume_music_hint_silent_ringtone_selected">ئۈنسىز قوڭغۇراق تەڭشىكى</string>
+ <string name="volume_call">سۆزلىشىش ئاۋازى</string>
+ <string name="volume_bluetooth_call">كۆكچىش ئىشلەتكەندىكى سۆزلىشىش ئاۋازى</string>
+ <string name="volume_alarm">قوڭغۇراق ئاۋازى</string>
+ <string name="volume_notification">ئۇقتۇرۇش ئاۋازى</string>
+ <string name="volume_unknown">ئاۋاز مىقدارى</string>
+ <string name="volume_icon_description_bluetooth">كۆكچىش ئاۋازى</string>
+ <string name="volume_icon_description_ringer">قوڭغۇراق ئاۋازى</string>
+ <string name="volume_icon_description_incall">چاقىرىش ئاۋازى</string>
+ <string name="volume_icon_description_media">ۋاسىتە ئاۋازى</string>
+ <string name="volume_icon_description_notification">ئۇقتۇرۇش ئاۋازى</string>
+ <string name="ringtone_default">كۆڭۈلدىكى قوڭغۇراق ئاۋازى</string>
+ <string name="ringtone_default_with_actual">كۆڭۈلدىكى قوڭغۇراق ئاۋازى (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)</string>
+ <string name="ringtone_silent">يوق</string>
+ <string name="ringtone_picker_title">قوڭغۇراق ئاۋازى</string>
+ <string name="ringtone_unknown">نامەلۇم قوڭغۇراق ئاۋازى</string>
+ <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
+ <string name="wifi_watchdog_network_disabled">Wi-Fi تورىغا باغلىنالمايدۇ</string>
+ <string name="wifi_watchdog_network_disabled_detailed"> ئىنتېرنېت باغلىنىشى ناچار</string>
+ <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
+ <string name="wifi_p2p_turnon_message">Wi-Fi Direct مەشغۇلاتىنى قوزغات. بۇ مەشغۇلات Wi-Fi خېرىدارى/قىزىق نۇقتا مەشغۇلاتىنى تاقايدۇ.</string>
+ <string name="wifi_p2p_failed_message">Wi-Fi Direct نى قوزغىتالمايدۇ</string>
+ <string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct ئوچۇق</string>
+ <string name="wifi_p2p_enabled_notification_message">چېكىلسە تەڭشەيدۇ</string>
+ <string name="accept">قوشۇل</string>
+ <string name="decline">قوشۇلما</string>
+ <string name="wifi_p2p_invitation_sent_title">تەكلىپ يوللاندى</string>
+ <string name="wifi_p2p_invitation_to_connect_title">باغلىنىش تەكلىپى</string>
+ <string name="wifi_p2p_from_message">يوللىغۇچى:</string>
+ <string name="wifi_p2p_to_message">تاپشۇرۇپ ئالغۇچى:</string>
+ <string name="wifi_p2p_enter_pin_message">لازىملىق PIN نى كىرگۈزۈڭ</string>
+ <string name="wifi_p2p_show_pin_message">PIN:</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet">تاختا كومپيۇتېر <xliff:g id="DEVICE_NAME">%1$s</xliff:g> غا باغلانغاندا Wi-FI باغلىنىشىنى ۋاقىتلىق ئۈزىدۇ</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default">تېلېفون <xliff:g id="DEVICE_NAME">%1$s</xliff:g> غا باغلانغاندا Wi-FI باغلىنىشىنى ۋاقىتلىق ئۈزىدۇ</string>
+ <string name="select_character">ھەرپ قىستۇر</string>
+ <string name="sms_control_title">قىسقا ئۇچۇر يوللاۋاتىدۇ</string>
+ <string name="sms_control_message">&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; كۆپ مىقداردا قىسقا ئۇچۇر يوللاۋاتىدۇ. بۇ ئەپنىڭ قىسقا ئۇچۇر يوللاشنى داۋاملاشتۇرۇشىغا يول قويامسىز؟</string>
+ <string name="sms_control_yes">يول قوي</string>
+ <string name="sms_control_no">رەت قىل</string>
+ <string name="sms_short_code_confirm_message">بىر ئۇچۇرنى &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ئۆزى &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; غا يوللىماقچى.</string>
+ <string name="sms_short_code_confirm_allow">يوللا</string>
+ <string name="sms_short_code_confirm_deny">ۋاز كەچ</string>
+ <string name="sms_short_code_remember_choice">تاللىشىمنى ئەستە تۇت</string>
+ <string name="sms_short_code_remember_undo_instruction">كېيىن بۇنى تەڭشەكلەر › ئەپلەردىن ئۆزگەرتەلەيسىز</string>
+ <string name="sms_short_code_confirm_always_allow">ھەمىشە يول قوي*</string>
+ <string name="sms_short_code_confirm_never_allow">ھەرگىز يول قويما</string>
+ <string name="sim_removed_title">SIM كارتا چىقىرىۋېتىلدى</string>
+ <string name="sim_done_button">تامام</string>
+ <string name="sim_added_title">SIM كارتا قوشۇلدى</string>
+ <string name="sim_restart_button">قايتا قوزغات</string>
+ <string name="time_picker_dialog_title">ۋاقىت تەڭشەك</string>
+ <string name="date_picker_dialog_title">چېسلا تەڭشەك</string>
+ <string name="date_time_set">تەڭشەك</string>
+ <string name="date_time_done">تامام</string>
+ <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff33b5e5">\"يېڭى: \"</font></string>
+ <string name="perms_description_app">تەمىنلىگۈچى <xliff:g id="APP_NAME">%1$s</xliff:g>.</string>
+ <string name="no_permissions">ھىچقانداق ھوقۇق كېرەك ئەمەس</string>
+ <string name="perm_costs_money">بۇنىڭغا چىقىم پەيدا بولۇشى مۇمكىن</string>
+ <string name="usb_storage_activity_title">يۇقىرى سىغىملىق USB ساقلىغۇچ</string>
+ <string name="usb_storage_title">USB ئۇلاندى</string>
+ <string name="usb_storage_message" product="nosdcard">سىز USB ئارقىلىق كومپيۇتېرنى ئۇلىدىڭىز. كومپيۇتېر بىلەن ئاندىرويىد USB ساقلىغۇچ ئارىسىدا ھۆججەت كۆچۈرمەكچى بولسىڭىز، تۆۋەندىكى توپچىنى بېسىڭ.</string>
+ <string name="usb_storage_message" product="default">سىز USB ئارقىلىق كومپيۇتېرنى ئۇلىدىڭىز. كومپيۇتېر بىلەن ئاندىرويىد SD كارتا ئارىسىدا ھۆججەت كۆچۈرمەكچى بولسىڭىز، تۆۋەندىكى توپچىنى بېسىڭ.</string>
+ <string name="usb_storage_button_mount">USB ساقلىغۇچنى ئاچ</string>
+ <string name="usb_storage_error_message" product="nosdcard">USB ساقلىغۇچنى USB ساقلىغۇچ سۈپىتىدە ئاچقاندا مەسىلە كۆرۈلدى.</string>
+ <string name="usb_storage_error_message" product="default">SD كارتىڭىزنى USB ساقلىغۇچ سۈپىتىدە ئاچقاندا مەسىلە كۆرۈلدى.</string>
+ <string name="usb_storage_notification_title">USB ئۇلاندى</string>
+ <string name="usb_storage_notification_message">ھۆججەتنى كومپيۇتېرغا كۆچۈرۈش ياكى كومپيۇتېردىن ساقلىغۇچقا كۆچۈرۈشنى تاللاڭ.</string>
+ <string name="usb_storage_stop_notification_title">USB ساقلىغۇچنى تاقا</string>
+ <string name="usb_storage_stop_notification_message">چېكىسلە USB ساقلىغۇچنى تاقايدۇ.</string>
+ <string name="usb_storage_stop_title">USB ساقلىغۇچ ئىشلىتىلىۋاتىدۇ </string>
+ <string name="usb_storage_stop_message" product="nosdcard">USB ساقلىغۇچنى تاقاشتىن ئىلگىرى، كومپيۇتېردىن Android نىڭ USB ساقلىغۇچنى ئېگەرسىزلەپ (\"قاڭقىت\")قانلىقىڭىزنى تەكشۈرۈڭ.</string>
+ <string name="usb_storage_stop_message" product="default">USB ساقلىغۇچنى تاقاشتىن ئىلگىرى، كومپيۇتېردىن Android نىڭ SD ساقلىغۇچىسىنى ئېگەرسىزلەپ (\"قاڭقىت\")قانلىقىڭىزنى تەكشۈرۈڭ.</string>
+ <string name="usb_storage_stop_button_mount">USB ساقلىغۇچنى تاقا</string>
+ <string name="usb_storage_stop_error_message">USB ساقلىغۇچنى تاقاشتا مەسىلە كۆرۈلدى. USB نى چىقىرىۋەتكەنلىكىڭىزنى تەكشۈرۈپ، قايتا سىناڭ.</string>
+ <string name="dlg_confirm_kill_storage_users_title">USB ساقلىغۇچنى تاقا</string>
+ <string name="dlg_confirm_kill_storage_users_text">ئەگەر سىز USB ساقلىغۇچنى ئاچسىڭىز، ئىشلىتىلىۋاتقان پىروگراممىلار ئىشتىن توختايدۇ ھەم USB نى تاقىغاندىن كېيىن ئاندىن قايتا ئىشلەيدۇ.</string>
+ <string name="dlg_error_title">USB مەشغۇلاتى مەغلۇب بولدى.</string>
+ <string name="dlg_ok">جەزملە</string>
+ <string name="usb_accessory_notification_title">USB زاپچاس سۈپىتىدە باغلاندى</string>
+ <string name="adb_active_notification_title">USB سازلاش ئۇلاندى</string>
+ <string name="adb_active_notification_message">چېكىلسە USB سازلاش چەكلىنىدۇ.</string>
+ <string name="hardware">قاتتىق دېتال</string>
+ <string name="select_keyboard_layout_notification_title">ھەرپتاختا ئورۇنلاشتۇرۇشىنى تاللاڭ.</string>
+ <string name="select_keyboard_layout_notification_message">چېكىپ ھەرپتاختا ئورۇنلاشتۇرۇلۇشىدىن بىرنى تاللاڭ.</string>
+ <string name="fast_scroll_alphabet"> ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="fast_scroll_numeric_alphabet"> 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
+ <string name="candidates_style"><u>"نامزات"</u></string>
+ <string name="ext_media_status_checking">تەكشۈرۈۋاتىدۇ…</string>
+ <string name="activity_list_empty">ماس كەلگۈدەك پائالىيەت تاپالمىدى</string>
+ <string name="permlab_route_media_output">ۋاستە چىقىرىش يولىنى ئۆزگەرت</string>
+ <string name="permdesc_route_media_output">ئەپنىڭ ۋاستە چىقىرىش يولىنى ئۆزگەرتىپ باشقا سىرتقى ئۈسكۈنىگە چىقىرىشىغا يول قويىدۇ.</string>
+ <string name="tutorial_double_tap_to_zoom_message_short">قوش چىكىپ يىراق-يېقىنلىقىنى باشقۇرغىلى بولىدۇ.</string>
+ <string name="gadget_host_error_inflating">ئەپچە قوشالمىدى</string>
+ <string name="ime_action_go">يۆتكەل</string>
+ <string name="ime_action_search">ئىزدە</string>
+ <string name="ime_action_send">يوللا</string>
+ <string name="ime_action_next">كېيىنكى</string>
+ <string name="ime_action_done">تامام</string>
+ <string name="ime_action_previous">ئالدىنقى</string>
+ <string name="ime_action_default">ئىجرا قىل</string>
+ <string name="dial_number_using"><xliff:g id="NUMBER">%s</xliff:g> دا نومۇر بۇرا</string>
+ <string name="create_contact_using"><xliff:g id="NUMBER">%s</xliff:g> دا ئالاقەداش قۇر</string>
+ <string name="grant_credentials_permission_message_header">تۆۋەندىكى بىر ياكى بىرقانچە ئەپ سىزنىڭ ھىساباتىڭىزنى زىيارەت قىلىش ھوقۇقىنى تەلەپ قىلىۋاتىدۇ.</string>
+ <string name="grant_credentials_permission_message_footer">بۇ ئىلتىماسقا يول قويامسىز؟</string>
+ <string name="grant_permissions_header_text">ئىلتىماسقا يول قوي</string>
+ <string name="allow">يول قوي</string>
+ <string name="deny">رەت قىل</string>
+ <string name="permission_request_notification_title">ئىلتىماس قىلغان ھوقۇق</string>
+ <string name="permission_request_notification_with_subtitle"><xliff:g id="ACCOUNT">%s</xliff:g> ھېساباتقا\nھوقۇق ئىلتىماس قىلدى.</string>
+ <string name="input_method_binding_label">كىرگۈزگۈچ</string>
+ <string name="sync_binding_label">قەدەمداش</string>
+ <string name="accessibility_binding_label">قوشۇمچە ئىقتىدار</string>
+ <string name="wallpaper_binding_label">تام قەغىزى</string>
+ <string name="chooser_wallpaper">تام قەغەز ئۆزگەرت</string>
+ <string name="notification_listener_binding_label">ئۇقتۇرۇش تىڭشىغۇچ</string>
+ <string name="vpn_title">VPN ئاكتىپلاندى</string>
+ <string name="vpn_title_long">VPN نى <xliff:g id="APP">%s</xliff:g> ئاكتىپلىدى</string>
+ <string name="vpn_text">چېكىلسە تورنى باشقۇرىدۇ.</string>
+ <string name="vpn_text_long"><xliff:g id="SESSION">%s</xliff:g> غا باغلاندى. چېكىلسە تورنى باشقۇرىدۇ.</string>
+ <string name="vpn_lockdown_connecting">ھەمىشە ئوچۇق VPN غا باغلىنىۋاتىدۇ…</string>
+ <string name="vpn_lockdown_connected">ھەمىشە ئوچۇق VPN غا باغلاندى</string>
+ <string name="vpn_lockdown_error">ھەمىشە ئوچۇق VPN خاتالىقى</string>
+ <string name="vpn_lockdown_config">چېكىلسە سەپلەيدۇ</string>
+ <string name="upload_file">ھۆججەت تاللاڭ</string>
+ <string name="no_file_chosen">ھۆججەت تاللانمىغان</string>
+ <string name="reset">ئەسلىگە قايتۇر</string>
+ <string name="submit">تاپشۇر</string>
+ <string name="car_mode_disable_notification_title">ماشىنا ھالىتى قوزغىتىلدى</string>
+ <string name="car_mode_disable_notification_message">چېكىلسە ماشىنا ھالىتىدىن چېكىنىدۇ.</string>
+ <string name="tethered_notification_title">USB غا باغلاش ياكى قىزىق نۇقتىنى قوزغىتىش</string>
+ <string name="tethered_notification_message">چېكىسلە تەڭشەيدۇ.</string>
+ <string name="back_button_label">قايت</string>
+ <string name="next_button_label">كېيىنكى</string>
+ <string name="skip_button_label">ئاتلا</string>
+ <string name="no_matches">ماس كەلگىنى يوق</string>
+ <string name="find_on_page">بەتتىن ئىزدە</string>
+ <string name="action_mode_done">تامام</string>
+ <string name="progress_erasing" product="nosdcard">USB ساقلىغۇچنى ئۆچۈرۈۋاتىدۇ…</string>
+ <string name="progress_erasing" product="default">SD كارتىنى ئۆچۈرۈۋاتىدۇ…</string>
+ <string name="share">ھەمبەھىر</string>
+ <string name="find">ئىزدە</string>
+ <string name="websearch">توردىن ئىزدە</string>
+ <string name="find_next">كېيىنكىنى ئىزدە</string>
+ <string name="find_previous">ئالدىنقىنى ئىزدە</string>
+ <string name="gpsNotifTicker"><xliff:g id="NAME">%s</xliff:g> نىڭ ئورۇن ئىلتىماسى</string>
+ <string name="gpsNotifTitle">ئورۇن ئىلتىماسى</string>
+ <string name="gpsNotifMessage">ئىلتىماس قىلغۇچى <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)</string>
+ <string name="gpsVerifYes">ھەئە</string>
+ <string name="gpsVerifNo">ياق</string>
+ <string name="sync_too_many_deletes">ئۆچۈرۈش چېكىدىن ئېشىپ كەتتى</string>
+ <string name="sync_too_many_deletes_desc">ھېسابات <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> نىڭ <xliff:g id="TYPE_OF_SYNC">%1$d</xliff:g> دانە <xliff:g id="NUMBER_OF_DELETED_ITEMS">%2$s</xliff:g> غا ئائىت ئۆچۈرۈلگەن تۈرى بار. قانداق مەشغۇلات قىلىسىز؟</string>
+ <string name="sync_really_delete">تۈرلەرنى ئۆچۈر.</string>
+ <string name="sync_undo_deletes">ئۆچۈرۈشتىن يېنىۋال.</string>
+ <string name="sync_do_nothing">ھازىر ھېچقانداق مەشغۇلات قىلما.</string>
+ <string name="choose_account_label">بىر ھېسابات تاللاڭ</string>
+ <string name="add_account_label">"بىر ھېسابات قوش"</string>
+ <string name="add_account_button_label">ھېسابات قوش</string>
+ <string name="number_picker_increment_button">چوڭايت</string>
+ <string name="number_picker_decrement_button">كىچىكلەت</string>
+ <string name="number_picker_increment_scroll_mode"><xliff:g id="VALUE">%s</xliff:g> نى چېكىپ بېسىڭ.</string>
+ <string name="number_picker_increment_scroll_action">ئۈستىگە سۈرۈلسە قىممىتى ئاشىدۇ، ئاستىغا سۈرۈلسە قىممىتى كېمىيىدۇ.</string>
+ <string name="time_picker_increment_minute_button">مىنۇت ئاشىدۇ</string>
+ <string name="time_picker_decrement_minute_button">مىنۇت كېمىيىدۇ</string>
+ <string name="time_picker_increment_hour_button">سائەت ئاشىدۇ</string>
+ <string name="time_picker_decrement_hour_button">سائەت كېمىيىدۇ</string>
+ <string name="time_picker_increment_set_pm_button">چ ك تەڭشەك</string>
+ <string name="time_picker_decrement_set_am_button">چ ب تەڭشەك</string>
+ <string name="date_picker_increment_month_button">ئاي ئاشىدۇ</string>
+ <string name="date_picker_decrement_month_button">ئاي كېمىيىدۇ</string>
+ <string name="date_picker_increment_day_button">كۈن ئاشىدۇ</string>
+ <string name="date_picker_decrement_day_button">كۈن كېمىيىدۇ</string>
+ <string name="date_picker_increment_year_button">يىل ئاشىدۇ</string>
+ <string name="date_picker_decrement_year_button">يىل كېمىيىدۇ</string>
+ <string name="keyboardview_keycode_alt">Alt</string>
+ <string name="keyboardview_keycode_cancel">ۋاز كەچ</string>
+ <string name="keyboardview_keycode_delete">ئۆچۈر</string>
+ <string name="keyboardview_keycode_done">تامام</string>
+ <string name="keyboardview_keycode_mode_change">ھالەت ئۆزگەرت</string>
+ <string name="keyboardview_keycode_shift">Shift</string>
+ <string name="keyboardview_keycode_enter">Enter</string>
+ <string name="activitychooserview_choose_application">ئەپ تاللاڭ</string>
+ <string name="activitychooserview_choose_application_error">قوزغىتالمايدىغىنى <xliff:g id="application_name" example="Acme">%s</xliff:g></string>
+ <string name="shareactionprovider_share_with">ھەمبەھىر</string>
+ <string name="shareactionprovider_share_with_application"><xliff:g id="APPLICATION_NAME">%s</xliff:g> ئىلە ھەمبەھىر</string>
+ <string name="content_description_sliding_handle">"تۇتقۇچنى سۈرۈڭ. چېكىپ بېسىڭ."</string>
+ <string name="description_target_unlock_tablet">سۈرۈلسە قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyboard_headset_required_to_hear_password">قۇلاقلىق قىستۇرۇلغاندىلا ئاندىن ئىم ئاۋازىنى ئاڭلىغىلى بولىدۇ.</string>
+ <string name="keyboard_password_character_no_headset">چېكىت</string>
+ <string name="action_bar_home_description">يولباشچى باش بەت</string>
+ <string name="action_bar_up_description">ئۈستىگە يولباشچى</string>
+ <string name="action_menu_overflow_description">تېخىمۇ كۆپ تاللانما</string>
+ <string name="action_bar_home_description_format">%1$s, %2$s</string>
+ <string name="action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>
+ <string name="storage_internal">ئىچىدىكى ساقلىغۇچ</string>
+ <string name="storage_sd_card">SD كارتا</string>
+ <string name="storage_usb">USB ساقلىغۇچ</string>
+ <string name="data_usage_warning_title">سانلىق مەلۇمات ئىشلىتىش ئاگاھلاندۇرۇشى</string>
+ <string name="data_usage_warning_body">چېكىلسە ئىشلىتىلىشى ۋە تەڭشەكلەرنى كۆرسىتىدۇ</string>
+ <string name="data_usage_3g_limit_snoozed_title">2G-3G سانلىق مەلۇمات ئېقىمىدىن ئېشىپ كەتتى</string>
+ <string name="data_usage_4g_limit_snoozed_title">4G سانلىق مەلۇمات ئېقىمىدىن ئېشىپ كەتتى</string>
+ <string name="data_usage_wifi_limit_snoozed_title">Wi-Fi سانلىق مەلۇمات ئېقىمىدىن ئېشىپ كەتتى</string>
+ <string name="data_usage_limit_snoozed_body"><xliff:g id="SIZE">%s</xliff:g> بەلگىلەنگەن چەكتىن ئېشىپ كەتتى</string>
+ <string name="data_usage_restricted_title">تەگلىك سانلىق مەلۇماتى چەكلىمىگە ئۇچرايدۇ</string>
+ <string name="data_usage_restricted_body">چېكىلسە چەكلىمە چىقىرىۋېتىلىدۇ.</string>
+ <string name="ssl_certificate">بىخەتەرلىك گۇۋاھنامىسى</string>
+ <string name="ssl_certificate_is_valid">بۇ گۇۋاھنامە كۈچكە ئىگە.</string>
+ <string name="issued_to">تارقىتىلغۇچى:</string>
+ <string name="common_name">ئورتاق ئات:</string>
+ <string name="org_name">تەشكىل:</string>
+ <string name="org_unit">تەشكىل بىرلىكى:</string>
+ <string name="issued_by">تارقاتقۇچى:</string>
+ <string name="validity_period">ئۈنۈملۈكلۈكى:</string>
+ <string name="issued_on">تارقاتقان ۋاقىت:</string>
+ <string name="expires_on">توشىدىغان ۋاقىت:</string>
+ <string name="serial_number">تەرتىپ نومۇرى:</string>
+ <string name="fingerprints">بارماق ئىزى:</string>
+ <string name="sha256_fingerprint">SHA-256 بارماق ئىزى</string>
+ <string name="sha1_fingerprint">SHA-1 بارماق ئىزى</string>
+ <string name="activity_chooser_view_see_all">ھەممىنى كۆرسەت</string>
+ <string name="activity_chooser_view_dialog_title_default">پائالىيەت تاللاڭ</string>
+ <string name="share_action_provider_share_with">ھەمبەھىر</string>
+ <string name="list_delimeter">"« ،»"</string>
+ <string name="sending">يوللاۋاتىدۇ…</string>
+ <string name="launchBrowserDefault">توركۆرگۈ قوزغىتامدۇ؟</string>
+ <string name="SetupCallDefault">چاقىرىشنى قوبۇللامسىز؟</string>
+ <string name="activity_resolver_use_always">ھەمىشە</string>
+ <string name="activity_resolver_use_once">بىر قېتىملا</string>
+ <string name="default_audio_route_name" product="tablet">تاختا كومپيۇتېر</string>
+ <string name="default_audio_route_name" product="default">تېلېفون</string>
+ <string name="default_audio_route_name_headphones">تىڭشىغۇچ</string>
+ <string name="default_audio_route_name_dock_speakers">لەڭگەر ياڭراتقۇ</string>
+ <string name="default_media_route_name_hdmi">HDMI</string>
+ <string name="default_audio_route_category_name">سىستېما</string>
+ <string name="bluetooth_a2dp_audio_route_name">كۆكچىش ئاۋازى</string>
+ <string name="wireless_display_route_description">سىمسىز كۆرسەتكۈچ</string>
+ <string name="media_route_chooser_title">ئۈسكۈنىگە باغلىنىدۇ</string>
+ <string name="media_route_chooser_title_for_remote_display">ئالمىشىش ئېكرانىدىن ئۈسكۈنىگە</string>
+ <string name="media_route_chooser_searching">ئۈسكۈنىلەرنى ئىزدەۋاتىدۇ\u2026</string>
+ <string name="media_route_chooser_extended_settings">تەڭشەكلەر</string>
+ <string name="media_route_controller_disconnect">ئۈز</string>
+ <string name="media_route_status_scanning">تەكشۈرۈۋاتىدۇ…</string>
+ <string name="media_route_status_connecting">باغلىنىۋاتىدۇ…</string>
+ <string name="media_route_status_available">ئىشلىتىلىشچان</string>
+ <string name="media_route_status_not_available">ئىشلەتكىلى بولمايدۇ</string>
+ <string name="media_route_status_in_use">ئىشلىتىلىۋاتىدۇ</string>
+ <string name="display_manager_built_in_display_name">ئىچكى ئېكران</string>
+ <string name="display_manager_hdmi_display_name">بۇ HDMI ئېكران</string>
+ <string name="display_manager_overlay_display_name">دەستىلەنمە ئېكران #<xliff:g id="ID">%1$d</xliff:g></string>
+ <string name="display_manager_overlay_display_title"><xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi</string>
+ <string name="display_manager_overlay_display_secure_suffix">، بىخەتەرلىك</string>
+ <string name="kg_forgot_pattern_button_text">ئەندىزە ئۇنتۇلغان</string>
+ <string name="kg_wrong_pattern">ئەندىزە خاتا</string>
+ <string name="kg_wrong_password">ئىم خاتا</string>
+ <string name="kg_wrong_pin">بۇ PIN خاتا</string>
+ <string name="kg_too_many_failed_attempts_countdown"><xliff:g id="NUMBER">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_pattern_instructions">قۇلۇپ ئاچىدىغان ئەندىزە سىزىڭ</string>
+ <string name="kg_sim_pin_instructions">كىرگۈزىدىغىنىڭىز SIM PIN</string>
+ <string name="kg_pin_instructions">كىرگۈزىدىغىنىڭىز PIN</string>
+ <string name="kg_password_instructions">ئىم كىرگۈزۈڭ</string>
+ <string name="kg_puk_enter_puk_hint">بۇ SIM كارتا توختىتىلغان. PUK كودى كىرگۈزۈلگەندىلا ئاندىن ئىشلەتكىلى بولىدۇ. مۇناسىۋەتلىك تەپسىلاتلار ئۈچۈن مۇلازىمەت تەمىنلىگۈچىڭىز بىلەن ئالاقە قىلىڭ.</string>
+ <string name="kg_puk_enter_pin_hint">لازىملىق PIN كودىنى كىرگۈزۈڭ</string>
+ <string name="kg_enter_confirm_pin_hint">لازىملىق PIN كودىنى جەزملەڭ</string>
+ <string name="kg_sim_unlock_progress_dialog_message">SIM كارتا قۇلۇپىنى ئېچىۋاتىدۇ…</string>
+ <string name="kg_password_wrong_pin_code">PIN كودى خاتا.</string>
+ <string name="kg_invalid_sim_pin_hint">4-8 خانىلىق PIN نى كىرگۈزۈڭ.</string>
+ <string name="kg_invalid_puk">توغرا PUK كودىنى قايتا كىرگۈزۈڭ. ئەگەر خاتا كىرگۈزۈشنىڭ قېتىم سانى بەك كۆپ بولۇپ كەتسە SIM كارتا مەڭگۈلۈك توختىتىلىدۇ.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">بۇ PIN كودى ماسلاشمىدى</string>
+ <string name="kg_login_too_many_attempts">ئەندىزىسىنى سىناش قېتىم سانى بەك كۆپ بولۇپ كەتتى</string>
+ <string name="kg_login_instructions">قۇلۇپ ئېچىشتا، Google ھېساباتىڭىزدا تىزىمغا كىرىڭ</string>
+ <string name="kg_login_username_hint">ئىشلەتكۈچى ئاتى(تورخەت)</string>
+ <string name="kg_login_password_hint">ئىم</string>
+ <string name="kg_login_submit_button">تىزىمغا كىر</string>
+ <string name="kg_login_invalid_input">ئىشلەتكۈچى ئاتى ۋە ياكى ئىم خاتا.</string>
+ <string name="kg_login_account_recovery_hint">ئىشلەتكۈچى ئاتىڭىز ياكى ئىمنى ئۇنۇتتىڭىزمۇ؟\n\"<b>"google.com/accounts/recovery"</b>\" زىيارەت قىلىڭ.</string>
+ <string name="kg_login_checking_password">ھېساباتنى تەكشۈرۈۋاتىدۇ…</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">سىز PIN نى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا كىرگۈزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">سىز قۇلۇپ ئېچىش ئىمنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا كىرگۈزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet">سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تاختا كومپيۇتېرنى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default">سىز تېلېفون قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تېلېفوننى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ.</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet">سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. تاختا كومپيۇتېر زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، </string>
+ <string name="kg_failed_attempts_now_wiping" product="default">سىز تېلېفون قۇلۇپىنى ئېچىشنى <xliff:g id="NUMBER">%d</xliff:g> قېتىم خاتا سىنىدىڭىز. تېلېفون زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، </string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما تورخەت ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ.\n\nيەنە <xliff:g id="NUMBER_2">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما تورخەت ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تېلېفون قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ.\n\nيەنە <xliff:g id="NUMBER_2">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_text_message_separator" product="default">" — "</string>
+ <string name="kg_reordering_delete_drop_target_text">چىقىرىۋەت</string>
+ <string name="continue_to_enable_accessibility">ئىككى بارماقنى بېسىپ تۇرغاندا قوشۇمچە ئىقتىدارنى قوزغىتىدۇ.</string>
+ <string name="accessibility_enabled">قوشۇمچە ئىقتىدار قوزغىتىلدى.</string>
+ <string name="enable_accessibility_canceled">قوشۇمچە ئىقتىدار بىكار قىلىندى.</string>
+ <string name="user_switched">نۆۋەتتىكى ئىشلەتكۈچى <xliff:g id="NAME">%1$s</xliff:g>.</string>
+ <string name="owner_name" msgid="3879126011135546571">ئىگىدار</string>
+ <string name="error_message_title">خاتالىق</string>
+ <string name="app_not_found">بۇ مەشغۇلاتنى بىر تەرەپ قىلىدىغان ئەپ يوق</string>
+ <string name="revoke">قايتۇرۇۋال</string>
+ <string name="mediasize_iso_a0">ISO A0</string>
+ <string name="mediasize_iso_a1">ISO A1</string>
+ <string name="mediasize_iso_a2">ISO A2</string>
+ <string name="mediasize_iso_a3">ISO A3</string>
+ <string name="mediasize_iso_a4">ISO A4</string>
+ <string name="mediasize_iso_a5">ISO A5</string>
+ <string name="mediasize_iso_a6">ISO A6</string>
+ <string name="mediasize_iso_a7">ISO A7</string>
+ <string name="mediasize_iso_a8">ISO A8</string>
+ <string name="mediasize_iso_a9">ISO A9</string>
+ <string name="mediasize_iso_a10">ISO A10</string>
+ <string name="mediasize_iso_b0">ISO B0</string>
+ <string name="mediasize_iso_b1">ISO B1</string>
+ <string name="mediasize_iso_b2">ISO B2</string>
+ <string name="mediasize_iso_b3">ISO B3</string>
+ <string name="mediasize_iso_b4">ISO B4</string>
+ <string name="mediasize_iso_b5">ISO B5</string>
+ <string name="mediasize_iso_b6">ISO B6</string>
+ <string name="mediasize_iso_b7">ISO B7</string>
+ <string name="mediasize_iso_b8">ISO B8</string>
+ <string name="mediasize_iso_b9">ISO B9</string>
+ <string name="mediasize_iso_b10">ISO B10</string>
+ <string name="mediasize_iso_c0">ISO C0</string>
+ <string name="mediasize_iso_c1">ISO C1</string>
+ <string name="mediasize_iso_c2">ISO C2</string>
+ <string name="mediasize_iso_c3">ISO C3</string>
+ <string name="mediasize_iso_c4">ISO C4</string>
+ <string name="mediasize_iso_c5">ISO C5</string>
+ <string name="mediasize_iso_c6">ISO C6</string>
+ <string name="mediasize_iso_c7">ISO C7</string>
+ <string name="mediasize_iso_c8">ISO C8</string>
+ <string name="mediasize_iso_c9">ISO C9</string>
+ <string name="mediasize_iso_c10">ISO C10</string>
+ <string name="mediasize_na_letter">خەت-چەك</string>
+ <string name="mediasize_na_gvrnmt_letter">ھۆكۈمەت خەت-چەك</string>
+ <string name="mediasize_na_legal">Legal</string>
+ <string name="mediasize_na_junior_legal">Junior Legal</string>
+ <string name="mediasize_na_ledger">Ledger</string>
+ <string name="mediasize_na_tabloid">Tabloid</string>
+ <string name="mediasize_na_index_3x5">Index Card 3 x 5</string>
+ <string name="mediasize_na_index_4x6">Index Card 4 x 6</string>
+ <string name="mediasize_na_index_5x8">Index Card 5 x 8</string>
+ <string name="mediasize_na_monarch">Monarch</string>
+ <string name="mediasize_na_quarto">Quarto</string>
+ <string name="mediasize_na_foolscap">Foolscap</string>
+ <string name="mediasize_chinese_roc_8k">ROC 8K</string>
+ <string name="mediasize_chinese_roc_16k">ROC 16K</string>
+ <string name="mediasize_chinese_prc_1">PRC 1</string>
+ <string name="mediasize_chinese_prc_2">PRC 2</string>
+ <string name="mediasize_chinese_prc_3">PRC 3</string>
+ <string name="mediasize_chinese_prc_4">PRC 4</string>
+ <string name="mediasize_chinese_prc_5">PRC 5</string>
+ <string name="mediasize_chinese_prc_6">PRC 6</string>
+ <string name="mediasize_chinese_prc_7">PRC 7</string>
+ <string name="mediasize_chinese_prc_8">PRC 8</string>
+ <string name="mediasize_chinese_prc_9">PRC 9</string>
+ <string name="mediasize_chinese_prc_10">PRC 10</string>
+ <string name="mediasize_chinese_prc_16k">PRC 16K</string>
+ <string name="mediasize_chinese_om_pa_kai">8 كەسلەم</string>
+ <string name="mediasize_chinese_om_dai_pa_kai">چوڭ 8 كەسلەم</string>
+ <string name="mediasize_chinese_om_jurro_ku_kai">16 كەسلەم</string>
+ <string name="mediasize_japanese_jis_b10">JIS B10</string>
+ <string name="mediasize_japanese_jis_b9">JIS B9</string>
+ <string name="mediasize_japanese_jis_b8">JIS B8</string>
+ <string name="mediasize_japanese_jis_b7">JIS B7</string>
+ <string name="mediasize_japanese_jis_b6">JIS B6</string>
+ <string name="mediasize_japanese_jis_b5">JIS B5</string>
+ <string name="mediasize_japanese_jis_b4">JIS B4</string>
+ <string name="mediasize_japanese_jis_b3">JIS B3</string>
+ <string name="mediasize_japanese_jis_b2">JIS B2</string>
+ <string name="mediasize_japanese_jis_b1">JIS B1</string>
+ <string name="mediasize_japanese_jis_b0">JIS B0</string>
+ <string name="mediasize_japanese_jis_exec">JIS Exec</string>
+ <string name="mediasize_japanese_chou4">Chou4</string>
+ <string name="mediasize_japanese_chou3">Chou3</string>
+ <string name="mediasize_japanese_chou2">Chou2</string>
+ <string name="mediasize_japanese_hagaki">Hagaki</string>
+ <string name="mediasize_japanese_oufuku">Oufuku</string>
+ <string name="mediasize_japanese_kahu">Kahu</string>
+ <string name="mediasize_japanese_kaku2">Kaku2</string>
+ <string name="mediasize_japanese_you4">You4</string>
+ <string name="mediasize_unknown_portrait">يوچۇن بويىغا</string>
+ <string name="mediasize_unknown_landscape">يوچۇن توغرىسىغا</string>
+ <string name="write_fail_reason_cancelled">ۋاز كەچتى</string>
+ <string name="write_fail_reason_cannot_write">مەزمۇن يازغاندا خاتالىق كۆرۈلدى</string>
+ <string name="reason_unknown">يوچۇن</string>
+ <string name="reason_service_unavailable">بېسىش مۇلازىمىتى قوزغىتىلمىغان</string>
+ <string name="print_service_installed_title"><xliff:g id="NAME">%s</xliff:g> مۇلازىمىتى ئورنىتىلدى</string>
+ <string name="print_service_installed_message">چېكىلسە قوزغىتىدۇ</string>
+ <string name="restr_pin_enter_admin_pin">باشقۇرغۇچى PIN نى كىرگۈزۈڭ</string>
+ <string name="restr_pin_enter_pin">كىرگۈزىدىغىنىڭىز PIN</string>
+ <string name="restr_pin_incorrect">خاتا</string>
+ <string name="restr_pin_enter_old_pin">نۆۋەتتىكى PIN:</string>
+ <string name="restr_pin_enter_new_pin">يېڭى PIN</string>
+ <string name="restr_pin_confirm_pin">يېڭى PIN جەزملە</string>
+ <string name="restr_pin_create_pin">بىر PIN كودى قۇرۇپ، باشقىلارنىڭ ئۆزگەرتىشىنى چەكلەيدۇ</string>
+ <string name="restr_pin_error_doesnt_match">PIN ماس كەلمىدى، قايتا سىناڭ.</string>
+ <string name="restr_pin_error_too_short">PIN بەك قىسقا. ئاز دېگەندە 4 خانە سان بولۇشى كېرەك.</string>
+ <string name="restr_pin_try_later">سەل تۇرۇپ قايتا سىناڭ</string>
+ <string name="zen_mode_feature_name">ئاۋارە قىلماڭ</string>
+ <string name="floating_toolbar_open_overflow_description">تېخىمۇ كۆپ تاللانما</string>
+</resources>
diff --git a/core/res/res/values-uk/cm_strings.xml b/core/res/res/values-uk/cm_strings.xml
new file mode 100644
index 0000000..368219f
--- /dev/null
+++ b/core/res/res/values-uk/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Скріншот</string>
+ <string name="permlab_receiveProtectedSms">отримувати захищені SMS</string>
+ <string name="permdesc_receiveProtectedSms">Дозволяє програмі отримувати захищені SMS.</string>
+ <string name="permlab_modifyProtectedSmsList">змінювати список захищених SMS</string>
+ <string name="permdesc_modifyProtectedSmsList">Дозволяє програмі змінювати список адрес захищених SMS.</string>
+ <string name="permgrouplab_security">Безпека</string>
+ <string name="permgroupdesc_security">Дозволи, пов\'язані з безпекою даних на пристрії.</string>
+ <string name="permlab_readPhoneBlacklist">перегляд чорного списку</string>
+ <string name="permdesc_readPhoneBlacklist">Дозволяє програмі читати інформацію про список абонентів, від яких заблоковані вхідні дзвінки або повідомлення.</string>
+ <string name="permlab_changePhoneBlacklist">зміна чорного списку</string>
+ <string name="permdesc_changePhoneBlacklist">Дозволяє програмі змінювати список абонентів, від яких заблоковані вхідні дзвінки або повідомлення.</string>
+ <string name="permlab_setKeyguardWallpaper">встановлення шпалер екрану блокування</string>
+ <string name="permdesc_setKeyguardWallpaper">Дозволяє програмі міняти шпалери екрану блокування.</string>
+ <string name="global_action_reboot">Перезавантаження</string>
+ <string name="global_action_current_user">Поточний</string>
+ <string name="reboot_reboot">Перезавантаження</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">Швидке перезавантаження</string>
+ <string name="reboot_title">Перезавантаження</string>
+ <string name="reboot_confirm" product="tablet">Ваш планшет перезавантажиться.</string>
+ <string name="reboot_confirm" product="default">Ваш телефон перезавантажиться.</string>
+ <string name="reboot_progress">Перезавантаження\u2026</string>
+ <string name="app_killed_message">Програму закрито</string>
+ <string name="adb_net_active_notification_title">ADB по мережі увімкнено</string>
+ <string name="adb_both_active_notification_title">ADB по USB та мережі увімкнено</string>
+ <string name="adb_active_generic_notification_message">Торкніться, аби вимкнути налагодження.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB та мережі</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Мережа</string>
+ <string name="permlab_interceptPackageLaunch">Перехоплення запуску додатку</string>
+ <string name="stylus_app_not_installed">%s не встановлено</string>
+ <string name="silent_mode_priority">Пріоритет</string>
+ <string name="silent_mode_none">Немає</string>
+ <string name="subscription_change_disabled_wifi_ap">Точку доступу Wi-Fi вимкнено через зміну SIM-картки</string>
+ <string name="notify_turn_wifi_off_title">Вимкнути Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">увімк. або вимк. Сторожа Приватності</string>
+ <string name="permdesc_changePrivacyGuardState">Програма може вибрати, чи буде друга програма працювати в захищеному режимі. Коли програму запущено в захищеному режимі, вона не отримає доступ до персональних даних, таких як контакти, повідомлення чи журнал дзвінків.</string>
+ <string name="privacy_guard_notification">Сторож Приватності активний</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> буде заборонено доступ до персональних даних</string>
+ <string name="privacy_guard_dialog_title">Сторож Приватності</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> намагається <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Запам\'ятати мій вибір</string>
+ <string name="app_ops_access_camera">доступ до камери</string>
+ <string name="app_ops_access_location">доступ до місцезнаходження</string>
+ <string name="app_ops_access_notifications">читати ваші сповіщення</string>
+ <string name="app_ops_activate_vpn">активувати VPN</string>
+ <string name="app_ops_auto_start">запуск при включені пристрою</string>
+ <string name="app_ops_delete_call_log">видалити журнал викликів</string>
+ <string name="app_ops_delete_contacts">видалити контакти</string>
+ <string name="app_ops_delete_mms">видалити MMS-повідомлення</string>
+ <string name="app_ops_delete_sms">видалити SMS-повідомлення</string>
+ <string name="app_ops_draw_on_top">показувати вікна поверх</string>
+ <string name="app_ops_get_usage_stats">отримувати статистику використання програм</string>
+ <string name="app_ops_keep_device_awake">заборонити пристрою переходити в сплячий режим</string>
+ <string name="app_ops_make_phone_call">робити телефонні дзвінки</string>
+ <string name="app_ops_modify_calendar">змінювати дані календаря</string>
+ <string name="app_ops_modify_call_log">змінювати дані списку дзвінків</string>
+ <string name="app_ops_modify_clipboard">змінювати вміст буфера обміну</string>
+ <string name="app_ops_modify_contacts">змінювати дані контактів</string>
+ <string name="app_ops_modify_settings">змінювати системні налаштування</string>
+ <string name="app_ops_mute_unmute_microphone">вимк./увімк. мікрофон</string>
+ <string name="app_ops_play_audio">відтворювати аудіо</string>
+ <string name="app_ops_post_notification">виводити сповіщення</string>
+ <string name="app_ops_project_media">project media</string>
+ <string name="app_ops_read_calendar">читати дані календаря</string>
+ <string name="app_ops_read_call_log">читати журнал дзвінків</string>
+ <string name="app_ops_read_clipboard">читати буфер обміну</string>
+ <string name="app_ops_read_contacts">читати дані ваших контактів</string>
+ <string name="app_ops_read_mms">читати ваші MMS-повідомлення</string>
+ <string name="app_ops_read_sms">читати ваші SMS-повідомлення</string>
+ <string name="app_ops_receive_sms">отримувати SMS-повідомлення</string>
+ <string name="app_ops_record_audio">запис аудіо</string>
+ <string name="app_ops_send_mms">надсилати MMS-повідомлення</string>
+ <string name="app_ops_send_sms">надсилати SMS-повідомлення</string>
+ <string name="app_ops_start_at_bootup">запуск при включені пристрою</string>
+ <string name="app_ops_toast_window">показувати спливаючі сповіщення</string>
+ <string name="app_ops_toggle_bluetooth">увімк. або вимк. Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">Мобільні дані</string>
+ <string name="app_ops_toggle_nfc">увімк. вимк. NFC</string>
+ <string name="app_ops_toggle_wifi">Переключити Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">керування гучністю будильника</string>
+ <string name="app_ops_use_audio_focus">керування аудіо-фокусом</string>
+ <string name="app_ops_use_bluetooth_volume">керування гучністю Bluetooth</string>
+ <string name="app_ops_use_master_volume">керування загальною гучністю</string>
+ <string name="app_ops_use_media_buttons">використовувати кнопки мультимедіа</string>
+ <string name="app_ops_use_media_volume">керування гучністю медіа</string>
+ <string name="app_ops_use_notification_volume">керування гучністю сповіщень</string>
+ <string name="app_ops_use_ring_volume">керування гучністю дзвінка</string>
+ <string name="app_ops_use_vibrate">використовувати вібровідгук</string>
+ <string name="app_ops_use_voice_volume">отримати управління гучністю при розмові</string>
+ <string name="app_ops_write_mms">створити MMS-повідомлення</string>
+ <string name="app_ops_write_sms">створити SMS-повідомлення</string>
+ <string name="app_ops_use_fingerprint">використовувати відбитки пальців</string>
+ <string name="app_ops_add_voicemail">Додати голосове повідомлення</string>
+ <string name="app_ops_read_phone_state">Доступ до стану телефону</string>
+ <string name="app_ops_scan_wifi">Сканувати Wi-Fi мережі</string>
+ <string name="app_ops_change_wallpaper">зміна шпалер</string>
+ <string name="app_ops_assist_structure">Використовувати допоміжну структуру</string>
+ <string name="app_ops_assist_screenshot">Скріншот</string>
+ <string name="app_ops_use_body_sensors">Використовувати датчики</string>
+ <string name="app_ops_read_cell_broadcasts">Широкомовні повідомлення</string>
+ <string name="app_ops_mock_location">Фіктивне місцезнаходження</string>
+ <string name="app_ops_read_external_storage">Зчитати дані з карти пам\'яті</string>
+ <string name="app_ops_write_external_storage">Записати дані на карту пам\'яті</string>
+ <string name="app_ops_turn_on_screen">Увімкнути екран</string>
+ <string name="app_ops_get_accounts">Отримати інформацію про акаунти</string>
+ <string name="app_ops_wifi_change">Змінити стан Wi-Fi</string>
+ <string name="app_ops_su">отримати root-доступ</string>
+ <string name="lock_to_app_toast_no_navbar">Щоб відкріпити цей екран, торкніться й утримуйте кнопку назад.</string>
+ <string name="live_display_auto">Автоматично</string>
+ <string name="live_display_auto_summary">Автоматичне підлаштування температури кольору екрана після сходу та заходу сонця</string>
+ <string name="live_display_off">Вимк</string>
+ <string name="live_display_off_summary">Вимкнути авторегулювання</string>
+ <string name="live_display_day">День</string>
+ <string name="live_display_day_summary">Використовувати параметри для денного освітлення</string>
+ <string name="live_display_night">Ніч</string>
+ <string name="live_display_night_summary">Використовувати параметри для нічного освітлення</string>
+ <string name="live_display_outdoor">Надворі (яскраве сонце)</string>
+ <string name="live_display_outdoor_summary">Використовувати параметри для яскравого освітлення надворі</string>
+ <string name="live_display_hint">LiveDisplay допоможе зменшити навантаження на зір та покращить Ваш сон. Натисніть тут, щоб спробувати його!</string>
+ <string name="tethered_notification_no_device_message">Немає під\'єднаного пристрою</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> підключений пристрій</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> підключених пристроїв</string>
+ <string name="notify_package_component_protected_title">Запуск програми заборонений</string>
+ <string name="notify_package_component_protected_text">Запуск <xliff:g id="app_name">%1$s</xliff:g> заблоковано. Натисніть, щоб ввести пароль і запустити програму.</string>
+ <string name="notify_battery_fully_charged_title">Батарея повністю заряджена</string>
+ <string name="notify_battery_fully_charged_text">Від’єднайте зарядку задля покращення витривалості батареї.</string>
+</resources>
diff --git a/core/res/res/values-vi/cm_strings.xml b/core/res/res/values-vi/cm_strings.xml
new file mode 100644
index 0000000..2aab8bc
--- /dev/null
+++ b/core/res/res/values-vi/cm_strings.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">Ảnh chụp màn hình</string>
+ <string name="permlab_receiveProtectedSms">nhận SMS được bảo vệ</string>
+ <string name="permdesc_receiveProtectedSms">Cho phép ứng dụng nhận tin nhắn SMS đến được bảo vệ.</string>
+ <string name="permlab_modifyProtectedSmsList">thay đổi danh sách SMS được bảo vệ</string>
+ <string name="permdesc_modifyProtectedSmsList">Cho phép ứng dụng sửa đổi danh sách địa chỉ SMS được bảo vệ.</string>
+ <string name="permgrouplab_security">Bảo mật</string>
+ <string name="permgroupdesc_security">Quyền liên quan đến thông tin bảo mật của thiết bị.</string>
+ <string name="permlab_readPhoneBlacklist">đọc danh sách đen của điện thoại</string>
+ <string name="permdesc_readPhoneBlacklist">Cho phép ứng dụng đọc thông tin về các số điện thoại bị chặn cuộc gọi hoặc tin nhắn đến.</string>
+ <string name="permlab_changePhoneBlacklist">thay đổi danh sách đen của điện thoại</string>
+ <string name="permdesc_changePhoneBlacklist">Cho phép ứng dụng thay đổi số điện thoại bị chặn cuộc gọi hoặc tin nhắn đến.</string>
+ <string name="permlab_setKeyguardWallpaper">thiết lập hình nền bảo vệ phím</string>
+ <string name="permdesc_setKeyguardWallpaper">Cho phép ứng dụng thay đổi hình nền màn hình khoá.</string>
+ <string name="global_action_reboot">Khởi động lại</string>
+ <string name="global_action_current_user">Hiện tại</string>
+ <string name="reboot_reboot">Khởi động lại</string>
+ <string name="reboot_recovery">Phục hồi</string>
+ <string name="reboot_bootloader">Trình nạp khởi động</string>
+ <string name="reboot_download">Tải về</string>
+ <string name="reboot_soft">Khởi động lại nhanh</string>
+ <string name="reboot_title">Khởi động lại</string>
+ <string name="reboot_confirm" product="tablet">Máy tính bảng của bạn sẽ khởi động lại.</string>
+ <string name="reboot_confirm" product="default">Điện thoại của bạn sẽ khởi động lại.</string>
+ <string name="reboot_progress">Đang khởi động lại\u2026</string>
+ <string name="app_killed_message">Ứng dụng đã tắt</string>
+ <string name="adb_net_active_notification_title">Đã bật ADB qua mạng</string>
+ <string name="adb_both_active_notification_title">Đã kích hoạt ADB qua USB &amp; mạng</string>
+ <string name="adb_active_generic_notification_message">Chạm để tắt gỡ lỗi.</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; mạng</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Mạng</string>
+ <string name="permlab_interceptPackageLaunch">chặn ứng dụng khởi chạy</string>
+ <string name="stylus_app_not_installed">%s chưa được cài đặt</string>
+ <string name="silent_mode_priority">Ưu tiên</string>
+ <string name="silent_mode_none">Không có</string>
+ <string name="subscription_change_disabled_wifi_ap">Đã vô hiệu hóa điểm truy cập WiFi vì thay đổi đăng ký SIM</string>
+ <string name="notify_turn_wifi_off_title">Tắt WiFi</string>
+ <string name="permlab_changePrivacyGuardState">bật hoặc tắt Bảo vệ quyền riêng tư</string>
+ <string name="permdesc_changePrivacyGuardState">Cho phép ứng dụng thay đổi ứng dụng khác chạy với Bảo vệ quyền riêng tư. Khi một ứng dụng chạy với Bảo vệ quyền riêng tư, nó sẽ không có quyền truy cập dữ liệu cá nhân như số liên lạc, nhật ký cuộc gọi hoặc tin nhắn.</string>
+ <string name="privacy_guard_notification">Bảo vệ quyền riêng tư đang hoạt động</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> sẽ không thể truy cập dữ liệu cá nhân</string>
+ <string name="privacy_guard_dialog_title">Bảo vệ quyền riêng tư</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> muốn <xliff:g id="op">%2$s</xliff:g>.</string>
+ <string name="permission_remember_choice">Nhớ lựa chọn của tôi</string>
+ <string name="app_ops_access_camera">truy cập máy ảnh</string>
+ <string name="app_ops_access_location">truy cập vị trí của bạn</string>
+ <string name="app_ops_access_notifications">đọc thông báo của bạn</string>
+ <string name="app_ops_activate_vpn">kích hoạt VPN</string>
+ <string name="app_ops_auto_start">chạy lúc khởi động</string>
+ <string name="app_ops_delete_call_log">xóa nhật ký cuộc gọi của bạn</string>
+ <string name="app_ops_delete_contacts">xóa danh bạ của bạn</string>
+ <string name="app_ops_delete_mms">xoá tin nhắn MMS của bạn</string>
+ <string name="app_ops_delete_sms">xoá tin nhắn SMS của bạn</string>
+ <string name="app_ops_draw_on_top">hiện cửa sổ trên cùng</string>
+ <string name="app_ops_get_usage_stats">lấy thống kê sử dụng ứng dụng</string>
+ <string name="app_ops_keep_device_awake">giữ thiết bị của bạn sáng</string>
+ <string name="app_ops_make_phone_call">thực hiện cuộc gọi điện thoại</string>
+ <string name="app_ops_modify_calendar">cập nhật lịch của bạn</string>
+ <string name="app_ops_modify_call_log">cập nhật nhật kí cuộc gọi</string>
+ <string name="app_ops_modify_clipboard">sửa đổi bảng tạm</string>
+ <string name="app_ops_modify_contacts">cập nhật danh bạ của bạn</string>
+ <string name="app_ops_modify_settings">cập nhật thiết lập hệ thống</string>
+ <string name="app_ops_mute_unmute_microphone">tắt/bật tiếng micro</string>
+ <string name="app_ops_play_audio">phát âm thanh</string>
+ <string name="app_ops_post_notification">gửi thông báo</string>
+ <string name="app_ops_project_media">chiếu đa phương tiện</string>
+ <string name="app_ops_read_calendar">đọc lịch của bạn</string>
+ <string name="app_ops_read_call_log">đọc nhật kí cuộc gọi</string>
+ <string name="app_ops_read_clipboard">đọc bảng tạm</string>
+ <string name="app_ops_read_contacts">đọc danh bạ của bạn</string>
+ <string name="app_ops_read_mms">đọc tin nhắn MMS của bạn</string>
+ <string name="app_ops_read_sms">đọc tin nhắn SMS của bạn</string>
+ <string name="app_ops_receive_sms">nhận tin nhắn SMS</string>
+ <string name="app_ops_record_audio">ghi âm</string>
+ <string name="app_ops_send_mms">gửi tin nhắn MMS</string>
+ <string name="app_ops_send_sms">gửi tin nhắn SMS</string>
+ <string name="app_ops_start_at_bootup">chạy lúc khởi động</string>
+ <string name="app_ops_toast_window">hiện thông báo nhanh</string>
+ <string name="app_ops_toggle_bluetooth">bật/tắt Bluetooth</string>
+ <string name="app_ops_toggle_nfc">bật/tắt NFC</string>
+ <string name="app_ops_use_alarm_volume">điều khiển âm lượng báo thức</string>
+ <string name="app_ops_use_audio_focus">điều khiển trọng tâm âm thanh</string>
+ <string name="app_ops_use_bluetooth_volume">điều khiển âm lượng Bluetooth</string>
+ <string name="app_ops_use_master_volume">điều khiển âm lượng tổng thể</string>
+ <string name="app_ops_use_media_buttons">sử dụng nút phương tiện</string>
+ <string name="app_ops_use_media_volume">điều khiển âm lượng đa phương tiện</string>
+ <string name="app_ops_use_notification_volume">điều khiển âm lượng thông báo</string>
+ <string name="app_ops_use_ring_volume">điều khiển âm lượng nhạc chuông</string>
+ <string name="app_ops_use_vibrate">dùng phản hồi xúc giác</string>
+ <string name="app_ops_use_voice_volume">điều khiển âm lượng cuộc gọi thoại</string>
+ <string name="app_ops_write_mms">soạn tin nhắn MMS</string>
+ <string name="app_ops_write_sms">soạn tin nhắn SMS</string>
+ <string name="app_ops_su">lấy quyền truy cập root</string>
+ <string name="lock_to_app_toast_no_navbar">Để bỏ ghim màn hình này, hãy chạm và giữ phím Quay lại.</string>
+ <string name="live_display_auto">Tự động</string>
+ <string name="live_display_auto_summary">Tự động chỉnh nhiệt độ màu của màn hình theo ngày và đêm</string>
+ <string name="live_display_off">Tắt</string>
+ <string name="live_display_off_summary">Vô hiệu hoá tất cả điều chỉnh</string>
+ <string name="live_display_day">Ngày</string>
+ <string name="live_display_day_summary">Chỉ sử dụng cài đặt ban ngày</string>
+ <string name="live_display_night">Đêm</string>
+ <string name="live_display_night_summary">Chỉ sử dụng cài đặt ban đêm</string>
+ <string name="live_display_outdoor">Ngoài trời (ánh sáng mặt trời)</string>
+ <string name="live_display_outdoor_summary">Chỉ sử dụng cài đặt ngoài trời</string>
+ <string name="live_display_hint">LiveDisplay có thể giúp giảm mỏi mắt và giúp bạn ngủ vào ban đêm. Nhấn vào đây để thử!</string>
+ <string name="tethered_notification_no_device_message">Không có thiết bị kết nối</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> thiết bị đã kết nối</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> thiết bị đã kết nối</string>
+</resources>
diff --git a/core/res/res/values-zh-rCN/cm_strings.xml b/core/res/res/values-zh-rCN/cm_strings.xml
new file mode 100644
index 0000000..8e8920d
--- /dev/null
+++ b/core/res/res/values-zh-rCN/cm_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">屏幕截图</string>
+ <string name="permlab_receiveProtectedSms">接收受保护的短信</string>
+ <string name="permdesc_receiveProtectedSms">允许应用接收受保护的短信。</string>
+ <string name="permlab_modifyProtectedSmsList">修改受保护的短信列表</string>
+ <string name="permdesc_modifyProtectedSmsList">允许应用修改受保护的短信地址列表。</string>
+ <string name="permgrouplab_security">安全</string>
+ <string name="permgroupdesc_security">与设备安全信息相关的权限。</string>
+ <string name="permlab_readPhoneBlacklist">读取手机黑名单</string>
+ <string name="permdesc_readPhoneBlacklist">允许应用读取有关被阻止来电或信息的电话号码的信息。</string>
+ <string name="permlab_changePhoneBlacklist">更改手机黑名单</string>
+ <string name="permdesc_changePhoneBlacklist">允许应用更改被阻止来电或信息的电话号码。</string>
+ <string name="permlab_setKeyguardWallpaper">设置锁屏壁纸</string>
+ <string name="permdesc_setKeyguardWallpaper">允许应用更改锁屏壁纸。</string>
+ <string name="global_action_reboot">重启</string>
+ <string name="global_action_current_user">当前</string>
+ <string name="reboot_reboot">重启</string>
+ <string name="reboot_recovery">恢复模式</string>
+ <string name="reboot_bootloader">引导程序</string>
+ <string name="reboot_download">下载模式</string>
+ <string name="reboot_soft">软重启</string>
+ <string name="reboot_title">重启</string>
+ <string name="reboot_confirm" product="tablet">您的平板电脑将会重启。</string>
+ <string name="reboot_confirm" product="default">您的手机将会重启。</string>
+ <string name="reboot_progress">正在重启\u2026</string>
+ <string name="app_killed_message">应用已被终止</string>
+ <string name="adb_net_active_notification_title">网络 ADB 调试已启用</string>
+ <string name="adb_both_active_notification_title">USB 和网络 ADB 调试已启用</string>
+ <string name="adb_active_generic_notification_message">触摸以禁用调试。</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; 网络</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">网络</string>
+ <string name="permlab_interceptPackageLaunch">拦截应用启动</string>
+ <string name="stylus_app_not_installed">%s 尚未被安装</string>
+ <string name="silent_mode_priority">优先级</string>
+ <string name="silent_mode_none">无</string>
+ <string name="subscription_change_disabled_wifi_ap">由于 SIM 卡订阅改变,已禁用 Wi-Fi 热点。</string>
+ <string name="notify_turn_wifi_off_title">关闭 Wi-Fi</string>
+ <string name="permlab_changePrivacyGuardState">启用或禁用隐私防护</string>
+ <string name="permdesc_changePrivacyGuardState">允许应用更改其他应用是否启用隐私防护。当一个应用运行时启用了隐私防护,它将不能访问个人数据,如联系人、通话记录、短信。</string>
+ <string name="privacy_guard_notification">隐私防护激活</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> 将不能访问个人数据</string>
+ <string name="privacy_guard_dialog_title">隐私防护</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> 希望 <xliff:g id="op">%2$s</xliff:g>。</string>
+ <string name="permission_remember_choice">记住我的选择</string>
+ <string name="app_ops_access_camera">存取相机</string>
+ <string name="app_ops_access_location">访问你的地理位置信息</string>
+ <string name="app_ops_access_notifications">读取通知</string>
+ <string name="app_ops_activate_vpn">激活一个 VPN</string>
+ <string name="app_ops_auto_start">开机自启动</string>
+ <string name="app_ops_delete_call_log">删除您的所有通话记录</string>
+ <string name="app_ops_delete_contacts">删除您的联系人</string>
+ <string name="app_ops_delete_mms">删除您的彩信</string>
+ <string name="app_ops_delete_sms">删除您的短信</string>
+ <string name="app_ops_draw_on_top">在顶部绘制窗口</string>
+ <string name="app_ops_get_usage_stats">获取应用使用情况统计</string>
+ <string name="app_ops_keep_device_awake">保持设备唤醒</string>
+ <string name="app_ops_make_phone_call">拨打电话</string>
+ <string name="app_ops_modify_calendar">更新你的日历</string>
+ <string name="app_ops_modify_call_log">更新通话记录</string>
+ <string name="app_ops_modify_clipboard">修改剪贴板</string>
+ <string name="app_ops_modify_contacts">更新你的联系人</string>
+ <string name="app_ops_modify_settings">更新系统设置</string>
+ <string name="app_ops_mute_unmute_microphone">麦克风静音 / 解除静音</string>
+ <string name="app_ops_play_audio">播放音频</string>
+ <string name="app_ops_post_notification">发出通知</string>
+ <string name="app_ops_project_media">放映媒体</string>
+ <string name="app_ops_read_calendar">读取你的日历</string>
+ <string name="app_ops_read_call_log">读取你的通话记录</string>
+ <string name="app_ops_read_clipboard">读取你的剪贴板</string>
+ <string name="app_ops_read_contacts">读取你的联系人</string>
+ <string name="app_ops_read_mms">读取你的彩信</string>
+ <string name="app_ops_read_sms">读取你的短信</string>
+ <string name="app_ops_receive_sms">接收短信</string>
+ <string name="app_ops_record_audio">录音</string>
+ <string name="app_ops_send_mms">发送彩信</string>
+ <string name="app_ops_send_sms">发送短信</string>
+ <string name="app_ops_start_at_bootup">开机自启动</string>
+ <string name="app_ops_toast_window">显示提示信息</string>
+ <string name="app_ops_toggle_bluetooth">开启蓝牙</string>
+ <string name="app_ops_toggle_mobile_data">切换移动数据</string>
+ <string name="app_ops_toggle_nfc">切换 NFC</string>
+ <string name="app_ops_toggle_wifi">开关 Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">控制闹铃音量</string>
+ <string name="app_ops_use_audio_focus">控制音频焦点</string>
+ <string name="app_ops_use_bluetooth_volume">控制蓝牙音量</string>
+ <string name="app_ops_use_master_volume">控制主音量</string>
+ <string name="app_ops_use_media_buttons">使用媒体按钮</string>
+ <string name="app_ops_use_media_volume">控制媒体音量</string>
+ <string name="app_ops_use_notification_volume">控制通知音量</string>
+ <string name="app_ops_use_ring_volume">控制铃声音量</string>
+ <string name="app_ops_use_vibrate">使用触觉反馈</string>
+ <string name="app_ops_use_voice_volume">控制语音通话音量</string>
+ <string name="app_ops_write_mms">编写彩信</string>
+ <string name="app_ops_write_sms">编写短信</string>
+ <string name="app_ops_use_fingerprint">使用指纹</string>
+ <string name="app_ops_add_voicemail">添加语音邮件</string>
+ <string name="app_ops_read_phone_state">访问电话状态</string>
+ <string name="app_ops_scan_wifi">扫描 Wi-Fi 网络</string>
+ <string name="app_ops_change_wallpaper">更改壁纸</string>
+ <string name="app_ops_assist_structure">使用协助结构</string>
+ <string name="app_ops_assist_screenshot">屏幕截图</string>
+ <string name="app_ops_use_body_sensors">使用身体传感器</string>
+ <string name="app_ops_read_cell_broadcasts">读取蜂窝广播</string>
+ <string name="app_ops_mock_location">模拟位置</string>
+ <string name="app_ops_read_external_storage">读取外部存储</string>
+ <string name="app_ops_write_external_storage">写入外部存储</string>
+ <string name="app_ops_turn_on_screen">打开屏幕</string>
+ <string name="app_ops_get_accounts">获取设备帐户</string>
+ <string name="app_ops_wifi_change">更改 Wi-Fi 状态</string>
+ <string name="app_ops_su">获取 Root 权限</string>
+ <string name="lock_to_app_toast_no_navbar">要取消固定此屏幕,触摸并按住返回键。</string>
+ <string name="live_display_auto">自动</string>
+ <string name="live_display_auto_summary">在日出和日落后自动调节屏幕色温</string>
+ <string name="live_display_off">关闭</string>
+ <string name="live_display_off_summary">禁用所有调整</string>
+ <string name="live_display_day">白天</string>
+ <string name="live_display_day_summary">仅使用白天设置</string>
+ <string name="live_display_night">夜晚</string>
+ <string name="live_display_night_summary">仅使用夜晚设置</string>
+ <string name="live_display_outdoor">户外(阳光)</string>
+ <string name="live_display_outdoor_summary">仅使用户外设置</string>
+ <string name="live_display_hint">LiveDisplay 可以帮助减少眼睛疲劳,帮助您的夜间睡眠。点击此处来试一试!</string>
+ <string name="tethered_notification_no_device_message">没有已连接设备</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> 个已连接的设备</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> 个已连接的设备</string>
+ <string name="notify_package_component_protected_title">已阻止活动启动</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> 正被保护防止启动。点击以认证并启动应用。</string>
+ <string name="notify_battery_fully_charged_title">电池已完全充满</string>
+ <string name="notify_battery_fully_charged_text">请将您的设备从充电器断开,以便获得更长的电池寿命。</string>
+</resources>
diff --git a/core/res/res/values-zh-rHK/cm_strings.xml b/core/res/res/values-zh-rHK/cm_strings.xml
new file mode 100644
index 0000000..6bbe9b7
--- /dev/null
+++ b/core/res/res/values-zh-rHK/cm_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">螢幕截圖</string>
+ <string name="permlab_receiveProtectedSms">接收受保護的短訊</string>
+ <string name="permdesc_receiveProtectedSms">允許應用程式接收受保護的短訊</string>
+ <string name="permlab_modifyProtectedSmsList">修改受保護的短訊清單</string>
+ <string name="permgrouplab_security">安全性</string>
+ <string name="permgroupdesc_security">與裝置安全性資訊相關的權限。</string>
+ <string name="permlab_readPhoneBlacklist">讀取手機黑名單</string>
+ <string name="permdesc_readPhoneBlacklist">允許應用程式讀取關於被封鎖來電或訊息的電話號碼的資訊。</string>
+ <string name="permlab_changePhoneBlacklist">更改手機黑名單</string>
+ <string name="permdesc_changePhoneBlacklist">允許應用程式更改被封鎖來電或訊息的電話號碼。</string>
+ <string name="permlab_setKeyguardWallpaper">設定鎖定畫面牆紙</string>
+ <string name="permdesc_setKeyguardWallpaper">允許應用程式更改鎖定畫面牆紙。</string>
+ <string name="global_action_reboot">重新啟動</string>
+ <string name="reboot_reboot">重新啟動</string>
+ <string name="reboot_recovery">修復模式</string>
+ <string name="reboot_bootloader">啟動載入程式 (Bootloader)</string>
+ <string name="reboot_download">下載</string>
+ <string name="reboot_soft">軟重新啟動</string>
+ <string name="reboot_confirm" product="tablet">您的平板電腦將重新啟動。</string>
+ <string name="reboot_confirm" product="default">您的電話將重新啟動。</string>
+ <string name="reboot_progress">正在重新啟動\u2026</string>
+ <string name="adb_net_active_notification_title">網絡 ADB 偵錯</string>
+ <string name="adb_both_active_notification_title">USB &amp; 網絡 ADB 偵錯</string>
+ <string name="adb_active_generic_notification_message">觸碰以停用調試。</string>
+ <string name="stylus_app_not_installed">未安裝 %s</string>
+ <string name="silent_mode_priority">優先級</string>
+ <string name="silent_mode_none">無</string>
+ <string name="permlab_changePrivacyGuardState">啟用或停用私隱守衛</string>
+ <string name="permdesc_changePrivacyGuardState">允許應用程式變更其他應用程式執行時是否啟用私隱守衛。當應用程式執行時啟用了私隱守衛,應用程式將無法存取個人資料,例如:聯絡人、通話記錄或訊息。</string>
+ <string name="privacy_guard_notification">私隱守衛啟用</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> 將無法存取個人資料</string>
+ <string name="privacy_guard_dialog_title">私隱守衛</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g>想要<xliff:g id="op">%2$s</xliff:g>。</string>
+ <string name="permission_remember_choice">記住我的選擇</string>
+ <string name="app_ops_access_camera">存取相機</string>
+ <string name="app_ops_access_location">存取您的位置</string>
+ <string name="app_ops_access_notifications">讀取您的通知</string>
+ <string name="app_ops_delete_sms">刪除短訊</string>
+ <string name="app_ops_draw_on_top">在頂部拖動視窗</string>
+ <string name="app_ops_get_usage_stats">獲取應用程式使用狀況統計</string>
+ <string name="app_ops_keep_device_awake">讓您的裝置保持清醒</string>
+ <string name="app_ops_make_phone_call">撥出電話</string>
+ <string name="app_ops_modify_calendar">更新您的日曆</string>
+ <string name="app_ops_modify_call_log">更新通話記錄</string>
+ <string name="app_ops_modify_clipboard">修改剪貼簿</string>
+ <string name="app_ops_modify_contacts">更新您的聯絡人</string>
+ <string name="app_ops_modify_settings">更新系統設定</string>
+ <string name="app_ops_mute_unmute_microphone">麥克風靜音/解除靜音</string>
+ <string name="app_ops_play_audio">播放音頻</string>
+ <string name="app_ops_post_notification">發出通知</string>
+ <string name="app_ops_project_media">媒體投映</string>
+ <string name="app_ops_read_clipboard">讀取剪貼簿</string>
+ <string name="app_ops_read_contacts">讀取您的聯絡人</string>
+ <string name="app_ops_read_mms">讀取您的多媒體短訊</string>
+ <string name="app_ops_read_sms">讀取您的短訊</string>
+ <string name="app_ops_receive_sms">接收短訊</string>
+ <string name="app_ops_record_audio">錄音</string>
+ <string name="app_ops_send_mms">發送多媒體短訊</string>
+ <string name="app_ops_send_sms">發送短訊</string>
+ <string name="app_ops_start_at_bootup">開機時啟動</string>
+ <string name="app_ops_toast_window">顯示彈出訊息</string>
+ <string name="app_ops_toggle_bluetooth">切換藍牙</string>
+ <string name="app_ops_toggle_nfc">切換 NFC</string>
+ <string name="app_ops_use_alarm_volume">控制鬧鐘音量</string>
+ <string name="app_ops_use_audio_focus">控制音訊焦點</string>
+ <string name="app_ops_use_bluetooth_volume">控制藍牙音量</string>
+ <string name="app_ops_use_master_volume">控制主音量</string>
+ <string name="app_ops_use_media_buttons">使用媒體按鈕</string>
+ <string name="app_ops_use_media_volume">控制媒體音量</string>
+ <string name="app_ops_use_notification_volume">控制通知音量</string>
+ <string name="app_ops_use_ring_volume">控制鈴聲音量</string>
+ <string name="app_ops_use_vibrate">使用觸控震動</string>
+ <string name="app_ops_use_voice_volume">控制語音通話音量</string>
+ <string name="app_ops_write_mms">撰寫多媒體短訊</string>
+ <string name="app_ops_write_sms">編寫短訊</string>
+ <string name="lock_to_app_toast_no_navbar">要解鎖此螢幕,觸碰並按住返回鍵。</string>
+ <string name="live_display_auto">自動</string>
+ <string name="live_display_auto_summary">在白天和夜晚自動調節螢幕顏色溫度</string>
+ <string name="live_display_off">關閉</string>
+ <string name="live_display_off_summary">停用所有調整</string>
+ <string name="live_display_day">白天</string>
+ <string name="live_display_day_summary">僅使用白天設定</string>
+ <string name="live_display_night">夜間</string>
+ <string name="live_display_night_summary">僅使用夜間設定</string>
+ <string name="live_display_outdoor">戶外(陽光)</string>
+ <string name="live_display_outdoor_summary">僅使用戶外設定</string>
+ <string name="live_display_hint">LiveDisplay 可有助減少眼睛疲勞,有助晚上睡眠。按下此處試試!</string>
+ <string name="tethered_notification_no_device_message">沒有已連接的裝置</string>
+</resources>
diff --git a/core/res/res/values-zh-rTW/cm_strings.xml b/core/res/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 0000000..0c55eaa
--- /dev/null
+++ b/core/res/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="global_action_screenshot">螢幕擷取</string>
+ <string name="permlab_receiveProtectedSms">接收受保護的簡訊</string>
+ <string name="permdesc_receiveProtectedSms">允許應用程式接收受保護的簡訊。</string>
+ <string name="permlab_modifyProtectedSmsList">修改受保護的簡訊清單</string>
+ <string name="permdesc_modifyProtectedSmsList">允許應用程式修改受保護的簡訊地址清單。</string>
+ <string name="permgrouplab_security">安全</string>
+ <string name="permgroupdesc_security">與裝置安全資訊相關的權限。</string>
+ <string name="permlab_readPhoneBlacklist">讀取手機黑名單</string>
+ <string name="permdesc_readPhoneBlacklist">允許應用程式讀取關於被封鎖來電或訊息的電話號碼的資訊。</string>
+ <string name="permlab_changePhoneBlacklist">變更手機黑名單</string>
+ <string name="permdesc_changePhoneBlacklist">允許應用程式變更被封鎖來電或訊息的電話號碼。</string>
+ <string name="permlab_setKeyguardWallpaper">設定鎖定畫面桌布</string>
+ <string name="permdesc_setKeyguardWallpaper">允許應用程式變更鎖定畫面桌布。</string>
+ <string name="global_action_reboot">重新啟動</string>
+ <string name="global_action_current_user">現在</string>
+ <string name="reboot_reboot">重新啟動</string>
+ <string name="reboot_recovery">Recovery</string>
+ <string name="reboot_bootloader">Bootloader</string>
+ <string name="reboot_download">Download</string>
+ <string name="reboot_soft">軟件重新啟動</string>
+ <string name="reboot_title">重新啟動</string>
+ <string name="reboot_confirm" product="tablet">您的平板電腦將會重新啟動。</string>
+ <string name="reboot_confirm" product="default">您的手機將會重新啟動。</string>
+ <string name="reboot_progress">正在重新啟動\u2026</string>
+ <string name="app_killed_message">已終止應用程式</string>
+ <string name="adb_net_active_notification_title">已啟用網路 ADB</string>
+ <string name="adb_both_active_notification_title">已啟用 USB 及網路 ADB</string>
+ <string name="adb_active_generic_notification_message">輕觸即可停用偵錯。</string>
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB和網路</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">網路</string>
+ <string name="permlab_interceptPackageLaunch">限制應用程式執行</string>
+ <string name="stylus_app_not_installed">未安裝 %s</string>
+ <string name="silent_mode_priority">優先度</string>
+ <string name="silent_mode_none">無</string>
+ <string name="permlab_changePrivacyGuardState">啟用或停用隱私守衛</string>
+ <string name="permdesc_changePrivacyGuardState">允許應用程式變更其他應用程式執行時是否啟用隱私守衛。當應用程式執行時啟用了隱私守衛,它將無法存取個人資料,例如聯絡人、通話記錄或訊息。</string>
+ <string name="privacy_guard_notification">隱私守衛正在運作</string>
+ <string name="privacy_guard_notification_detail">「<xliff:g id="app">%1$s</xliff:g>」將無法存取個人資料</string>
+ <string name="privacy_guard_dialog_title">隱私守衛</string>
+ <string name="privacy_guard_dialog_summary">「<xliff:g id="app">%1$s</xliff:g>」想要<xliff:g id="op">%2$s</xliff:g>。</string>
+ <string name="permission_remember_choice">記住我的選擇</string>
+ <string name="app_ops_access_camera">存取相機</string>
+ <string name="app_ops_access_location">存取您的位置</string>
+ <string name="app_ops_access_notifications">讀取您的通知</string>
+ <string name="app_ops_activate_vpn">啟動 VPN</string>
+ <string name="app_ops_auto_start">開機時啟動</string>
+ <string name="app_ops_delete_call_log">刪除您的通話紀錄</string>
+ <string name="app_ops_delete_contacts">刪除您的連絡人</string>
+ <string name="app_ops_delete_mms">刪除您的多媒體訊息</string>
+ <string name="app_ops_delete_sms">刪除您的簡訊</string>
+ <string name="app_ops_draw_on_top">在頂層繪製視窗</string>
+ <string name="app_ops_get_usage_stats">取得應用程式的使用狀況統計</string>
+ <string name="app_ops_keep_device_awake">讓您的裝置保持清醒</string>
+ <string name="app_ops_make_phone_call">撥打電話</string>
+ <string name="app_ops_modify_calendar">更新您的日曆</string>
+ <string name="app_ops_modify_call_log">更新通話紀錄</string>
+ <string name="app_ops_modify_clipboard">修改剪貼簿</string>
+ <string name="app_ops_modify_contacts">更新您的連絡人資料</string>
+ <string name="app_ops_modify_settings">更新系統設定</string>
+ <string name="app_ops_mute_unmute_microphone">麥克風靜音/解除靜音</string>
+ <string name="app_ops_play_audio">播放音訊</string>
+ <string name="app_ops_post_notification">發佈通知</string>
+ <string name="app_ops_project_media">放映媒體</string>
+ <string name="app_ops_read_calendar">讀取您的日曆</string>
+ <string name="app_ops_read_call_log">讀取通話紀錄</string>
+ <string name="app_ops_read_clipboard">讀取剪貼簿</string>
+ <string name="app_ops_read_contacts">讀取您的聯絡人資料</string>
+ <string name="app_ops_read_mms">讀取您的多媒體簡訊</string>
+ <string name="app_ops_read_sms">讀取您的簡訊</string>
+ <string name="app_ops_receive_sms">接收簡訊</string>
+ <string name="app_ops_record_audio">錄製音訊</string>
+ <string name="app_ops_send_mms">傳送多媒體訊息</string>
+ <string name="app_ops_send_sms">傳送簡訊</string>
+ <string name="app_ops_start_at_bootup">開機時啟動</string>
+ <string name="app_ops_toast_window">顯示彈出信息</string>
+ <string name="app_ops_toggle_bluetooth">開關藍牙</string>
+ <string name="app_ops_toggle_nfc">開關 NFC</string>
+ <string name="app_ops_toggle_wifi">切換 Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">控制鬧鐘音量</string>
+ <string name="app_ops_use_audio_focus">控制音訊焦點</string>
+ <string name="app_ops_use_bluetooth_volume">控制藍牙音量</string>
+ <string name="app_ops_use_master_volume">控制主音量</string>
+ <string name="app_ops_use_media_buttons">使用媒體按鈕</string>
+ <string name="app_ops_use_media_volume">控制媒體音量</string>
+ <string name="app_ops_use_notification_volume">控制通知音量</string>
+ <string name="app_ops_use_ring_volume">控制鈴聲音量</string>
+ <string name="app_ops_use_vibrate">使用觸控震動</string>
+ <string name="app_ops_use_voice_volume">控制語音通話音量</string>
+ <string name="app_ops_write_mms">撰寫多媒體訊息</string>
+ <string name="app_ops_write_sms">撰寫簡訊</string>
+ <string name="app_ops_use_fingerprint">使用指紋</string>
+ <string name="app_ops_add_voicemail">新增語音訊息</string>
+ <string name="app_ops_read_phone_state">存取電話狀態</string>
+ <string name="app_ops_scan_wifi">掃描 Wi-Fi 網路</string>
+ <string name="app_ops_change_wallpaper">變更桌布</string>
+ <string name="app_ops_assist_structure">使用協助工具</string>
+ <string name="app_ops_assist_screenshot">擷取螢幕畫面</string>
+ <string name="app_ops_use_body_sensors">使用人體感應器</string>
+ <string name="app_ops_read_cell_broadcasts">讀取區域廣播</string>
+ <string name="app_ops_mock_location">模擬所在位置</string>
+ <string name="app_ops_read_external_storage">讀取外部儲存空間</string>
+ <string name="app_ops_write_external_storage">寫入外部儲存空間</string>
+ <string name="app_ops_turn_on_screen">開啟螢幕</string>
+ <string name="app_ops_get_accounts">取得裝置帳號</string>
+ <string name="app_ops_wifi_change">變更 Wi-Fi 狀態</string>
+ <string name="app_ops_su">取得 Root 權限</string>
+ <string name="lock_to_app_toast_no_navbar">要解鎖此螢幕,觸摸並按住返回鍵。</string>
+ <string name="live_display_auto">自動</string>
+ <string name="live_display_auto_summary">在白天和夜晚自動調節螢幕顏色溫度</string>
+ <string name="live_display_off">關閉</string>
+ <string name="live_display_off_summary">禁用所有的調整</string>
+ <string name="live_display_day">白天</string>
+ <string name="live_display_day_summary">僅使用白天設定</string>
+ <string name="live_display_night">夜間</string>
+ <string name="live_display_night_summary">僅使用夜間設定</string>
+ <string name="live_display_outdoor">戶外 (陽光)</string>
+ <string name="live_display_outdoor_summary">僅使用戶外設定</string>
+ <string name="live_display_hint">LiveDisplay 可以幫助減少眼睛的疲勞及睡前使用造成的不適。輕觸此處來試試!</string>
+ <string name="tethered_notification_no_device_message">沒有已連接的裝置</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> 個已連接裝置</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> 個已連接裝置</string>
+ <string name="notify_package_component_protected_title">已阻止啟動活動</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s </xliff:g> 正被防止啟動。按一下以進行身份驗證並啟動應用程式。</string>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2828d21..e17b017 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6849,6 +6849,9 @@ i
<attr name="showDefault" format="boolean" />
<!-- Whether to show an item for 'Silent'. -->
<attr name="showSilent" format="boolean" />
+ <!-- The style of the ringtone dialog.
+ @hide -->
+ <attr name="dialogStyle" format="reference" />
</declare-styleable>
<!-- Base attributes available to VolumePreference. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index cf08dea..a0b92b9 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -790,6 +790,8 @@
<flag name="smallestScreenSize" value="0x0800" />
<!-- The layout direction has changed. For example going from LTR to RTL. -->
<flag name="layoutDirection" value="0x2000" />
+ <!-- Theme has changed, This should be an ORed value of all ActivityInfo.CONFIG_THEME_* -->
+ <flag name="themeChange" value="0x300000" />
<!-- The font scaling factor has changed, that is the user has
selected a new global font size. -->
<flag name="fontScale" value="0x40000000" />
@@ -1289,6 +1291,9 @@
<attr name="description" />
<attr name="protectionLevel" />
<attr name="permissionFlags" />
+ <!-- @hide Allows permissions to be granted to specific application signatures,
+ which are defined in /system/etc/permissions/someapp.xml. -->
+ <attr name="allowViaWhitelist" format="boolean" />
</declare-styleable>
<!-- The <code>permission-group</code> tag declares a logical grouping of
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 7c63950..0d33a51 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -29,4 +29,8 @@
<!-- Whether to allow vertically stacked button bars. This is disabled for
configurations with a small (e.g. less than 320dp) screen height. -->
<bool name="allow_stacked_button_bar">false</bool>
+ <!-- Whether to enable softap extention feature -->
+ <bool name="config_softap_extention">true</bool>
+ <!-- Whether to enable auto connection feature -->
+ <bool name="wifi_autocon">false</bool>
</resources>
diff --git a/core/res/res/values/cm_arrays.xml b/core/res/res/values/cm_arrays.xml
new file mode 100644
index 0000000..6629b4f
--- /dev/null
+++ b/core/res/res/values/cm_arrays.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Do not translate. Defines the mapping of notification package names
+ from the actual triggering package to the user selectable package.
+ E.g. GTalk notifications come via Google Services Framework
+ Format: [triggering package]|[user package] -->
+ <string-array name="notification_light_package_mapping" translatable="false">
+ <item>com.google.android.gsf|com.google.android.talk</item>
+ </string-array>
+
+ <!-- Defines the shutdown options shown in the reboot dialog. -->
+ <array name="shutdown_reboot_options" translatable="false">
+ <item>@string/reboot_reboot</item>
+ <item>@string/reboot_soft</item>
+ <item>@string/reboot_recovery</item>
+ <item>@string/reboot_bootloader</item>
+ </array>
+
+ <!-- Do not translate. Defines the shutdown actions passed to the kernel.
+ The first item should be empty for regular reboot. -->
+ <string-array name="shutdown_reboot_actions" translatable="false">
+ <item></item>
+ <item>soft_reboot</item>
+ <item>recovery</item>
+ <item>bootloader</item>
+ </string-array>
+
+ <!-- List of packages that should not be themed.
+ Note: These strings are checked using String.startsWith() so include as much of the
+ package name as possible to avoid other packages being un-themed unintentionally -->
+ <string-array name="non_themeable_packages" translatable="false">
+ </string-array>
+
+ <!-- Do not translate. App ops request strings -->
+ <string-array name="app_ops_labels" translatable="false">
+ <!-- OP_COARSE_LOCATION -->
+ <item>@string/app_ops_access_location</item>
+ <!-- OP_FINE_LOCATION -->
+ <item>@string/app_ops_access_location</item>
+ <!-- OP_GPS -->
+ <item>@string/app_ops_access_location</item>
+ <!-- OP_VIBRATE -->
+ <item>@string/app_ops_use_vibrate</item>
+ <!-- OP_READ_CONTACTS -->
+ <item>@string/app_ops_read_contacts</item>
+ <!-- OP_WRITE_CONTACTS -->
+ <item>@string/app_ops_modify_contacts</item>
+ <!-- OP_READ_CALL_LOG -->
+ <item>@string/app_ops_read_call_log</item>
+ <!-- OP_WRITE_CALL_LOG -->
+ <item>@string/app_ops_modify_call_log</item>
+ <!-- OP_READ_CALENDAR -->
+ <item>@string/app_ops_read_calendar</item>
+ <!-- OP_WRITE_CALENDAR -->
+ <item>@string/app_ops_modify_calendar</item>
+ <!-- OP_WIFI_SCAN -->
+ <item>@string/app_ops_scan_wifi</item>
+ <!-- OP_POST_NOTIFICATION -->
+ <item>@string/app_ops_post_notification</item>
+ <!-- OP_NEIGHBORING_CELLS -->
+ <item>@string/app_ops_access_location</item>
+ <!-- OP_CALL_PHONE -->
+ <item>@string/app_ops_make_phone_call</item>
+ <!-- OP_READ_SMS -->
+ <item>@string/app_ops_read_sms</item>
+ <!-- OP_WRITE_SMS -->
+ <item>@string/app_ops_write_sms</item>
+ '<!-- OP_RECEIVE_SMS -->
+ <item>@string/app_ops_receive_sms</item>
+ <!-- OP_RECEIVE_EMERGENCY_SMS -->
+ <item>@string/app_ops_receive_sms</item>
+ <!-- OP_RECEIVE_MMS -->
+ <item>@string/app_ops_receive_sms</item>
+ <!-- OP_RECEIVE_WAP_PUSH -->
+ <item>@string/app_ops_receive_sms</item>
+ <!-- OP_SEND_SMS -->
+ <item>@string/app_ops_send_sms</item>
+ <!-- OP_READ_ICC_SMS -->
+ <item>@string/app_ops_read_sms</item>
+ <!-- OP_WRITE_ICC_SMS -->
+ <item>@string/app_ops_write_sms</item>
+ <!-- OP_WRITE_SETTINGS -->
+ <item>@string/app_ops_modify_settings</item>
+ <!-- OP_SYSTEM_ALERT_WINDOW -->
+ <item>@string/app_ops_draw_on_top</item>
+ <!-- OP_ACCESS_NOTIFICATIONS -->
+ <item>@string/app_ops_access_notifications</item>
+ <!-- OP_CAMERA -->
+ <item>@string/app_ops_access_camera</item>
+ <!-- OP_RECORD_AUDIO -->
+ <item>@string/app_ops_record_audio</item>
+ <!-- OP_PLAY_AUDIO -->
+ <item>@string/app_ops_play_audio</item>
+ <!-- OP_READ_CLIPBOARD -->
+ <item>@string/app_ops_read_clipboard</item>
+ <!-- OP_WRITE_CLIPBOARD -->
+ <item>@string/app_ops_modify_clipboard</item>
+ <!-- OP_TAKE_MEDIA_BUTTONS -->
+ <item>@string/app_ops_use_media_buttons</item>
+ <!-- OP_TAKE_AUDIO_FOCUS -->
+ <item>@string/app_ops_use_audio_focus</item>
+ <!-- OP_AUDIO_MASTER_VOLUME -->
+ <item>@string/app_ops_use_master_volume</item>
+ <!-- OP_AUDIO_VOICE_VOLUME -->
+ <item>@string/app_ops_use_voice_volume</item>
+ <!-- OP_AUDIO_RING_VOLUME -->
+ <item>@string/app_ops_use_ring_volume</item>
+ <!-- OP_AUDIO_MEDIA_VOLUME -->
+ <item>@string/app_ops_use_media_volume</item>
+ <!-- OP_AUDIO_ALARM_VOLUME -->
+ <item>@string/app_ops_use_alarm_volume</item>
+ <!-- OP_AUDIO_NOTIFICATION_VOLUME -->
+ <item>@string/app_ops_use_notification_volume</item>
+ <!-- OP_AUDIO_BLUETOOTH_VOLUME -->
+ <item>@string/app_ops_use_bluetooth_volume</item>
+ <!-- OP_WAKE_LOCK -->
+ <item>@string/app_ops_keep_device_awake</item>
+ <!-- OP_MONITOR_LOCATION -->
+ <item>@string/app_ops_access_location</item>
+ <!-- OP_MONITOR_HIGH_POWER_LOCATION -->
+ <item>@string/app_ops_access_location</item>
+ <!-- OP_GET_USAGE_STATS -->
+ <item>@string/app_ops_get_usage_stats</item>
+ <!-- OP_MUTE_MICROPHONE -->
+ <item>@string/app_ops_mute_unmute_microphone</item>
+ <!-- OP_TOAST_WINDOW -->
+ <item>@string/app_ops_toast_window</item>
+ <!-- OP_PROJECT_MEDIA -->
+ <item>@string/app_ops_project_media</item>
+ <!-- OP_ACTIVATE_VPN -->
+ <item>@string/app_ops_activate_vpn</item>
+ <!-- OP_WRITE_WALLPAPER -->
+ <item>@string/app_ops_change_wallpaper</item>
+ <!-- OP_ASSIST_STRUCTURE -->
+ <item>@string/app_ops_assist_structure</item>
+ <!-- OP_ASSIST_SCREENSHOT -->
+ <item>@string/app_ops_assist_screenshot</item>
+ <!-- OP_READ_PHONE_STATE -->
+ <item>@string/app_ops_read_phone_state</item>
+ <!-- OP_ADD_VOICEMAIL -->
+ <item>@string/app_ops_add_voicemail</item>
+ <!-- OP_USE_SIP -->
+ <item>@string/app_ops_make_phone_call</item>
+ <!-- OP_PROCESS_OUTGOING_CALLS -->
+ <item>@string/app_ops_make_phone_call</item>
+ <!-- OP_USE_FINGERPRINT -->
+ <item>@string/app_ops_use_fingerprint</item>
+ <!-- OP_BODY_SENSORS -->
+ <item>@string/app_ops_use_body_sensors</item>
+ <!-- OP_READ_CELL_BROADCASTS -->
+ <item>@string/app_ops_read_cell_broadcasts</item>
+ <!-- OP_MOCK_LOCATION -->
+ <item>@string/app_ops_mock_location</item>
+ <!-- OP_READ_EXTERNAL_STORAGE -->
+ <item>@string/app_ops_read_external_storage</item>
+ <!-- OP_WRITE_EXTERNAL_STORAGE -->
+ <item>@string/app_ops_write_external_storage</item>
+ <!-- OP_TURN_SCREEN_ON -->
+ <item>@string/app_ops_turn_on_screen</item>
+ <!-- OP_GET_ACCOUNTS -->
+ <item>@string/app_ops_get_accounts</item>
+ <!-- OP_WIFI_CHANGE -->
+ <item>@string/app_ops_wifi_change</item>
+ <!-- OP_BLUETOOTH_CHANGE -->
+ <item>@string/app_ops_toggle_bluetooth</item>
+ <!-- OP_BOOT_COMPLETED -->
+ <item>@string/app_ops_start_at_bootup</item>
+ <!-- OP_NFC_CHANGE -->
+ <item>@string/app_ops_toggle_nfc</item>
+ <!-- OP_DATA_CONNECT_CHANGE -->
+ <item>@string/app_ops_toggle_mobile_data</item>
+ <!-- OP_SU -->
+ <item>@string/app_ops_su</item>
+ </string-array>
+
+ <string-array name="live_display_entries" translatable="false">
+ <item>@string/live_display_auto</item>
+ <item>@string/live_display_off</item>
+ <item>@string/live_display_day</item>
+ <item>@string/live_display_night</item>
+ <item>@string/live_display_outdoor</item>
+ </string-array>
+
+ <string-array name="live_display_summaries" translatable="false">
+ <item>@string/live_display_auto_summary</item>
+ <item>@string/live_display_off_summary</item>
+ <item>@string/live_display_day_summary</item>
+ <item>@string/live_display_night_summary</item>
+ <item>@string/live_display_outdoor_summary</item>
+ </string-array>
+
+ <string-array name="live_display_values" translatable="false">
+ <item>2</item>
+ <item>0</item>
+ <item>4</item>
+ <item>1</item>
+ <item>3</item>
+ </string-array>
+
+
+ <!-- A list of pre-installed applications that will be treated as carrier apps,
+ regardless of the SIM inserted. These applications will be granted phone and
+ location permissions, and must obtain user content through other means -->
+ <string-array name="config_enabledPreinstalledCarrierApps" translatable="false" />
+</resources>
diff --git a/core/res/res/values/cm_colors.xml b/core/res/res/values/cm_colors.xml
new file mode 100644
index 0000000..3eca3ae
--- /dev/null
+++ b/core/res/res/values/cm_colors.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Exposed Hard coded colors -->
+ <color name="edit_side_paste_window_text_color">@android:color/black</color>
+ <color name="edit_paste_window_text_color">@android:color/black</color>
+ <color name="edit_action_popup_text_color">@android:color/black</color>
+ <color name="web_view_dropdown_text_color">#ff000000</color>
+ <color name="web_view_dropdown_background_color">#ffffffff</color>
+ <color name="perms_costs_money_text_color">@color/perms_costs_money</color>
+ <color name="loading_view_text_color">#60FFFFFF</color>
+ <color name="loading_view_text_shadow_color">#FF000000</color>
+ <color name="notification_action_tombstone_text_color">#555555</color>
+ <color name="character_picker_button_text_color">#FFFFFFFF</color>
+ <color name="activity_list_divider_color">@android:color/holo_blue_light</color>
+ <color name="dialog_divider_color">@android:color/holo_blue_light</color>
+ <color name="typing_filter_text_color">#99FFFFFF</color>
+ <color name="typing_filter_background_color">#BB000000</color>
+ <color name="status_bar_latest_event_content_bg_color">#FFFF00FF</color>
+ <color name="media_controller_background_color">#CC000000</color>
+ <color name="immersive_cling_bg_color">#ff009688</color>
+ <color name="immersive_cling_text_color">@color/primary_text_default_material_light</color>
+ <color name="immersive_cling_button_text_color">@android:color/white</color>
+ <color name="app_permission_icon_tint">@android:color/black</color>
+ <color name="notification_mtrl_action_textcolor">@color/secondary_text_material_light</color>
+ <color name="notification_mtrl_big_picture_bg">#CCEEEEEE</color>
+ <color name="resolver_list_bg">@color/white</color>
+</resources>
diff --git a/core/res/res/values/cm_integers.xml b/core/res/res/values/cm_integers.xml
new file mode 100644
index 0000000..0668c92
--- /dev/null
+++ b/core/res/res/values/cm_integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015, The CyanogenMod 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.
+*/
+-->
+<resources>
+ <!-- Default for Settings.Global.WIFI_IDLE_MS (15 minutes) -->
+ <integer name="def_wifi_idle_ms">900000</integer>
+</resources>
diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml
new file mode 100644
index 0000000..9b03793
--- /dev/null
+++ b/core/res/res/values/cm_strings.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- label for item that screenshots in phone options dialog -->
+ <string name="global_action_screenshot">Screenshot</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_receiveProtectedSms">receive protected SMS</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_receiveProtectedSms">Allows the app to receive an incoming protected SMS.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_modifyProtectedSmsList">modify protected SMS list</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_modifyProtectedSmsList">Allows the app to modify the protected SMS address list.</string>
+
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgrouplab_security">Security</string>
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgroupdesc_security">Permissions related to device security information.</string>
+
+ <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_readPhoneBlacklist">read phone blacklist</string>
+ <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_readPhoneBlacklist">Allows an app to read information about phone numbers that are blocked for incoming calls or messages.</string>
+
+ <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_changePhoneBlacklist">change phone blacklist</string>
+ <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_changePhoneBlacklist">Allows an app to change the phone numbers that are blocked for incoming calls or messages.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want the application to do this. -->
+ <string name="permlab_setKeyguardWallpaper">set keyguard wallpaper</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_setKeyguardWallpaper">Allows an app to change the lock screen wallpaper.</string>
+
+ <!-- label for item that reboots the phone in phone options dialog -->
+ <string name="global_action_reboot">Reboot</string>
+ <!-- label for current user in phone options dialog -->
+ <string name="global_action_current_user">Current</string>
+
+ <!-- Reboot menu -->
+ <!-- Button to reboot the phone, within the Reboot Options dialog -->
+ <string name="reboot_reboot">Reboot</string>
+ <!-- Button to reboot the phone into recovery, within the Reboot Options dialog -->
+ <string name="reboot_recovery">Recovery</string>
+ <!-- Button to reboot the phone into bootloader, within the Reboot Options dialog -->
+ <string name="reboot_bootloader">Bootloader</string>
+ <!-- Button to reboot the phone into download, within the Reboot Options dialog -->
+ <string name="reboot_download">Download</string>
+ <!-- Button to soft reboot the device, within the Reboot Options dialog -->
+ <string name="reboot_soft">Soft reboot</string>
+
+ <!-- Title of dialog to confirm rebooting. -->
+ <string name="reboot_title">Reboot</string>
+
+ <!-- Reboot Confirmation Dialog. When the user chooses to reboot the device, there will
+ be a confirmation dialog. This is the message. -->
+ <string name="reboot_confirm" product="tablet">Your tablet will reboot.</string>
+ <string name="reboot_confirm" product="default">Your phone will reboot.</string>
+
+ <!-- Reboot Progress Dialog. This is shown if the user chooses to reboot the phone. -->
+ <string name="reboot_progress">Rebooting\u2026</string>
+
+ <!-- Long-press back kill application -->
+ <string name="app_killed_message">App killed</string>
+
+ <!-- ADB over network notification -->
+ <string name="adb_net_active_notification_title">ADB over network enabled</string>
+ <!-- ADB over USB and network notification -->
+ <string name="adb_both_active_notification_title">ADB over USB &amp; network enabled</string>
+ <!-- ADB notification message-->
+ <string name="adb_active_generic_notification_message">Touch to disable debugging.</string>
+
+ <!-- ADB custom tile -->
+ <string name="adb_active_custom_tile">ADB - <xliff:g id="adb_type" example="USB">%1$s</xliff:g></string>
+ <string name="adb_active_custom_tile_both">USB &amp; network</string>
+ <string name="adb_active_custom_tile_usb">USB</string>
+ <string name="adb_active_custom_tile_net">Network</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want the application to do this. -->
+ <string name="permlab_interceptPackageLaunch">intercept app launch</string>
+
+ <!-- stylus gestures support -->
+ <string name="stylus_app_not_installed">%s is not installed</string>
+
+ <!-- Zen mode buttons -->
+ <string name="silent_mode_priority">Priority</string>
+ <string name="silent_mode_none">None</string>
+
+ <!-- Wifi Hotspot disabled due to subscription change -->
+ <string name="subscription_change_disabled_wifi_ap">Disabled Wi-Fi hotspot due to SIM subscription change</string>
+
+ <!-- WiFi turn off notification action text -->
+ <string name="notify_turn_wifi_off_title">Turn Wi-Fi off</string>
+
+ <!-- Privacy Guard -->
+ <string name="permlab_changePrivacyGuardState">enable or disable Privacy Guard</string>
+ <string name="permdesc_changePrivacyGuardState">Allows the app to change whether another app runs with Privacy Guard. When an app is running with Privacy Guard, it will not have access to personal data such as contacts, call logs, or messages.</string>
+ <string name="privacy_guard_notification">Privacy Guard active</string>
+ <string name="privacy_guard_notification_detail"><xliff:g id="app">%1$s</xliff:g> will not be able to access personal data</string>
+ <string name="privacy_guard_dialog_title">Privacy Guard</string>
+ <string name="privacy_guard_dialog_summary"><xliff:g id="app">%1$s</xliff:g> would like to <xliff:g id="op">%2$s</xliff:g>.</string>
+
+ <!-- Text of the checkbox for the permission confirmation dialog to remember the user's choice. [CHAR LIMIT=40] -->
+ <string name="permission_remember_choice">Remember my choice</string>
+
+ <!-- App ops requests -->
+ <string name="app_ops_access_camera">access the camera</string>
+ <string name="app_ops_access_location">access your location</string>
+ <string name="app_ops_access_notifications">read your notifications</string>
+ <string name="app_ops_activate_vpn">activate a VPN</string>
+ <string name="app_ops_auto_start">start at power up</string>
+ <string name="app_ops_delete_call_log">delete your call log</string>
+ <string name="app_ops_delete_contacts">delete your contacts</string>
+ <string name="app_ops_delete_mms">delete your MMS messages</string>
+ <string name="app_ops_delete_sms">delete your SMS messages</string>
+ <string name="app_ops_draw_on_top">draw windows on top</string>
+ <string name="app_ops_get_usage_stats">get app usage stats</string>
+ <string name="app_ops_keep_device_awake">keep your device awake</string>
+ <string name="app_ops_make_phone_call">make a phone call</string>
+ <string name="app_ops_modify_calendar">update your calendar</string>
+ <string name="app_ops_modify_call_log">update the call log</string>
+ <string name="app_ops_modify_clipboard">modify the clipboard</string>
+ <string name="app_ops_modify_contacts">update your contacts</string>
+ <string name="app_ops_modify_settings">update system settings</string>
+ <string name="app_ops_mute_unmute_microphone">mute/unmute the microphone</string>
+ <string name="app_ops_play_audio">play audio</string>
+ <string name="app_ops_post_notification">post a notification</string>
+ <string name="app_ops_project_media">project media</string>
+ <string name="app_ops_read_calendar">read your calendar</string>
+ <string name="app_ops_read_call_log">read the call log</string>
+ <string name="app_ops_read_clipboard">read the clipboard</string>
+ <string name="app_ops_read_contacts">read your contacts</string>
+ <string name="app_ops_read_mms">read your MMS messages</string>
+ <string name="app_ops_read_sms">read your SMS messages</string>
+ <string name="app_ops_receive_sms">receive an SMS message</string>
+ <string name="app_ops_record_audio">record audio</string>
+ <string name="app_ops_send_mms">send an MMS message</string>
+ <string name="app_ops_send_sms">send an SMS message</string>
+ <string name="app_ops_start_at_bootup">start at power up</string>
+ <string name="app_ops_toast_window">display toast messages</string>
+ <string name="app_ops_toggle_bluetooth">toggle Bluetooth</string>
+ <string name="app_ops_toggle_mobile_data">toggle cellular data</string>
+ <string name="app_ops_toggle_nfc">toggle NFC</string>
+ <string name="app_ops_toggle_wifi">toggle Wi-Fi</string>
+ <string name="app_ops_use_alarm_volume">control alarm volume</string>
+ <string name="app_ops_use_audio_focus">control the audio focus</string>
+ <string name="app_ops_use_bluetooth_volume">control the Bluetooth volume</string>
+ <string name="app_ops_use_master_volume">control the master volume</string>
+ <string name="app_ops_use_media_buttons">use the media buttons</string>
+ <string name="app_ops_use_media_volume">control the media volume</string>
+ <string name="app_ops_use_notification_volume">control the notification volume</string>
+ <string name="app_ops_use_ring_volume">control the ringtone volume</string>
+ <string name="app_ops_use_vibrate">use haptic feedback</string>
+ <string name="app_ops_use_voice_volume">control the voice call volume</string>
+ <string name="app_ops_write_mms">write an MMS message</string>
+ <string name="app_ops_write_sms">write an SMS message</string>
+ <string name="app_ops_use_fingerprint">use fingerprint</string>
+ <string name="app_ops_add_voicemail">add a voicemail</string>
+ <string name="app_ops_read_phone_state">access phone state</string>
+ <string name="app_ops_scan_wifi">scan Wi-Fi networks</string>
+ <string name="app_ops_change_wallpaper">change the wallpaper</string>
+ <string name="app_ops_assist_structure">use assist structure</string>
+ <string name="app_ops_assist_screenshot">take a screenshot</string>
+ <string name="app_ops_use_body_sensors">use body sensors</string>
+ <string name="app_ops_read_cell_broadcasts">read cell broadcasts</string>
+ <string name="app_ops_mock_location">mock your location</string>
+ <string name="app_ops_read_external_storage">read external storage</string>
+ <string name="app_ops_write_external_storage">write external storage</string>
+ <string name="app_ops_turn_on_screen">turn the screen on</string>
+ <string name="app_ops_get_accounts">get device accounts</string>
+ <string name="app_ops_wifi_change">change Wi-Fi state</string>
+ <string name="app_ops_su">get root access</string>
+
+ <!-- Notify user that they are in Lock-to-app (for devices without navbar) -->
+ <string name="lock_to_app_toast_no_navbar">To unpin this screen, touch and hold the Back button.</string>
+
+ <!-- LiveDisplay strings -->
+ <string name="live_display_title" translatable="false">LiveDisplay</string>
+ <string name="live_display_auto">Automatic</string>
+ <string name="live_display_auto_summary">Automatically adjust color temperature of screen after sunset and sunrise</string>
+ <string name="live_display_off">Off</string>
+ <string name="live_display_off_summary">Disable all adjustments</string>
+ <string name="live_display_day">Day</string>
+ <string name="live_display_day_summary">Use day settings only</string>
+ <string name="live_display_night">Night</string>
+ <string name="live_display_night_summary">Use night settings only</string>
+ <string name="live_display_outdoor">Outdoor (bright sun)</string>
+ <string name="live_display_outdoor_summary">Use outdoor settings only</string>
+ <string name="live_display_hint">LiveDisplay can help reduce eyestrain and help you sleep at night. Click here to try it out!</string>
+
+ <!-- Template for showing cellular network operator name while LTE calling is enabled -->
+ <string name="high_definition_tag" translatable="false">%s</string>
+
+ <string name="tethered_notification_no_device_message">No connected device</string>
+ <string name="tethered_notification_one_device_message"><xliff:g id="count">%1$s</xliff:g> connected device</string>
+ <string name="tethered_notification_multi_device_message"><xliff:g id="count">%1$s</xliff:g> connected devices</string>
+
+ <!-- Keyguard strings -->
+ <!-- Sequence of characters used to separate carrier message strings in keyguard. Typically just vertical line
+ with spaces on either side. [CHAR LIMIT=3] -->
+ <string name="kg_sub_separator" translatable="false">" | "</string>
+
+ <!-- Protected Apps Notification -->
+ <string name="notify_package_component_protected_title">Activity launch blocked</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> is protected from being launched. Tap to authenticate and launch the application.</string>
+
+ <!-- Battery fully charged notification -->
+ <string name="notify_battery_fully_charged_title">Battery fully charged</string>
+ <string name="notify_battery_fully_charged_text">Disconnect your device from the charger to improve battery longevity.</string>
+
+ <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose
+ whether they want to allow the application to do this. -->
+ <string name="permlab_resetBatteryStats">reset battery statistics</string>
+ <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose
+ whether they want to allow the application to do this. -->
+ <string name="permdesc_resetBatteryStats">Allows an application to reset the current low-level battery usage data.</string>
+</resources>
diff --git a/core/res/res/values/cm_symbols.xml b/core/res/res/values/cm_symbols.xml
new file mode 100644
index 0000000..49f9874
--- /dev/null
+++ b/core/res/res/values/cm_symbols.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod Project
+ Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+ 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.
+-->
+<resources>
+ <!-- We don't want to publish private symbols in android.R as part of the
+ SDK. Instead, put them here. -->
+ <private-symbols package="com.android.internal" />
+
+ <!-- Private symbols that we need to reference from framework code. See
+ frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
+ this.
+ -->
+ <!-- External CM specific core services -->
+ <java-symbol type="array" name="config_externalCMServices" />
+
+ <java-symbol type="bool" name="config_singleStageCameraKey" />
+ <java-symbol type="integer" name="config_longPressOnMenuBehavior" />
+ <java-symbol type="integer" name="config_longPressOnAppSwitchBehavior" />
+
+ <!-- Notification and battery light -->
+ <java-symbol type="bool" name="config_intrusiveNotificationLed" />
+ <java-symbol type="bool" name="config_multiColorNotificationLed" />
+ <java-symbol type="bool" name="config_intrusiveBatteryLed" />
+ <java-symbol type="bool" name="config_multiColorBatteryLed" />
+ <java-symbol type="array" name="notification_light_package_mapping" />
+ <java-symbol type="array" name="config_notificationNoAlertsVibePattern" />
+
+ <!-- ADB custom tile -->
+ <java-symbol type="string" name="adb_active_custom_tile" />
+ <java-symbol type="string" name="adb_active_custom_tile_both" />
+ <java-symbol type="string" name="adb_active_custom_tile_usb" />
+ <java-symbol type="string" name="adb_active_custom_tile_net" />
+
+ <!-- Package Manager -->
+ <java-symbol type="array" name="config_disabledComponents" />
+ <java-symbol type="array" name="config_forceEnabledComponents" />
+
+ <java-symbol type="string" name="global_action_current_user" />
+ <java-symbol type="dimen" name="global_actions_avatar_size" />
+
+ <!-- Stylus gestures -->
+ <java-symbol type="bool" name="config_stylusGestures" />
+ <java-symbol type="string" name="stylus_app_not_installed" />
+
+ <!-- global actions (zen mode buttons) -->
+ <java-symbol type="id" name="option4" />
+
+ <!-- LED pulse -->
+ <java-symbol type="bool" name="config_ledCanPulse" />
+
+ <!-- Non-themeable packages -->
+ <java-symbol type="array" name="non_themeable_packages" />
+
+ <!-- Wifi AP Disabled from Subscription change -->
+ <java-symbol type="string" name="subscription_change_disabled_wifi_ap" />
+
+ <!-- WiFi turn off notification -->
+ <java-symbol type="string" name="notify_turn_wifi_off_title" />
+
+ <!-- Region locked prebundled packages (per mcc) -->
+ <java-symbol type="array" name="config_region_locked_packages" />
+
+ <!-- Packages in this list should be a union of all packages defined in values-mccxxx (mcc) -->
+ <java-symbol type="array" name="config_restrict_to_region_locked_devices" />
+
+ <!-- Support Samsung docks -->
+ <java-symbol type="bool" name="config_forceAnalogCarDock" />
+ <java-symbol type="bool" name="config_forceAnalogDeskDock" />
+
+ <!-- Privacy Guard -->
+ <java-symbol type="drawable" name="stat_notify_privacy_guard" />
+ <java-symbol type="string" name="privacy_guard_notification" />
+ <java-symbol type="string" name="privacy_guard_notification_detail" />
+ <java-symbol type="string" name="privacy_guard_dialog_title" />
+ <java-symbol type="string" name="privacy_guard_dialog_summary" />
+
+ <!-- app opps always-ask -->
+ <java-symbol type="id" name="permission_text" />
+ <java-symbol type="id" name="permission_remember_layout" />
+ <java-symbol type="id" name="permission_remember_choice_checkbox" />
+ <java-symbol type="id" name="permission_remember_choice_text" />
+ <java-symbol type="string" name="allow" />
+ <java-symbol type="string" name="deny" />
+ <java-symbol type="layout" name="permission_confirmation_dialog" />
+ <java-symbol type="array" name="app_ops_labels" />
+
+ <!-- Blur effects -->
+ <java-symbol type="bool" name="config_ui_blur_enabled" />
+
+ <!-- Advanced settings switch -->
+ <java-symbol type="string" name="lock_to_app_toast_no_navbar" />
+
+ <!-- PlatLogo -->
+ <java-symbol type="drawable" name="platlogo_cm" />
+
+ <!-- Automatic brightness enhancements -->
+ <java-symbol type="integer" name="config_autoBrightnessBrighteningLightFastDebounce"/>
+
+ <!-- LiveDisplay -->
+ <java-symbol type="string" name="live_display_title" />
+ <java-symbol type="string" name="live_display_hint" />
+ <java-symbol type="string" name="live_display_auto" />
+ <java-symbol type="string" name="live_display_auto_summary" />
+ <java-symbol type="string" name="live_display_day" />
+ <java-symbol type="string" name="live_display_day_summary" />
+ <java-symbol type="string" name="live_display_night" />
+ <java-symbol type="string" name="live_display_night_summary" />
+ <java-symbol type="string" name="live_display_outdoor" />
+ <java-symbol type="string" name="live_display_outdoor_summary" />
+ <java-symbol type="array" name="live_display_entries" />
+ <java-symbol type="array" name="live_display_summaries" />
+ <java-symbol type="array" name="live_display_values" />
+ <java-symbol type="integer" name="config_dayColorTemperature" />
+
+ <java-symbol type="string" name="high_definition_tag" />
+
+ <java-symbol type="string" name="tethered_notification_no_device_message" />
+ <java-symbol type="string" name="tethered_notification_one_device_message" />
+ <java-symbol type="string" name="tethered_notification_multi_device_message" />
+
+ <!-- Wifi idle time default -->
+ <java-symbol type="integer" name="def_wifi_idle_ms" />
+
+ <!-- Carrier Apps -->
+ <java-symbol type="array" name="config_enabledPreinstalledCarrierApps" />
+
+ <!-- KeyGuard -->
+ <java-symbol type="string" name="kg_sub_separator" />
+
+ <!-- Protected Apps -->
+ <java-symbol type="drawable" name="stat_notify_protected" />
+ <java-symbol type="string" name="notify_package_component_protected_title" />
+ <java-symbol type="string" name="notify_package_component_protected_text" />
+
+ <!-- Restricted fingerprint config -->
+ <java-symbol type="bool" name="config_fingerprintRestrictedToSystemAndOwner" />
+
+ <!-- Show battery fully charged notification -->
+ <java-symbol type="bool" name="config_showBatteryFullyChargedNotification" />
+ <java-symbol type="string" name="notify_battery_fully_charged_title" />
+ <java-symbol type="string" name="notify_battery_fully_charged_text" />
+
+</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f76dfb2..73ad781 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -30,6 +30,7 @@
<item><xliff:g id="id">cast</xliff:g></item>
<item><xliff:g id="id">hotspot</xliff:g></item>
<item><xliff:g id="id">location</xliff:g></item>
+ <item><xliff:g id="id">su</xliff:g></item>
<item><xliff:g id="id">bluetooth</xliff:g></item>
<item><xliff:g id="id">nfc</xliff:g></item>
<item><xliff:g id="id">tty</xliff:g></item>
@@ -537,6 +538,9 @@
<!-- Operating volatage for wifi radio. 0 by default-->
<integer translatable="false" name="config_wifi_operating_voltage_mv">0</integer>
+ <!-- Wifi framework supports ECBM mode -->
+ <bool translatable="false" name="config_wifi_ecbm_mode_change">true</bool>
+
<!-- Flag indicating whether the we should enable the automatic brightness in Settings.
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">false</bool>
@@ -701,6 +705,10 @@
we rely on gravity to determine the effective orientation. -->
<bool name="config_deskDockEnablesAccelerometer">true</bool>
+ <!-- Control whether a desk dock event should override the default bluetooth
+ audio routing, FORCE_BT_DESK_DOCK, with an analog dock, FORCE_ANALOG_DOCK. -->
+ <bool name="config_forceAnalogDeskDock">false</bool>
+
<!-- Car dock behavior -->
<!-- The number of degrees to rotate the display when the device is in a car dock.
@@ -719,6 +727,10 @@
<bool name="config_carDockEnablesAccelerometer">true</bool>
+ <!-- Control whether a car dock event should override the default bluetooth
+ audio routing, FORCE_BT_CAR_DOCK, with an analog dock, FORCE_ANALOG_DOCK. -->
+ <bool name="config_forceAnalogCarDock">false</bool>
+
<!-- HDMI behavior -->
<!-- The number of degrees to rotate the display when the device has HDMI connected
@@ -917,6 +929,21 @@
<!-- Is the notification LED intrusive? Used to decide if there should be a disable option -->
<bool name="config_intrusiveNotificationLed">false</bool>
+ <!-- Does the notification LED support multiple colors?
+ Used to decide if the user can change the colors -->
+ <bool name="config_multiColorNotificationLed">false</bool>
+
+ <!-- Is the battery LED intrusive? Used to decide if there should be a disable option -->
+ <bool name="config_intrusiveBatteryLed">false</bool>
+
+ <!-- Does the battery LED support multiple colors?
+ Used to decide if the user can change the colors -->
+ <bool name="config_multiColorBatteryLed">false</bool>
+
+ <!-- Do the battery/notification LEDs support pulsing?
+ Used to decide if we show pulse settings -->
+ <bool name="config_ledCanPulse">true</bool>
+
<!-- Default value for LED off time when the battery is low on charge in miliseconds -->
<integer name="config_notificationsBatteryLedOff">2875</integer>
@@ -955,21 +982,84 @@
<!-- Control the behavior when the user long presses the home button.
0 - Nothing
- 1 - Recent apps view in SystemUI
- 2 - Launch assist intent
+ 1 - Menu key
+ 2 - Recent apps view in SystemUI
+ 3 - Launch assist intent
+ 4 - Voice Search
+ 5 - In-app Search
This needs to match the constants in
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
-->
- <integer name="config_longPressOnHomeBehavior">0</integer>
+ <integer name="config_longPressOnHomeBehavior">2</integer>
<!-- Control the behavior when the user double-taps the home button.
0 - Nothing
- 1 - Recent apps view in SystemUI
+ 1 - Menu key
+ 2 - Recent apps view in SystemUI
+ 3 - Launch assist intent
+ 4 - Voice Search
+ 5 - In-app Search
This needs to match the constants in
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
-->
<integer name="config_doubleTapOnHomeBehavior">0</integer>
+ <!-- Control the behavior when the user long presses the menu button.
+ 0 - Nothing
+ 1 - Menu key
+ 2 - Recent apps view in SystemUI
+ 3 - Launch assist intent
+ 4 - Voice Search
+ 5 - In-app Search
+ This needs to match the constants in
+ policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+ -->
+ <integer name="config_longPressOnMenuBehavior">3</integer>
+
+ <!-- Control the behavior when the user long presses the app switch button.
+ 0 - Nothing
+ 1 - Menu key
+ 2 - Recent apps view in SystemUI
+ 3 - Launch assist intent
+ 4 - Voice Search
+ 5 - In-app Search
+ This needs to match the constants in
+ services/core/java/com/android/server/policy/policy/impl/PhoneWindowManager.java
+ -->
+ <integer name="config_longPressOnAppSwitchBehavior">0</integer>
+
+ <!-- Hardware keys present on the device, stored as a bit field.
+ This integer should equal the sum of the corresponding value for each
+ of the following keys present:
+ 1 - Home
+ 2 - Back
+ 4 - Menu
+ 8 - Assistant (search)
+ 16 - App switch
+ 32 - Camera
+ 64 - Volume rocker
+ For example, a device with Home, Back and Menu keys would set this
+ config to 7. -->
+ <integer name="config_deviceHardwareKeys">79</integer>
+
+ <!-- Hardware keys present on the device with the ability to wake, stored as a bit field.
+ This integer should equal the sum of the corresponding value for each
+ of the following keys present:
+ 1 - Home
+ 2 - Back
+ 4 - Menu
+ 8 - Assistant (search)
+ 16 - App switch
+ 32 - Camera
+ 64 - Volume rocker
+ For example, a device with Home, Back and Menu keys would set this
+ config to 7. -->
+ <integer name="config_deviceHardwareWakeKeys">79</integer>
+
+ <!-- Indicates that the device has Single-stage Camera key
+ (without "Focus" state) instead of Dual-stage. -->
+ <bool name="config_singleStageCameraKey">false</bool>
+
<!-- Minimum screen brightness setting allowed by the power manager.
The user is forbidden from setting the brightness below this level. -->
<integer name="config_screenBrightnessSettingMinimum">10</integer>
@@ -995,6 +1085,7 @@
when adapting to brighter or darker environments. This parameter controls how quickly
brightness changes occur in response to an observed change in light level that exceeds the
hysteresis threshold. -->
+ <integer name="config_autoBrightnessBrighteningLightFastDebounce">500</integer>
<integer name="config_autoBrightnessBrighteningLightDebounce">4000</integer>
<integer name="config_autoBrightnessDarkeningLightDebounce">8000</integer>
@@ -1005,6 +1096,9 @@
to reduce it to preserve the battery. Value of 100% means no scaling. -->
<fraction name="config_screenAutoBrightnessDozeScaleFactor">100%</fraction>
+ <!-- Period of time in which to consider light samples in milliseconds. -->
+ <integer name="config_autoBrightnessAmbientLightHorizon">10000</integer>
+
<!-- When the screen is turned on, the previous estimate of the ambient light level at the time
the screen was turned off is restored and is used to determine the initial screen
brightness.
@@ -1079,6 +1173,10 @@
<integer-array name="config_autoBrightnessKeyboardBacklightValues">
</integer-array>
+ <integer name="config_buttonBrightnessSettingDefault">255</integer>
+ <integer name="config_keyboardBrightnessSettingDefault">0</integer>
+ <bool name="config_deviceHasVariableButtonBrightness">false</bool>
+
<!-- Amount of time it takes for the light sensor to warm up in milliseconds.
For this time after the screen turns on, the Power Manager
will not debounce light sensor readings -->
@@ -1217,6 +1315,11 @@
-->
</string-array>
+ <!-- Component name of the combo network location provider. -->
+ <string name="config_comboNetworkLocationProvider" translatable="false">@null</string>
+ <!-- Component name of the service providing geofence API support. -->
+ <string name="config_geofenceProvider" translatable="false">@null</string>
+
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
use cases -->
<bool name="config_bluetooth_sco_off_call">true</bool>
@@ -1759,6 +1862,9 @@
<!-- Configure wifi tcp buffersizes in the form:
rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max -->
<string name="config_wifi_tcp_buffers" translatable="false">524288,1048576,2097152,262144,524288,1048576</string>
+ <!-- Configuration to send sms on 1x when UE is attached to eHRPD and there is an active
+ 1xRTT voice call, irrespective of IMS registration state -->
+ <bool name="config_send_sms1x_on_voice_call">true</bool>
<!-- Whether WiFi display is supported by this device.
There are many prerequisites for this feature to work correctly.
@@ -1867,6 +1973,16 @@
<item>100</item>
</integer-array>
+ <!-- Vibrator pattern to be used as for notifications while alerts
+ are disabled (e.g. during phone calls) if enabled by the user.
+ -->
+ <integer-array name="config_notificationNoAlertsVibePattern">
+ <item>0</item>
+ <item>50</item>
+ <item>100</item>
+ <item>50</item>
+ </integer-array>
+
<!-- Flag indicating if the speed up audio on mt call code should be executed -->
<bool name="config_speed_up_audio_on_mt_calls">false</bool>
@@ -2129,6 +2245,12 @@
<bool name="config_networkSamplingWakesDevice">true</bool>
+ <!-- Path to the library that contains a device specific key handler -->
+ <string name="config_deviceKeyHandlerLib" translatable="false"></string>
+
+ <!-- Name of that key handler class -->
+ <string name="config_deviceKeyHandlerClass" translatable="false"></string>
+
<string-array translatable="false" name="config_cdma_home_system" />
<!--From SmsMessage-->
@@ -2136,9 +2258,13 @@
string that's stored in 8-bit unpacked format) characters.-->
<bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>
- <!-- Package name providing WebView implementation. -->
+ <!-- Package name providing default WebView implementation. -->
<string name="config_webViewPackageName" translatable="false">com.android.webview</string>
+ <!-- Package name providing alternate WebView implementation.
+ Fall back to config_webViewPackageName if not available. -->
+ <string name="config_alternateWebViewPackageName" translatable="false">com.google.android.webview</string>
+
<!-- If EMS is not supported, framework breaks down EMS into single segment SMS
and adds page info " x/y". This config is used to set which carrier doesn't
support EMS and whether page info should be added at the beginning or the end.
@@ -2153,6 +2279,9 @@
<bool name="config_auto_attach_data_on_creation">true</bool>
+ <!-- True if the gesture service should be started at system start -->
+ <bool name="config_enableGestureService">false</bool>
+
<!-- Values for GPS configuration -->
<string-array translatable="false" name="config_gpsParameters">
<item>SUPL_HOST=supl.google.com</item>
@@ -2213,6 +2342,7 @@
when evaluating RSRP for LTE antenna bar display
0. Strict threshold
1. Lenient threshold
+ 2. Custom threshold
-->
<integer name="config_LTE_RSRP_threshold_type">1</integer>
@@ -2298,6 +2428,10 @@
<!-- Keyguard component -->
<string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>
+ <!-- Set to true to disallow 3rd party apps access to the fingerprint reader, for older
+ hardware compatibility. This also disables fingerprints for secondary users. -->
+ <bool name="config_fingerprintRestrictedToSystemAndOwner">false</bool>
+
<!-- For performance and storage reasons, limit the number of fingerprints per user -->
<integer name="config_fingerprintMaxTemplatesPerUser">5</integer>
@@ -2345,6 +2479,55 @@
<string-array name="config_cell_retries_per_error_code">
</string-array>
+ <!-- Configuration to play sms ringtone during MO/MT call -->
+ <bool name="config_sms_ringtone_incall">false</bool>
+ <!-- IpReachability monitor enable/Disable -->
+ <bool translatable="false" name="config_wifi_ipreachability_monitor">false</bool>
+
+ <!-- Configuration that determines if ACTIVATE_REJECT_GGSN is to be treated as
+ a permanent error -->
+ <bool translatable="false" name="config_reject_ggsn_perm_failure">true</bool>
+ <!-- Configuration that determines if PROTOCOL_ERRORS is to be treated as a
+ permanent error -->
+ <bool translatable="false" name="config_protocol_errors_perm_failure">true</bool>
+
+ <!-- External CM Services list -->
+ <string-array name="config_externalCMServices"></string-array>
+
+ <!-- Timeout in MS for how long you have to long-press the back key to
+ kill the foreground app. -->
+ <integer name="config_backKillTimeout">2000</integer>
+
+ <!-- Setting to false will disable CM's IME switcher implementation for tablets -->
+ <bool name="config_show_cmIMESwitcher">true</bool>
+
+ <!-- The list of components which should be automatically disabled. -->
+ <string-array name="config_disabledComponents" translatable="false">
+ </string-array>
+
+ <!-- The list of components which should be forced to be enabled. -->
+ <string-array name="config_forceEnabledComponents" translatable="false">
+ </string-array>
+
+ <!-- Boolean to enable stk functionality on Samsung phones -->
+ <bool name="config_samsung_stk">false</bool>
+
+ <!-- If a dock provides a lid switch, that lid can be removed. This
+ setting is used to determine, whether lidOpenRotation has to be
+ applied. -->
+ <bool name="config_hasRemovableLid">false</bool>
+
+ <!-- Boolean to enable Stylus gestures -->
+ <bool name="config_stylusGestures">false</bool>
+
+ <!-- Config to enable installation of region locked packages -->
+ <string-array name="config_region_locked_packages" translatable="false">
+ </string-array>
+
+ <!-- Packages in this list should be a union of all packages defined in values-mccxxx (mcc) -->
+ <string-array name="config_restrict_to_region_locked_devices" translatable="false">
+ </string-array>
+
<!-- Set initial MaxRetry value for operators -->
<integer name="config_mdc_initial_max_retry">1</integer>
@@ -2358,6 +2541,20 @@
is non-interactive. -->
<bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>
+ <!-- Support in Surfaceflinger for blur layers.
+ NOTE: This requires additional hardware-specific code. -->
+ <bool name="config_ui_blur_enabled">false</bool>
+
+ <!-- When config_LTE_RSRP_threshold_type is set to "custom" -->
+ <integer-array name="config_LTE_RSRP_custom_levels">
+ <item>-140</item>
+ <item>-128</item>
+ <item>-118</item>
+ <item>-108</item>
+ <item>-98</item>
+ <item>-44</item>
+ </integer-array>
+
<!-- Name of the component to handle network policy notifications. If present,
disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
<string translatable="false" name="config_networkPolicyNotificationComponent"></string>
@@ -2365,4 +2562,12 @@
<!-- The BT name of the keyboard packaged with the device. If this is defined, SystemUI will
automatically try to pair with it when the device exits tablet mode. -->
<string translatable="false" name="config_packagedKeyboardName"></string>
+ <integer name="config_dayColorTemperature">6500</integer>
+
+ <!-- Show battery fully charged notification -->
+ <bool name="config_showBatteryFullyChargedNotification">false</bool>
+
+ <!-- Older rotation sensors are not setting event.timestamp correctly. Setting to
+ true will use SystemClock.elapsedRealtimeNanos() to set timestamp. -->
+ <bool name="config_useSystemClockforRotationSensor">false</bool>
</resources>
diff --git a/core/res/res/values/customize.xml b/core/res/res/values/customize.xml
new file mode 100644
index 0000000..53a1807
--- /dev/null
+++ b/core/res/res/values/customize.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<resources>
+ <!-- Support for disabling to fetch APN from OMH card
+ for some cdma carriers -->
+ <java-symbol type="bool" name="config_fetch_apn_from_omh_card" />
+ <bool name="config_fetch_apn_from_omh_card">false</bool>
+ <!-- Used in LocalePicker, default language must be contained -->
+ <string name="locale_codes" translatable="false"></string>
+
+ <!-- custom date format or not -->
+ <bool name="def_custom_dateformat">false</bool>
+</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a6342c2..aeb1568 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -401,4 +401,7 @@
<item type="dimen" format="integer" name="time_picker_column_start_material">0</item>
<item type="dimen" format="integer" name="time_picker_column_end_material">1</item>
+
+ <!-- Largest size an avatar might need to be drawn in the power menu user picker -->
+ <dimen name="global_actions_avatar_size">40dp</dimen>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0793905..1fef7e7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4109,4 +4109,12 @@
<item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> selected</item>
<item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
</plurals>
+
+ <!-- Used to replace a range of characters in text that is too wide
+ for the space allocated to it (three dots). -->
+ <string name="ellipsis">\u2026</string>
+
+ <!-- Used to replace a range of characters in text that is too wide
+ for the space allocated to it (two dots). -->
+ <string name="ellipsis_two_dots">\u2025</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e709500..92b3b2d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -220,6 +220,7 @@
<java-symbol type="id" name="profile_badge_line2" />
<java-symbol type="id" name="profile_badge_line3" />
<java-symbol type="id" name="transitionPosition" />
+ <java-symbol type="id" name="filtered_item_container" />
<java-symbol type="attr" name="actionModeShareDrawable" />
<java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -242,6 +243,7 @@
<java-symbol type="attr" name="accessibilityFocusedDrawable"/>
<java-symbol type="attr" name="isLightTheme"/>
+ <java-symbol type="bool" name="def_custom_dateformat" />
<java-symbol type="bool" name="action_bar_embed_tabs" />
<java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
<java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
@@ -297,6 +299,7 @@
<java-symbol type="bool" name="config_useFixedVolume" />
<java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
+ <java-symbol type="bool" name="config_wifi_ecbm_mode_change" />
<java-symbol type="bool" name="config_enableMultiUserUI"/>
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="bool" name="config_hasRecents" />
@@ -360,6 +363,7 @@
<java-symbol type="integer" name="config_wifi_framework_max_auth_errors_to_blacklist" />
<java-symbol type="integer" name="config_wifi_framework_network_black_list_min_time_milli" />
<java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
+ <java-symbol type="bool" name="config_send_sms1x_on_voice_call" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
<java-symbol type="integer" name="config_burnInProtectionMinHorizontalOffset" />
@@ -449,6 +453,7 @@
<java-symbol type="dimen" name="accessibility_magnification_indicator_width" />
<java-symbol type="dimen" name="circular_display_mask_thickness" />
+ <java-symbol type="string" name="locale_codes" />
<java-symbol type="string" name="add_account_button_label" />
<java-symbol type="string" name="addToDictionary" />
<java-symbol type="string" name="action_bar_home_description" />
@@ -826,8 +831,11 @@
<java-symbol type="string" name="reboot_to_update_reboot" />
<java-symbol type="string" name="reboot_to_reset_title" />
<java-symbol type="string" name="reboot_to_reset_message" />
+ <java-symbol type="string" name="reboot_confirm" />
<java-symbol type="string" name="reboot_safemode_confirm" />
<java-symbol type="string" name="reboot_safemode_title" />
+ <java-symbol type="string" name="reboot_title" />
+ <java-symbol type="string" name="reboot_progress" />
<java-symbol type="string" name="relationTypeAssistant" />
<java-symbol type="string" name="relationTypeBrother" />
<java-symbol type="string" name="relationTypeChild" />
@@ -1463,6 +1471,8 @@
<java-symbol type="array" name="config_safeModeEnabledVibePattern" />
<java-symbol type="array" name="config_contextClickVibePattern" />
<java-symbol type="array" name="config_virtualKeyVibePattern" />
+ <java-symbol type="array" name="shutdown_reboot_options" />
+ <java-symbol type="array" name="shutdown_reboot_actions" />
<java-symbol type="attr" name="actionModePopupWindowStyle" />
<java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
<java-symbol type="attr" name="dialogTitleDecorLayout" />
@@ -1491,6 +1501,7 @@
<java-symbol type="drawable" name="ic_jog_dial_vibrate_on" />
<java-symbol type="drawable" name="ic_lock_airplane_mode" />
<java-symbol type="drawable" name="ic_lock_airplane_mode_off" />
+ <java-symbol type="drawable" name="ic_lock_power_reboot" />
<java-symbol type="drawable" name="ic_menu_cc" />
<java-symbol type="drawable" name="jog_tab_bar_left_unlock" />
<java-symbol type="drawable" name="jog_tab_bar_right_sound_off" />
@@ -1534,6 +1545,8 @@
<java-symbol type="integer" name="config_carDockRotation" />
<java-symbol type="integer" name="config_defaultUiModeType" />
<java-symbol type="integer" name="config_deskDockRotation" />
+ <java-symbol type="integer" name="config_deviceHardwareKeys" />
+ <java-symbol type="integer" name="config_deviceHardwareWakeKeys" />
<java-symbol type="integer" name="config_doubleTapOnHomeBehavior" />
<java-symbol type="integer" name="config_lidKeyboardAccessibility" />
<java-symbol type="integer" name="config_lidNavigationAccessibility" />
@@ -1560,6 +1573,7 @@
<java-symbol type="string" name="config_orientationSensorType" />
<java-symbol type="string" name="faceunlock_multiple_failures" />
<java-symbol type="string" name="global_action_power_off" />
+ <java-symbol type="string" name="global_action_reboot" />
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
<java-symbol type="string" name="global_actions_airplane_mode_on_status" />
<java-symbol type="string" name="global_actions_toggle_airplane_mode" />
@@ -1691,6 +1705,7 @@
<java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
<java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
<java-symbol type="integer" name="config_autoBrightnessLightSensorRate"/>
+ <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
<java-symbol type="integer" name="config_carDockKeepsScreenOn" />
<java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
<java-symbol type="integer" name="config_datause_notification_type" />
@@ -1719,6 +1734,9 @@
<java-symbol type="integer" name="config_screenBrightnessDark" />
<java-symbol type="integer" name="config_screenBrightnessDim" />
<java-symbol type="integer" name="config_screenBrightnessDoze" />
+ <java-symbol type="integer" name="config_buttonBrightnessSettingDefault" />
+ <java-symbol type="integer" name="config_keyboardBrightnessSettingDefault" />
+ <java-symbol type="bool" name="config_deviceHasVariableButtonBrightness" />
<java-symbol type="integer" name="config_shutdownBatteryTemperature" />
<java-symbol type="integer" name="config_undockedHdmiRotation" />
<java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
@@ -1753,6 +1771,8 @@
<java-symbol type="string" name="config_geocoderProviderPackageName" />
<java-symbol type="string" name="config_geofenceProviderPackageName" />
<java-symbol type="string" name="config_networkLocationProviderPackageName" />
+ <java-symbol type="string" name="config_comboNetworkLocationProvider" />
+ <java-symbol type="string" name="config_geofenceProvider" />
<java-symbol type="string" name="config_wimaxManagerClassname" />
<java-symbol type="string" name="config_wimaxNativeLibLocation" />
<java-symbol type="string" name="config_wimaxServiceClassname" />
@@ -1888,6 +1908,7 @@
<java-symbol type="anim" name="lock_screen_behind_enter_fade_in" />
<java-symbol type="anim" name="lock_screen_wallpaper_exit" />
<java-symbol type="anim" name="launch_task_behind_source" />
+ <java-symbol type="anim" name="lock_screen_wallpaper_exit_noop" />
<java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
<java-symbol type="dimen" name="status_bar_icon_size" />
@@ -2027,6 +2048,7 @@
<java-symbol type="string" name="websearch" />
<java-symbol type="drawable" name="ic_media_video_poster" />
<java-symbol type="string" name="config_webViewPackageName" />
+ <java-symbol type="string" name="config_alternateWebViewPackageName" />
<!-- From SubtitleView -->
<java-symbol type="dimen" name="subtitle_corner_radius" />
@@ -2041,6 +2063,10 @@
<java-symbol type="layout" name="year_label_text_view" />
<java-symbol type="layout" name="date_picker_material" />
+ <!-- Config.xml entries -->
+ <java-symbol type="string" name="config_deviceKeyHandlerLib" />
+ <java-symbol type="string" name="config_deviceKeyHandlerClass" />
+
<java-symbol type="id" name="time_header" />
<java-symbol type="id" name="hours" />
<java-symbol type="id" name="minutes" />
@@ -2215,6 +2241,7 @@
<!-- From SignalStrength -->
<java-symbol type="integer" name="config_LTE_RSRP_threshold_type" />
+ <java-symbol type="array" name="config_LTE_RSRP_custom_levels" />
<java-symbol type="string" name="android_system_label" />
<java-symbol type="string" name="system_error_wipe_data" />
@@ -2337,9 +2364,56 @@
<java-symbol type="string" name="config_cameraLaunchGestureSensorStringType" />
<java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" />
+ <!-- config softap extention feature -->
+ <java-symbol type="bool" name="config_softap_extention" />
+
+ <!-- for wifi auto connection -->
+ <java-symbol type="bool" name="wifi_autocon" />
+ <!-- Configuration to play sms ringtone during MO/MT call -->
+ <java-symbol type="bool" name="config_sms_ringtone_incall" />
+
+ <!-- IpReachability Monitor -->
+ <java-symbol type="bool" name="config_wifi_ipreachability_monitor" />
+
+ <!-- Data Connectivity Error Configurations -->
+ <java-symbol type="bool" name="config_reject_ggsn_perm_failure" />
+ <java-symbol type="bool" name="config_protocol_errors_perm_failure" />
+
+ <!-- Gesture Sensor -->
+ <java-symbol type="bool" name="config_enableGestureService" />
+
+ <!-- Config.xml entries -->
+ <java-symbol type="bool" name="config_show_cmIMESwitcher"/>
+ <java-symbol type="bool" name="config_samsung_stk" />
+ <java-symbol type="bool" name="config_hasRemovableLid" />
+
+ <!-- Power menu -->
+ <java-symbol type="drawable" name="ic_lock_screenshot" />
+ <java-symbol type="string" name="global_action_screenshot" />
+ <java-symbol type="drawable" name="ic_lock_settings" />
+ <java-symbol type="drawable" name="ic_lock_user" />
+
+ <!-- Developer settings - Kill app back press -->
+ <java-symbol type="string" name="app_killed_message" />
+
+ <!-- Config.xml entries -->
+ <java-symbol type="integer" name="config_backKillTimeout" />
+
+ <!-- ADB notification -->
+ <java-symbol type="string" name="adb_net_active_notification_title" />
+ <java-symbol type="string" name="adb_both_active_notification_title" />
+ <java-symbol type="string" name="adb_active_generic_notification_message" />
+
+ <!-- Last app switch animations -->
+ <java-symbol type="anim" name="last_app_in" />
+ <java-symbol type="anim" name="last_app_out" />
+
<java-symbol type="string" name="config_networkPolicyNotificationComponent" />
+
<java-symbol type="drawable" name="platlogo_m" />
<java-symbol type="string" name="config_iccHotswapPromptForRestartDialogComponent" />
<java-symbol type="string" name="config_packagedKeyboardName" />
+
+ <java-symbol type="bool" name="config_useSystemClockforRotationSensor" />
</resources>
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 5f4199a..40b5c15 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -19,5 +19,5 @@
<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
<zen version="2">
- <allow calls="true" messages="false" reminders="true" events="true" />
+ <allow calls="true" messages="true" from="2" reminders="true" events="true" />
</zen>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 5783a49..0baeaff 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -111,6 +111,9 @@
http://clients.txtnation.com/entries/209633-hungary-premium-sms-short-code-regulations -->
<shortcode country="hu" pattern="[01](?:\\d{3}|\\d{9})" premium="0691227910|1784" free="116\\d{3}" />
+ <!-- Indonesia: 2-4 digit codes with a whitelist of free codes -->
+ <shortcode country="id" pattern="\\d{2,4}" free="11|123|1233|1234|2233|228|261|2619|355|388|4444|551|807|808|888|995|999" />
+
<!-- Ireland: 5 digits, 5xxxx (50xxx=free, 5[12]xxx=standard), plus EU:
http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf -->
<shortcode country="ie" pattern="\\d{5}" premium="5[3-9]\\d{3}" free="50\\d{3}|116\\d{3}" standard="5[12]\\d{3}" />
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index baa772e..8b4030a 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -27,6 +27,7 @@ import static android.system.OsConstants.S_IXOTH;
import android.app.PackageInstallObserver;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -3324,11 +3325,6 @@ public class PackageManagerTests extends AndroidTestCase {
}
installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
- try {
- ks = pm.getKeySetByAlias(otherPkgName, "A");
- assertTrue(false); // should have thrown
- } catch (SecurityException e) {
- }
cleanUpInstall(otherPkgName);
ks = pm.getKeySetByAlias(mPkgName, "A");
assertNotNull(ks);
@@ -3852,4 +3848,21 @@ public class PackageManagerTests extends AndroidTestCase {
* how to do tests on updated system apps?
* verify updates to system apps cannot be installed on the sdcard.
*/
+
+ //CM Tests
+ public void testIsComponentProtectedFromSamePackage() {
+ ComponentName testComponentName = new ComponentName("com.android.test",
+ "com.android.test.component.protected");
+ getPm().setComponentProtectedSetting(testComponentName, true);
+ assertFalse(getPm().isComponentProtected(testComponentName.getPackageName(),
+ testComponentName));
+ }
+
+ public void testIsComponentProtectedFromManagers() {
+ ComponentName testComponentName = new ComponentName("com.android.test",
+ "com.android.test.component.protected");
+ getPm().setComponentProtectedSetting(testComponentName, true);
+ assertFalse(getPm().isComponentProtected(testComponentName.getPackageName(),
+ testComponentName));
+ }
}
diff --git a/data/sounds/AllAudio.mk b/data/sounds/AllAudio.mk
index f6d8ee9..e049098 100644
--- a/data/sounds/AllAudio.mk
+++ b/data/sounds/AllAudio.mk
@@ -19,24 +19,16 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
$(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
- $(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
$(LOCAL_PATH)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \
$(LOCAL_PATH)/alarms/ogg/Argon.ogg:system/media/audio/alarms/Argon.ogg \
$(LOCAL_PATH)/alarms/ogg/Barium.ogg:system/media/audio/alarms/Barium.ogg \
$(LOCAL_PATH)/alarms/ogg/Carbon.ogg:system/media/audio/alarms/Carbon.ogg \
- $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
$(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
$(LOCAL_PATH)/alarms/ogg/Krypton.ogg:system/media/audio/alarms/Krypton.ogg \
$(LOCAL_PATH)/alarms/ogg/Neon.ogg:system/media/audio/alarms/Neon.ogg \
- $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
$(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
$(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
$(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
- $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
$(LOCAL_PATH)/alarms/ogg/Scandium.ogg:system/media/audio/alarms/Scandium.ogg \
$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
$(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \
@@ -63,8 +55,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/DontPanic.ogg:system/media/audio/notifications/DontPanic.ogg \
$(LOCAL_PATH)/notifications/Drip.ogg:system/media/audio/notifications/Drip.ogg \
$(LOCAL_PATH)/notifications/Electra.ogg:system/media/audio/notifications/Electra.ogg \
- $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
- $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
$(LOCAL_PATH)/notifications/ogg/Fluorine.ogg:system/media/audio/notifications/Fluorine.ogg \
$(LOCAL_PATH)/notifications/Fomalhaut.ogg:system/media/audio/notifications/Fomalhaut.ogg \
@@ -76,7 +66,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Iridium.ogg:system/media/audio/notifications/Iridium.ogg \
$(LOCAL_PATH)/notifications/ogg/Krypton.ogg:system/media/audio/notifications/Krypton.ogg \
$(LOCAL_PATH)/newwavelabs/KzurbSonar.ogg:system/media/audio/notifications/KzurbSonar.ogg \
- $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/Merope.ogg:system/media/audio/notifications/Merope.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
$(LOCAL_PATH)/newwavelabs/OnTheHunt.ogg:system/media/audio/notifications/OnTheHunt.ogg \
@@ -91,33 +80,135 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Selenium.ogg:system/media/audio/notifications/Selenium.ogg \
$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
$(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \
- $(LOCAL_PATH)/notifications/SpaceSeed.ogg:system/media/audio/notifications/SpaceSeed.ogg \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
$(LOCAL_PATH)/notifications/ogg/Strontium.ogg:system/media/audio/notifications/Strontium.ogg \
$(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
$(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Thallium.ogg:system/media/audio/notifications/Thallium.ogg \
- $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/newwavelabs/Voila.ogg:system/media/audio/notifications/Voila.ogg \
$(LOCAL_PATH)/notifications/ogg/Xenon.ogg:system/media/audio/notifications/Xenon.ogg \
$(LOCAL_PATH)/notifications/ogg/Zirconium.ogg:system/media/audio/notifications/Zirconium.ogg \
- $(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \
$(LOCAL_PATH)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
$(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
$(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
$(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \
$(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \
$(LOCAL_PATH)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg \
- $(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg \
- $(LOCAL_PATH)/ringtones/ANDROMEDA.ogg:system/media/audio/ringtones/ANDROMEDA.ogg \
+
+ifeq ($(TARGET_NEEDS_BOOSTED_SOUNDS),true)
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/ringtones/boosted/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/BOOTES.ogg:system/media/audio/ringtones/BOOTES.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Backroad.ogg:system/media/audio/ringtones/Backroad.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/BussaMove.ogg:system/media/audio/ringtones/BussaMove.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/CASSIOPEIA.ogg:system/media/audio/ringtones/CASSIOPEIA.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Calypso_Steel.ogg:system/media/audio/ringtones/Calypso_Steel.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/CaribbeanIce.ogg:system/media/audio/ringtones/CaribbeanIce.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Champagne_Edition.ogg:system/media/audio/ringtones/Champagne_Edition.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Club_Cubano.ogg:system/media/audio/ringtones/Club_Cubano.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/CrayonRock.ogg:system/media/audio/ringtones/CrayonRock.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/DancinFool.ogg:system/media/audio/ringtones/DancinFool.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/DonMessWivIt.ogg:system/media/audio/ringtones/DonMessWivIt.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Eastern_Sky.ogg:system/media/audio/ringtones/Eastern_Sky.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Enter_the_Nexus.ogg:system/media/audio/ringtones/Enter_the_Nexus.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Eridani.ogg:system/media/audio/ringtones/Eridani.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/EtherShake.ogg:system/media/audio/ringtones/EtherShake.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/FreeFlight.ogg:system/media/audio/ringtones/FreeFlight.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/FriendlyGhost.ogg:system/media/audio/ringtones/FriendlyGhost.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Funk_Yall.ogg:system/media/audio/ringtones/Funk_Yall.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/GameOverGuitar.ogg:system/media/audio/ringtones/GameOverGuitar.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Gimme_Mo_Town.ogg:system/media/audio/ringtones/Gimme_Mo_Town.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Glacial_Groove.ogg:system/media/audio/ringtones/Glacial_Groove.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Growl.ogg:system/media/audio/ringtones/Growl.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/HalfwayHome.ogg:system/media/audio/ringtones/HalfwayHome.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/InsertCoin.ogg:system/media/audio/ringtones/InsertCoin.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Kuma.ogg:system/media/audio/ringtones/Kuma.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Lyra.ogg:system/media/audio/ringtones/Lyra.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Nairobi.ogg:system/media/audio/ringtones/Nairobi.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Nassau.ogg:system/media/audio/ringtones/Nassau.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Paradise_Island.ogg:system/media/audio/ringtones/Paradise_Island.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Playa.ogg:system/media/audio/ringtones/Playa.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Rasalas.ogg:system/media/audio/ringtones/Rasalas.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Revelation.ogg:system/media/audio/ringtones/Revelation.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Road_Trip.ogg:system/media/audio/ringtones/Road_Trip.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/RomancingTheTone.ogg:system/media/audio/ringtones/RomancingTheTone.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Safari.ogg:system/media/audio/ringtones/Safari.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Savannah.ogg:system/media/audio/ringtones/Savannah.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Seville.ogg:system/media/audio/ringtones/Seville.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Shes_All_That.ogg:system/media/audio/ringtones/Shes_All_That.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/SilkyWay.ogg:system/media/audio/ringtones/SilkyWay.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/SitarVsSitar.ogg:system/media/audio/ringtones/SitarVsSitar.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/SpringyJalopy.ogg:system/media/audio/ringtones/SpringyJalopy.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Steppin_Out.ogg:system/media/audio/ringtones/Steppin_Out.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Terminated.ogg:system/media/audio/ringtones/Terminated.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Themos.ogg:system/media/audio/ringtones/Themos.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Third_Eye.ogg:system/media/audio/ringtones/Third_Eye.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Thunderfoot.ogg:system/media/audio/ringtones/Thunderfoot.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/VeryAlarmed.ogg:system/media/audio/ringtones/VeryAlarmed.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/World.ogg:system/media/audio/ringtones/World.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Atria.ogg:system/media/audio/ringtones/Atria.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Callisto.ogg:system/media/audio/ringtones/Callisto.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Dione.ogg:system/media/audio/ringtones/Dione.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Ganymede.ogg:system/media/audio/ringtones/Ganymede.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Luna.ogg:system/media/audio/ringtones/Luna.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Oberon.ogg:system/media/audio/ringtones/Oberon.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Phobos.ogg:system/media/audio/ringtones/Phobos.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Sedna.ogg:system/media/audio/ringtones/Sedna.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Titania.ogg:system/media/audio/ringtones/Titania.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Triton.ogg:system/media/audio/ringtones/Triton.ogg \
+ $(LOCAL_PATH)/ringtones/boosted/Umbriel.ogg:system/media/audio/ringtones/Umbriel.ogg
+else
+PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Atria.ogg:system/media/audio/ringtones/Atria.ogg \
$(LOCAL_PATH)/ringtones/BOOTES.ogg:system/media/audio/ringtones/BOOTES.ogg \
$(LOCAL_PATH)/newwavelabs/Backroad.ogg:system/media/audio/ringtones/Backroad.ogg \
$(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
@@ -126,7 +217,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \
$(LOCAL_PATH)/newwavelabs/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \
$(LOCAL_PATH)/newwavelabs/BussaMove.ogg:system/media/audio/ringtones/BussaMove.ogg \
- $(LOCAL_PATH)/ringtones/CANISMAJOR.ogg:system/media/audio/ringtones/CANISMAJOR.ogg \
$(LOCAL_PATH)/ringtones/CASSIOPEIA.ogg:system/media/audio/ringtones/CASSIOPEIA.ogg \
$(LOCAL_PATH)/newwavelabs/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \
$(LOCAL_PATH)/newwavelabs/Calypso_Steel.ogg:system/media/audio/ringtones/Calypso_Steel.ogg \
@@ -141,7 +231,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \
$(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
$(LOCAL_PATH)/newwavelabs/DancinFool.ogg:system/media/audio/ringtones/DancinFool.ogg \
- $(LOCAL_PATH)/newwavelabs/Ding.ogg:system/media/audio/ringtones/Ding.ogg \
$(LOCAL_PATH)/newwavelabs/DonMessWivIt.ogg:system/media/audio/ringtones/DonMessWivIt.ogg \
$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
$(LOCAL_PATH)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg \
@@ -166,22 +255,18 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/ringtones/Lyra.ogg:system/media/audio/ringtones/Lyra.ogg \
$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
- $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
$(LOCAL_PATH)/newwavelabs/Nairobi.ogg:system/media/audio/ringtones/Nairobi.ogg \
$(LOCAL_PATH)/newwavelabs/Nassau.ogg:system/media/audio/ringtones/Nassau.ogg \
$(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
$(LOCAL_PATH)/newwavelabs/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \
- $(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
$(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
$(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
$(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
- $(LOCAL_PATH)/ringtones/PERSEUS.ogg:system/media/audio/ringtones/PERSEUS.ogg \
$(LOCAL_PATH)/newwavelabs/Paradise_Island.ogg:system/media/audio/ringtones/Paradise_Island.ogg \
$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
$(LOCAL_PATH)/newwavelabs/Playa.ogg:system/media/audio/ringtones/Playa.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
$(LOCAL_PATH)/ringtones/ogg/Rasalas.ogg:system/media/audio/ringtones/Rasalas.ogg \
$(LOCAL_PATH)/newwavelabs/Revelation.ogg:system/media/audio/ringtones/Revelation.ogg \
$(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
@@ -208,13 +293,26 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/Third_Eye.ogg:system/media/audio/ringtones/Third_Eye.ogg \
$(LOCAL_PATH)/newwavelabs/Thunderfoot.ogg:system/media/audio/ringtones/Thunderfoot.ogg \
$(LOCAL_PATH)/newwavelabs/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \
- $(LOCAL_PATH)/ringtones/URSAMINOR.ogg:system/media/audio/ringtones/URSAMINOR.ogg \
$(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
$(LOCAL_PATH)/newwavelabs/VeryAlarmed.ogg:system/media/audio/ringtones/VeryAlarmed.ogg \
$(LOCAL_PATH)/ringtones/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg \
$(LOCAL_PATH)/newwavelabs/World.ogg:system/media/audio/ringtones/World.ogg \
$(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg \
- $(LOCAL_PATH)/ringtones/hydra.ogg:system/media/audio/ringtones/hydra.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Atria.ogg:system/media/audio/ringtones/Atria.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Callisto.ogg:system/media/audio/ringtones/Callisto.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Dione.ogg:system/media/audio/ringtones/Dione.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Ganymede.ogg:system/media/audio/ringtones/Ganymede.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Luna.ogg:system/media/audio/ringtones/Luna.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Oberon.ogg:system/media/audio/ringtones/Oberon.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Phobos.ogg:system/media/audio/ringtones/Phobos.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Sedna.ogg:system/media/audio/ringtones/Sedna.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Titania.ogg:system/media/audio/ringtones/Titania.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Triton.ogg:system/media/audio/ringtones/Triton.ogg \
+ $(LOCAL_PATH)/ringtones/material/ogg/Umbriel.ogg:system/media/audio/ringtones/Umbriel.ogg
+endif
+
+PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
@@ -228,7 +326,25 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
$(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/ogg/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
- $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Ariel.ogg:system/media/audio/notifications/Ariel.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Carme.ogg:system/media/audio/notifications/Carme.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Ceres.ogg:system/media/audio/notifications/Ceres.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Elara.ogg:system/media/audio/notifications/Elara.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Europa.ogg:system/media/audio/notifications/Europa.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Iapetus.ogg:system/media/audio/notifications/Iapetus.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Io.ogg:system/media/audio/notifications/Io.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Rhea.ogg:system/media/audio/notifications/Rhea.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Salacia.ogg:system/media/audio/notifications/Salacia.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Tethys.ogg:system/media/audio/notifications/Tethys.ogg \
+ $(LOCAL_PATH)/notifications/material/ogg/Titan.ogg:system/media/audio/notifications/Titan.ogg
+ifeq ($(TARGET_NEEDS_BOOSTED_SOUNDS),true)
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/effects/boosted/Roachpowder_camera-shutter.aiff:system/media/audio/ui/camera_click.ogg
+else
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg
+endif
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index 5a5eea6..6eaa323 100644
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
@@ -45,7 +45,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
$(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
$(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk
index 0f85b33..b85282a 100644
--- a/data/sounds/AudioPackage11.mk
+++ b/data/sounds/AudioPackage11.mk
@@ -45,7 +45,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
$(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
$(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat_proc48.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
diff --git a/data/sounds/AudioPackage2.mk b/data/sounds/AudioPackage2.mk
index ba9d7e2..a304caa 100644
--- a/data/sounds/AudioPackage2.mk
+++ b/data/sounds/AudioPackage2.mk
@@ -10,8 +10,6 @@
LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
- $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
@@ -26,7 +24,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
$(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
- $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
$(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
$(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
@@ -62,9 +59,7 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
$(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
- $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
$(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
- $(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
$(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
$(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
$(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
diff --git a/data/sounds/AudioPackage3.mk b/data/sounds/AudioPackage3.mk
index 5bfeb42..01b068e 100644
--- a/data/sounds/AudioPackage3.mk
+++ b/data/sounds/AudioPackage3.mk
@@ -10,8 +10,6 @@
LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
- $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
@@ -26,7 +24,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
$(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
- $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
$(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
$(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
@@ -58,9 +55,7 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
$(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
- $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
$(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
- $(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
$(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
$(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
$(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
diff --git a/data/sounds/AudioPackage4.mk b/data/sounds/AudioPackage4.mk
index 43dbe20..bfdb027 100644
--- a/data/sounds/AudioPackage4.mk
+++ b/data/sounds/AudioPackage4.mk
@@ -10,8 +10,6 @@
LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
- $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
@@ -24,9 +22,7 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/Doink.ogg:system/media/audio/notifications/Doink.ogg \
$(LOCAL_PATH)/notifications/Drip.ogg:system/media/audio/notifications/Drip.ogg \
$(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
- $(LOCAL_PATH)/notifications/SpaceSeed.ogg:system/media/audio/notifications/SpaceSeed.ogg \
$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
- $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
$(LOCAL_PATH)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
$(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
$(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
@@ -73,7 +69,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/CrayonRock.ogg:system/media/audio/ringtones/CrayonRock.ogg \
$(LOCAL_PATH)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \
$(LOCAL_PATH)/newwavelabs/DancinFool.ogg:system/media/audio/ringtones/DancinFool.ogg \
- $(LOCAL_PATH)/newwavelabs/Ding.ogg:system/media/audio/ringtones/Ding.ogg \
$(LOCAL_PATH)/newwavelabs/DonMessWivIt.ogg:system/media/audio/ringtones/DonMessWivIt.ogg \
$(LOCAL_PATH)/newwavelabs/Eastern_Sky.ogg:system/media/audio/ringtones/Eastern_Sky.ogg \
$(LOCAL_PATH)/newwavelabs/Enter_the_Nexus.ogg:system/media/audio/ringtones/Enter_the_Nexus.ogg \
@@ -86,7 +81,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
$(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
- $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
$(LOCAL_PATH)/newwavelabs/Nairobi.ogg:system/media/audio/ringtones/Nairobi.ogg \
$(LOCAL_PATH)/newwavelabs/Nassau.ogg:system/media/audio/ringtones/Nassau.ogg \
$(LOCAL_PATH)/newwavelabs/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \
diff --git a/data/sounds/AudioPackage5.mk b/data/sounds/AudioPackage5.mk
index fbbb16a..681fd59 100644
--- a/data/sounds/AudioPackage5.mk
+++ b/data/sounds/AudioPackage5.mk
@@ -31,7 +31,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \
$(LOCAL_PATH)/notifications/Altair.ogg:system/media/audio/notifications/Altair.ogg \
$(LOCAL_PATH)/notifications/Antares.ogg:system/media/audio/notifications/Antares.ogg \
- $(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \
$(LOCAL_PATH)/notifications/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
$(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \
$(LOCAL_PATH)/notifications/Capella.ogg:system/media/audio/notifications/Capella.ogg \
@@ -47,7 +46,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \
$(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \
$(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \
- $(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg \
$(LOCAL_PATH)/ringtones/ANDROMEDA.ogg:system/media/audio/ringtones/ANDROMEDA.ogg \
$(LOCAL_PATH)/ringtones/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
$(LOCAL_PATH)/ringtones/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
diff --git a/data/sounds/AudioPackage6.mk b/data/sounds/AudioPackage6.mk
index c843fdc..3a618cf 100644
--- a/data/sounds/AudioPackage6.mk
+++ b/data/sounds/AudioPackage6.mk
@@ -9,8 +9,6 @@ LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/alarms/ogg/Barium.ogg:system/media/audio/alarms/Barium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
$(LOCAL_PATH)/alarms/ogg/Scandium.ogg:system/media/audio/alarms/Scandium.ogg \
$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index ce82651..f51fb05 100644
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -8,12 +8,6 @@
LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
@@ -35,7 +29,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
- $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
$(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
@@ -43,7 +36,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
diff --git a/data/sounds/AudioPackage7alt.mk b/data/sounds/AudioPackage7alt.mk
index db468f3..db67e2b 100644
--- a/data/sounds/AudioPackage7alt.mk
+++ b/data/sounds/AudioPackage7alt.mk
@@ -34,7 +34,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
- $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
$(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
@@ -42,7 +41,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
index 4112c18..d2bf724 100644
--- a/data/sounds/AudioPackage8.mk
+++ b/data/sounds/AudioPackage8.mk
@@ -8,14 +8,7 @@
LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
$(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
- $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
@@ -37,7 +30,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
- $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
$(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
@@ -45,7 +37,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk
index 1b430c0..e89dbb1 100644
--- a/data/sounds/AudioPackage9.mk
+++ b/data/sounds/AudioPackage9.mk
@@ -44,6 +44,5 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
$(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
$(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
- $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
$(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg
diff --git a/data/sounds/F1_MissedCall.ogg b/data/sounds/F1_MissedCall.ogg
deleted file mode 100644
index 396d78f..0000000
--- a/data/sounds/F1_MissedCall.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/F1_New_MMS.ogg b/data/sounds/F1_New_MMS.ogg
deleted file mode 100644
index d3cbdfc..0000000
--- a/data/sounds/F1_New_MMS.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/OriginalAudio.mk b/data/sounds/OriginalAudio.mk
index e1ca24b..9e8a42d 100644
--- a/data/sounds/OriginalAudio.mk
+++ b/data/sounds/OriginalAudio.mk
@@ -9,8 +9,6 @@
LOCAL_PATH:= frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
- $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
@@ -25,7 +23,6 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
$(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
- $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
$(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
$(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
$(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
@@ -50,9 +47,7 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
$(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
- $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
$(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
- $(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
$(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
$(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
$(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
diff --git a/data/sounds/Ring_Digital_02.ogg b/data/sounds/Ring_Digital_02.ogg
index f823739..6345151 100644
--- a/data/sounds/Ring_Digital_02.ogg
+++ b/data/sounds/Ring_Digital_02.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Cesium.ogg b/data/sounds/alarms/ogg/Cesium.ogg
deleted file mode 100644
index a8c379a..0000000
--- a/data/sounds/alarms/ogg/Cesium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/alarms/ogg/Fermium.ogg b/data/sounds/alarms/ogg/Fermium.ogg
deleted file mode 100644
index d8f6124..0000000
--- a/data/sounds/alarms/ogg/Fermium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/alarms/ogg/Hassium.ogg b/data/sounds/alarms/ogg/Hassium.ogg
deleted file mode 100644
index 793c269..0000000
--- a/data/sounds/alarms/ogg/Hassium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/alarms/ogg/Neptunium.ogg b/data/sounds/alarms/ogg/Neptunium.ogg
deleted file mode 100644
index d99f133..0000000
--- a/data/sounds/alarms/ogg/Neptunium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/alarms/ogg/Nobelium.ogg b/data/sounds/alarms/ogg/Nobelium.ogg
deleted file mode 100644
index 1f94d1e..0000000
--- a/data/sounds/alarms/ogg/Nobelium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/alarms/ogg/Plutonium.ogg b/data/sounds/alarms/ogg/Plutonium.ogg
deleted file mode 100644
index 5e9a750..0000000
--- a/data/sounds/alarms/ogg/Plutonium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/alarms/ogg/Promethium.ogg b/data/sounds/alarms/ogg/Promethium.ogg
deleted file mode 100644
index d5f0893..0000000
--- a/data/sounds/alarms/ogg/Promethium.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/effects/boosted/Roachpowder_camera-shutter.aiff b/data/sounds/effects/boosted/Roachpowder_camera-shutter.aiff
new file mode 100644
index 0000000..e0534ed
--- /dev/null
+++ b/data/sounds/effects/boosted/Roachpowder_camera-shutter.aiff
Binary files differ
diff --git a/data/sounds/newwavelabs/Ding.ogg b/data/sounds/newwavelabs/Ding.ogg
deleted file mode 100644
index 72a86c0..0000000
--- a/data/sounds/newwavelabs/Ding.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/newwavelabs/MildlyAlarming.ogg b/data/sounds/newwavelabs/MildlyAlarming.ogg
deleted file mode 100644
index 9025b18..0000000
--- a/data/sounds/newwavelabs/MildlyAlarming.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/newwavelabs/Noises1.ogg b/data/sounds/newwavelabs/Noises1.ogg
deleted file mode 100644
index 829b4fa..0000000
--- a/data/sounds/newwavelabs/Noises1.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/SpaceSeed.ogg b/data/sounds/notifications/SpaceSeed.ogg
deleted file mode 100644
index e69024d..0000000
--- a/data/sounds/notifications/SpaceSeed.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/Tinkerbell.ogg b/data/sounds/notifications/Tinkerbell.ogg
deleted file mode 100644
index 434e96b..0000000
--- a/data/sounds/notifications/Tinkerbell.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/arcturus.ogg b/data/sounds/notifications/arcturus.ogg
deleted file mode 100644
index 9d73103..0000000
--- a/data/sounds/notifications/arcturus.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/ogg/Lalande.ogg b/data/sounds/notifications/ogg/Lalande.ogg
deleted file mode 100644
index 42c6271..0000000
--- a/data/sounds/notifications/ogg/Lalande.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/ogg/Tejat.ogg b/data/sounds/notifications/ogg/Tejat.ogg
deleted file mode 100644
index 04ba06c..0000000
--- a/data/sounds/notifications/ogg/Tejat.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/ogg/Tejat_proc48.ogg b/data/sounds/notifications/ogg/Tejat_proc48.ogg
deleted file mode 100644
index b1637d7..0000000
--- a/data/sounds/notifications/ogg/Tejat_proc48.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/vega.ogg b/data/sounds/notifications/vega.ogg
deleted file mode 100644
index e596e60..0000000
--- a/data/sounds/notifications/vega.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Andromeda.ogg b/data/sounds/ringtones/boosted/Andromeda.ogg
new file mode 100644
index 0000000..68dda8b
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Andromeda.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Aquila.ogg b/data/sounds/ringtones/boosted/Aquila.ogg
new file mode 100644
index 0000000..569c248
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Aquila.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/ArgoNavis.ogg b/data/sounds/ringtones/boosted/ArgoNavis.ogg
new file mode 100644
index 0000000..797f9fa
--- /dev/null
+++ b/data/sounds/ringtones/boosted/ArgoNavis.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Atria.ogg b/data/sounds/ringtones/boosted/Atria.ogg
new file mode 100644
index 0000000..c37feaa
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Atria.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/BOOTES.ogg b/data/sounds/ringtones/boosted/BOOTES.ogg
new file mode 100644
index 0000000..affb115
--- /dev/null
+++ b/data/sounds/ringtones/boosted/BOOTES.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Backroad.ogg b/data/sounds/ringtones/boosted/Backroad.ogg
new file mode 100644
index 0000000..e1ee99b
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Backroad.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/BeatPlucker.ogg b/data/sounds/ringtones/boosted/BeatPlucker.ogg
new file mode 100644
index 0000000..f619d44
--- /dev/null
+++ b/data/sounds/ringtones/boosted/BeatPlucker.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/BentleyDubs.ogg b/data/sounds/ringtones/boosted/BentleyDubs.ogg
new file mode 100644
index 0000000..86af876
--- /dev/null
+++ b/data/sounds/ringtones/boosted/BentleyDubs.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Big_Easy.ogg b/data/sounds/ringtones/boosted/Big_Easy.ogg
new file mode 100644
index 0000000..e02a3c8
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Big_Easy.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/BirdLoop.ogg b/data/sounds/ringtones/boosted/BirdLoop.ogg
new file mode 100644
index 0000000..28220f2
--- /dev/null
+++ b/data/sounds/ringtones/boosted/BirdLoop.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Bollywood.ogg b/data/sounds/ringtones/boosted/Bollywood.ogg
new file mode 100644
index 0000000..26b69d2
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Bollywood.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/BussaMove.ogg b/data/sounds/ringtones/boosted/BussaMove.ogg
new file mode 100644
index 0000000..c8eb07b
--- /dev/null
+++ b/data/sounds/ringtones/boosted/BussaMove.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/CASSIOPEIA.ogg b/data/sounds/ringtones/boosted/CASSIOPEIA.ogg
new file mode 100644
index 0000000..38e1b0f
--- /dev/null
+++ b/data/sounds/ringtones/boosted/CASSIOPEIA.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Cairo.ogg b/data/sounds/ringtones/boosted/Cairo.ogg
new file mode 100644
index 0000000..a065a21
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Cairo.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Callisto.ogg b/data/sounds/ringtones/boosted/Callisto.ogg
new file mode 100644
index 0000000..1f5977e
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Callisto.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Calypso_Steel.ogg b/data/sounds/ringtones/boosted/Calypso_Steel.ogg
new file mode 100644
index 0000000..91eb551
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Calypso_Steel.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/CanisMajor.ogg b/data/sounds/ringtones/boosted/CanisMajor.ogg
new file mode 100644
index 0000000..0830c0f
--- /dev/null
+++ b/data/sounds/ringtones/boosted/CanisMajor.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/CaribbeanIce.ogg b/data/sounds/ringtones/boosted/CaribbeanIce.ogg
new file mode 100644
index 0000000..dcb8da6
--- /dev/null
+++ b/data/sounds/ringtones/boosted/CaribbeanIce.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Carina.ogg b/data/sounds/ringtones/boosted/Carina.ogg
new file mode 100644
index 0000000..007eea3
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Carina.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Centaurus.ogg b/data/sounds/ringtones/boosted/Centaurus.ogg
new file mode 100644
index 0000000..f374f08
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Centaurus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Champagne_Edition.ogg b/data/sounds/ringtones/boosted/Champagne_Edition.ogg
new file mode 100644
index 0000000..35ffb87
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Champagne_Edition.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Club_Cubano.ogg b/data/sounds/ringtones/boosted/Club_Cubano.ogg
new file mode 100644
index 0000000..5de77f8
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Club_Cubano.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/CrayonRock.ogg b/data/sounds/ringtones/boosted/CrayonRock.ogg
new file mode 100644
index 0000000..625e80d
--- /dev/null
+++ b/data/sounds/ringtones/boosted/CrayonRock.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/CrazyDream.ogg b/data/sounds/ringtones/boosted/CrazyDream.ogg
new file mode 100644
index 0000000..cb53fdd
--- /dev/null
+++ b/data/sounds/ringtones/boosted/CrazyDream.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/CurveBall.ogg b/data/sounds/ringtones/boosted/CurveBall.ogg
new file mode 100644
index 0000000..7655585
--- /dev/null
+++ b/data/sounds/ringtones/boosted/CurveBall.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Cygnus.ogg b/data/sounds/ringtones/boosted/Cygnus.ogg
new file mode 100644
index 0000000..ed777fd
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Cygnus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/DancinFool.ogg b/data/sounds/ringtones/boosted/DancinFool.ogg
new file mode 100644
index 0000000..60ff0e9
--- /dev/null
+++ b/data/sounds/ringtones/boosted/DancinFool.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Dione.ogg b/data/sounds/ringtones/boosted/Dione.ogg
new file mode 100644
index 0000000..7fff3c2
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Dione.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/DonMessWivIt.ogg b/data/sounds/ringtones/boosted/DonMessWivIt.ogg
new file mode 100644
index 0000000..c6f9e3c
--- /dev/null
+++ b/data/sounds/ringtones/boosted/DonMessWivIt.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Draco.ogg b/data/sounds/ringtones/boosted/Draco.ogg
new file mode 100644
index 0000000..66da7b4
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Draco.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/DreamTheme.ogg b/data/sounds/ringtones/boosted/DreamTheme.ogg
new file mode 100644
index 0000000..d0b0708
--- /dev/null
+++ b/data/sounds/ringtones/boosted/DreamTheme.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Eastern_Sky.ogg b/data/sounds/ringtones/boosted/Eastern_Sky.ogg
new file mode 100644
index 0000000..87273bc
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Eastern_Sky.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Enter_the_Nexus.ogg b/data/sounds/ringtones/boosted/Enter_the_Nexus.ogg
new file mode 100644
index 0000000..6d08950
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Enter_the_Nexus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Eridani.ogg b/data/sounds/ringtones/boosted/Eridani.ogg
new file mode 100644
index 0000000..7a02018
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Eridani.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/EtherShake.ogg b/data/sounds/ringtones/boosted/EtherShake.ogg
new file mode 100644
index 0000000..1dee33a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/EtherShake.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/FreeFlight.ogg b/data/sounds/ringtones/boosted/FreeFlight.ogg
new file mode 100644
index 0000000..9e84e31
--- /dev/null
+++ b/data/sounds/ringtones/boosted/FreeFlight.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/FriendlyGhost.ogg b/data/sounds/ringtones/boosted/FriendlyGhost.ogg
new file mode 100644
index 0000000..c44e6c0
--- /dev/null
+++ b/data/sounds/ringtones/boosted/FriendlyGhost.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Funk_Yall.ogg b/data/sounds/ringtones/boosted/Funk_Yall.ogg
new file mode 100644
index 0000000..43f98aa
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Funk_Yall.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/GameOverGuitar.ogg b/data/sounds/ringtones/boosted/GameOverGuitar.ogg
new file mode 100644
index 0000000..2da9602
--- /dev/null
+++ b/data/sounds/ringtones/boosted/GameOverGuitar.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Ganymede.ogg b/data/sounds/ringtones/boosted/Ganymede.ogg
new file mode 100644
index 0000000..aadad88
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Ganymede.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Gimme_Mo_Town.ogg b/data/sounds/ringtones/boosted/Gimme_Mo_Town.ogg
new file mode 100644
index 0000000..86526a5
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Gimme_Mo_Town.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Girtab.ogg b/data/sounds/ringtones/boosted/Girtab.ogg
new file mode 100644
index 0000000..1a7a7b0
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Girtab.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Glacial_Groove.ogg b/data/sounds/ringtones/boosted/Glacial_Groove.ogg
new file mode 100644
index 0000000..d7cab21
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Glacial_Groove.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Growl.ogg b/data/sounds/ringtones/boosted/Growl.ogg
new file mode 100644
index 0000000..e418785
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Growl.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/HalfwayHome.ogg b/data/sounds/ringtones/boosted/HalfwayHome.ogg
new file mode 100644
index 0000000..3abb74a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/HalfwayHome.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Hydra.ogg b/data/sounds/ringtones/boosted/Hydra.ogg
new file mode 100644
index 0000000..1783b8d
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Hydra.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/InsertCoin.ogg b/data/sounds/ringtones/boosted/InsertCoin.ogg
new file mode 100644
index 0000000..a7cd52b
--- /dev/null
+++ b/data/sounds/ringtones/boosted/InsertCoin.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Kuma.ogg b/data/sounds/ringtones/boosted/Kuma.ogg
new file mode 100644
index 0000000..2ab496c
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Kuma.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/LoopyLounge.ogg b/data/sounds/ringtones/boosted/LoopyLounge.ogg
new file mode 100644
index 0000000..4463e79
--- /dev/null
+++ b/data/sounds/ringtones/boosted/LoopyLounge.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/LoveFlute.ogg b/data/sounds/ringtones/boosted/LoveFlute.ogg
new file mode 100644
index 0000000..2074360
--- /dev/null
+++ b/data/sounds/ringtones/boosted/LoveFlute.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Luna.ogg b/data/sounds/ringtones/boosted/Luna.ogg
new file mode 100644
index 0000000..b222f5a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Luna.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Lyra.ogg b/data/sounds/ringtones/boosted/Lyra.ogg
new file mode 100644
index 0000000..1c79eeb
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Lyra.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Machina.ogg b/data/sounds/ringtones/boosted/Machina.ogg
new file mode 100644
index 0000000..2218e11
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Machina.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/MidEvilJaunt.ogg b/data/sounds/ringtones/boosted/MidEvilJaunt.ogg
new file mode 100644
index 0000000..8437ebb
--- /dev/null
+++ b/data/sounds/ringtones/boosted/MidEvilJaunt.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Nairobi.ogg b/data/sounds/ringtones/boosted/Nairobi.ogg
new file mode 100644
index 0000000..b43723d
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Nairobi.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Nassau.ogg b/data/sounds/ringtones/boosted/Nassau.ogg
new file mode 100644
index 0000000..96f26ba
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Nassau.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/NewPlayer.ogg b/data/sounds/ringtones/boosted/NewPlayer.ogg
new file mode 100644
index 0000000..adf42f7
--- /dev/null
+++ b/data/sounds/ringtones/boosted/NewPlayer.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/No_Limits.ogg b/data/sounds/ringtones/boosted/No_Limits.ogg
new file mode 100644
index 0000000..4055fdb
--- /dev/null
+++ b/data/sounds/ringtones/boosted/No_Limits.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Noises2.ogg b/data/sounds/ringtones/boosted/Noises2.ogg
new file mode 100644
index 0000000..0861bc2
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Noises2.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Noises3.ogg b/data/sounds/ringtones/boosted/Noises3.ogg
new file mode 100644
index 0000000..7aa83af
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Noises3.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Oberon.ogg b/data/sounds/ringtones/boosted/Oberon.ogg
new file mode 100644
index 0000000..4b6e8f1
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Oberon.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/OrganDub.ogg b/data/sounds/ringtones/boosted/OrganDub.ogg
new file mode 100644
index 0000000..7494355
--- /dev/null
+++ b/data/sounds/ringtones/boosted/OrganDub.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Orion.ogg b/data/sounds/ringtones/boosted/Orion.ogg
new file mode 100644
index 0000000..e283ea5
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Orion.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Paradise_Island.ogg b/data/sounds/ringtones/boosted/Paradise_Island.ogg
new file mode 100644
index 0000000..63ee12a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Paradise_Island.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Pegasus.ogg b/data/sounds/ringtones/boosted/Pegasus.ogg
new file mode 100644
index 0000000..87b8a67
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Pegasus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Perseus.ogg b/data/sounds/ringtones/boosted/Perseus.ogg
new file mode 100644
index 0000000..80fb2bd
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Perseus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Phobos.ogg b/data/sounds/ringtones/boosted/Phobos.ogg
new file mode 100644
index 0000000..e3195b0
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Phobos.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Playa.ogg b/data/sounds/ringtones/boosted/Playa.ogg
new file mode 100644
index 0000000..7a69073
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Playa.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Pyxis.ogg b/data/sounds/ringtones/boosted/Pyxis.ogg
new file mode 100644
index 0000000..77401f6
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Pyxis.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Rasalas.ogg b/data/sounds/ringtones/boosted/Rasalas.ogg
new file mode 100644
index 0000000..beb985a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Rasalas.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Revelation.ogg b/data/sounds/ringtones/boosted/Revelation.ogg
new file mode 100644
index 0000000..5cce13f
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Revelation.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Rigel.ogg b/data/sounds/ringtones/boosted/Rigel.ogg
new file mode 100644
index 0000000..8aa4348
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Rigel.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Ring_Classic_02.ogg b/data/sounds/ringtones/boosted/Ring_Classic_02.ogg
new file mode 100644
index 0000000..eb65743
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Ring_Classic_02.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Ring_Digital_02.ogg b/data/sounds/ringtones/boosted/Ring_Digital_02.ogg
new file mode 100644
index 0000000..76694ed
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Ring_Digital_02.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Ring_Synth_02.ogg b/data/sounds/ringtones/boosted/Ring_Synth_02.ogg
new file mode 100644
index 0000000..4b48c4b
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Ring_Synth_02.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Ring_Synth_04.ogg b/data/sounds/ringtones/boosted/Ring_Synth_04.ogg
new file mode 100644
index 0000000..b63a3e5
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Ring_Synth_04.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Road_Trip.ogg b/data/sounds/ringtones/boosted/Road_Trip.ogg
new file mode 100644
index 0000000..2af6fd0
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Road_Trip.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/RomancingTheTone.ogg b/data/sounds/ringtones/boosted/RomancingTheTone.ogg
new file mode 100644
index 0000000..fef977c
--- /dev/null
+++ b/data/sounds/ringtones/boosted/RomancingTheTone.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Safari.ogg b/data/sounds/ringtones/boosted/Safari.ogg
new file mode 100644
index 0000000..af9935f
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Safari.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Savannah.ogg b/data/sounds/ringtones/boosted/Savannah.ogg
new file mode 100644
index 0000000..c700f90
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Savannah.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Scarabaeus.ogg b/data/sounds/ringtones/boosted/Scarabaeus.ogg
new file mode 100644
index 0000000..627d400
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Scarabaeus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Sceptrum.ogg b/data/sounds/ringtones/boosted/Sceptrum.ogg
new file mode 100644
index 0000000..a9e41b7
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Sceptrum.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Sedna.ogg b/data/sounds/ringtones/boosted/Sedna.ogg
new file mode 100644
index 0000000..9e84526
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Sedna.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Seville.ogg b/data/sounds/ringtones/boosted/Seville.ogg
new file mode 100644
index 0000000..539152a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Seville.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Shes_All_That.ogg b/data/sounds/ringtones/boosted/Shes_All_That.ogg
new file mode 100644
index 0000000..6984976
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Shes_All_That.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/SilkyWay.ogg b/data/sounds/ringtones/boosted/SilkyWay.ogg
new file mode 100644
index 0000000..16dbd5a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/SilkyWay.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/SitarVsSitar.ogg b/data/sounds/ringtones/boosted/SitarVsSitar.ogg
new file mode 100644
index 0000000..dbd739e
--- /dev/null
+++ b/data/sounds/ringtones/boosted/SitarVsSitar.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Solarium.ogg b/data/sounds/ringtones/boosted/Solarium.ogg
new file mode 100644
index 0000000..f1e2f96
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Solarium.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/SpringyJalopy.ogg b/data/sounds/ringtones/boosted/SpringyJalopy.ogg
new file mode 100644
index 0000000..f3b9b20
--- /dev/null
+++ b/data/sounds/ringtones/boosted/SpringyJalopy.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Steppin_Out.ogg b/data/sounds/ringtones/boosted/Steppin_Out.ogg
new file mode 100644
index 0000000..ae86b48
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Steppin_Out.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Terminated.ogg b/data/sounds/ringtones/boosted/Terminated.ogg
new file mode 100644
index 0000000..8543392
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Terminated.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Testudo.ogg b/data/sounds/ringtones/boosted/Testudo.ogg
new file mode 100644
index 0000000..9fafd9a
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Testudo.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Themos.ogg b/data/sounds/ringtones/boosted/Themos.ogg
new file mode 100644
index 0000000..25c5411
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Themos.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Third_Eye.ogg b/data/sounds/ringtones/boosted/Third_Eye.ogg
new file mode 100644
index 0000000..e148786
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Third_Eye.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Thunderfoot.ogg b/data/sounds/ringtones/boosted/Thunderfoot.ogg
new file mode 100644
index 0000000..0f080f2
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Thunderfoot.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Titania.ogg b/data/sounds/ringtones/boosted/Titania.ogg
new file mode 100644
index 0000000..20714ff
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Titania.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Triton.ogg b/data/sounds/ringtones/boosted/Triton.ogg
new file mode 100644
index 0000000..cfdf7b9
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Triton.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/TwirlAway.ogg b/data/sounds/ringtones/boosted/TwirlAway.ogg
new file mode 100644
index 0000000..6b00e8e
--- /dev/null
+++ b/data/sounds/ringtones/boosted/TwirlAway.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Umbriel.ogg b/data/sounds/ringtones/boosted/Umbriel.ogg
new file mode 100644
index 0000000..03d39ef
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Umbriel.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/UrsaMinor.ogg b/data/sounds/ringtones/boosted/UrsaMinor.ogg
new file mode 100644
index 0000000..b642ce7
--- /dev/null
+++ b/data/sounds/ringtones/boosted/UrsaMinor.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/VeryAlarmed.ogg b/data/sounds/ringtones/boosted/VeryAlarmed.ogg
new file mode 100644
index 0000000..bbbff62
--- /dev/null
+++ b/data/sounds/ringtones/boosted/VeryAlarmed.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Vespa.ogg b/data/sounds/ringtones/boosted/Vespa.ogg
new file mode 100644
index 0000000..b3bbd74
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Vespa.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/World.ogg b/data/sounds/ringtones/boosted/World.ogg
new file mode 100644
index 0000000..76f4eea
--- /dev/null
+++ b/data/sounds/ringtones/boosted/World.ogg
Binary files differ
diff --git a/data/sounds/ringtones/boosted/Zeta.ogg b/data/sounds/ringtones/boosted/Zeta.ogg
new file mode 100644
index 0000000..cf76667
--- /dev/null
+++ b/data/sounds/ringtones/boosted/Zeta.ogg
Binary files differ
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 3e4d93b..ba2a890 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -96,6 +96,7 @@ public final class Bitmap implements Parcelable {
if (sDefaultDensity >= 0) {
return sDefaultDensity;
}
+ //noinspection deprecation
sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
return sDefaultDensity;
}
diff --git a/graphics/java/android/graphics/FontListConverter.java b/graphics/java/android/graphics/FontListConverter.java
new file mode 100644
index 0000000..c675c88
--- /dev/null
+++ b/graphics/java/android/graphics/FontListConverter.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.graphics;
+
+import android.graphics.FontListParser;
+import android.graphics.FontListParser.Alias;
+import android.graphics.FontListParser.Font;
+import android.graphics.LegacyFontListParser.Family;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+/**
+ * Converts a list of Family to FontListParser.Config
+ * {@hide}
+ */
+public class FontListConverter {
+ // These array values were determined by the order
+ // of fonts in a fileset. The order is:
+ // "Normal, Bold, Italic, BoldItalic"
+ // Additionally the weight values in L's fonts.xml
+ // are used to determine a generic weight value for each type
+ // e.g The 2nd entry in a fileset is the bold font.
+ protected static final int[] WEIGHTS = { 400, 700, 400, 700 };
+ protected static boolean[] ITALICS = { false, false, true, true };
+ protected static final int DEFAULT_WEIGHT = WEIGHTS[0];
+
+ // Arbitrarily chosen list based on L's fonts.xml.
+ // There could be more out there, but we can't use a generic pattern of "fontName-styleName"
+ // as "sans-serif" would be translated as a font called "sans" with the style "serif".
+ public static final String[] STYLES = {
+ "thin",
+ "light",
+ "medium",
+ "black"
+ };
+
+ // Maps a "normal" family to a list of similar families differing by style
+ // Example: "sans-serif" -> { sans-serif-thin, sans-serif-light, sans-serif-medium }
+ private HashMap<Family, List<Family>> mFamilyVariants = new HashMap<Family, List<Family>>();
+ private List<Family> mFamilies =
+ new ArrayList<Family >();
+ private String mFontDir;
+
+
+ public FontListConverter(List<Family> families, String fontDir) {
+ mFamilies.addAll(families);
+ mFontDir = fontDir;
+ findFamilyVariants();
+ }
+
+ public FontListConverter(Family family, String fontDir) {
+ mFamilies.add(family);
+ mFontDir = fontDir;
+ findFamilyVariants();
+ }
+
+ private void findFamilyVariants() {
+ for(Family family : mFamilies) {
+ if (isNormalStyle(family)) {
+ List<Family> variants = findVariants(family, mFamilies);
+ mFamilyVariants.put(family, variants);
+ }
+ }
+ }
+
+ private List<Family> findVariants(Family normalFamily, List<Family> legacyFamilies) {
+ List<Family> variants = new ArrayList<Family>();
+
+ String normalFamilyName = normalFamily.getName();
+
+ for(Family family : legacyFamilies) {
+ String name = family.getName();
+
+ if (name.startsWith(normalFamilyName) && !isNormalStyle(family)) {
+ variants.add(family);
+ }
+ }
+ return variants;
+ }
+
+ public FontListParser.Config convert() {
+ FontListParser.Config config = new FontListParser.Config();
+ config.families.addAll(convertFamilies());
+ config.aliases.addAll(createAliases());
+ return config;
+ }
+
+ /**
+ * A "normal" style is just standard font,
+ * eg Roboto is normal. Roboto-Thin is styled.
+ */
+ protected boolean isNormalStyle(Family family) {
+ String name = family.getName();
+ if (name == null) return false;
+
+ for(String style : STYLES) {
+ if (name.endsWith('-' + style)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected List<FontListParser.Family> convertFamilies() {
+ List<FontListParser.Family> convertedFamilies = new ArrayList<FontListParser.Family>();
+
+ // Only convert normal families. Each normal family will add in its variants
+ for(Family family : mFamilyVariants.keySet()) {
+ convertedFamilies.add(convertFamily(family));
+ }
+
+ return convertedFamilies;
+ }
+
+ protected FontListParser.Family convertFamily(Family legacyFamily) {
+ List<String> nameset = legacyFamily.nameset;
+ List<String> fileset = legacyFamily.fileset;
+
+ // Arbitrarily choose the first entry in the nameset to be the name
+ String name = nameset.isEmpty() ? null : nameset.get(0);
+
+ List<Font> fonts = convertFonts(fileset);
+
+ // Add fonts from other variants
+ for(Family variantFamily : mFamilyVariants.get(legacyFamily)) {
+ fonts.addAll(convertFonts(variantFamily.fileset));
+ }
+
+ return new FontListParser.Family(name, fonts, null, null);
+ }
+
+ protected List<FontListParser.Font> convertFonts(List<String> fileset) {
+ List<Font> fonts = new ArrayList<Font>();
+
+ for(int i=0; i < fileset.size(); i++) {
+ String fullpath = mFontDir + File.separatorChar + fileset.get(i);
+ // fileset should only be 4 entries, but if
+ // its more we can just assign a default.
+ int weight = i < WEIGHTS.length ? WEIGHTS[i] : DEFAULT_WEIGHT;
+ boolean isItalic = i < ITALICS.length ? ITALICS[i] : false;
+
+ Font font = new Font(fullpath, weight, isItalic);
+ fonts.add(font);
+ }
+
+ return fonts;
+ }
+
+ protected List<Alias> createAliases() {
+ List<Alias> aliases = new ArrayList<Alias>();
+
+ for(Family family : mFamilyVariants.keySet()) {
+ // Get any aliases that might be from a normal family's nameset.
+ // eg sans-serif, arial, helvetica, tahoma etc.
+ if (isNormalStyle(family)) {
+ aliases.addAll(adaptNamesetAliases(family.nameset));
+ }
+ }
+
+ aliases.addAll(getAliasesForRelatedFamilies());
+
+ return aliases;
+ }
+
+ private List<Alias> getAliasesForRelatedFamilies() {
+ List<Alias> aliases = new ArrayList<Alias>();
+
+ for(Entry<Family, List<Family>> entry : mFamilyVariants.entrySet()) {
+ String toName = entry.getKey().nameset.get(0);
+ List<Family> relatedFamilies = entry.getValue();
+ for(Family relatedFamily : relatedFamilies) {
+ aliases.addAll(adaptNamesetAliases(relatedFamily.nameset, toName));
+ }
+ }
+ return aliases;
+ }
+
+ private List<Alias> adaptNamesetAliases(List<String> nameset, String toName) {
+ List<Alias> aliases = new ArrayList<Alias>();
+ for(String name : nameset) {
+ Alias alias = new Alias();
+ alias.name = name;
+ alias.toName = toName;
+ aliases.add(alias);
+ }
+ return aliases;
+ }
+
+ private List<Alias> adaptNamesetAliases(List<String> nameset) {
+ List<Alias> aliases = new ArrayList<Alias>();
+ if (nameset.size() < 2) return aliases; // An alias requires a name and toName
+
+ String toName = nameset.get(0);
+ for(int i = 1; i < nameset.size(); i++) {
+ Alias alias = new Alias();
+ alias.name = nameset.get(i);
+ alias.toName = toName;
+ aliases.add(alias);
+ }
+
+ return aliases;
+ }
+}
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 97081f9..d789690 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -21,6 +21,9 @@ import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -74,25 +77,83 @@ public class FontListParser {
}
/* Parse fallback list (no names) */
- public static Config parse(InputStream in) throws XmlPullParserException, IOException {
+ public static Config parse(File configFilename, String fontDir)
+ throws XmlPullParserException, IOException {
+ FileInputStream in = null;
+ in = new FileInputStream(configFilename);
+ return FontListParser.parse(in, fontDir);
+ }
+
+ /* Parse fallback list (no names) */
+ public static Config parse(InputStream in, String fontDir)
+ throws XmlPullParserException, IOException {
+ BufferedInputStream bis = null;
try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- parser.nextTag();
- return readFamilies(parser);
+ // wrap input stream in a BufferedInputStream, if it's not already, for mark support
+ if (!(in instanceof BufferedInputStream)) {
+ bis = new BufferedInputStream(in);
+ } else {
+ bis = (BufferedInputStream) in;
+ }
+ // mark the beginning so we can reset to this position after checking format
+ bis.mark(in.available());
+ if (isLegacyFormat(bis)) {
+ return parseLegacyFormat(bis, fontDir);
+ } else {
+ return parseNormalFormat(bis, fontDir);
+ }
+ } finally {
+ if (bis != null) bis.close();
+ }
+ }
+
+ public static boolean isLegacyFormat(InputStream in)
+ throws XmlPullParserException, IOException {
+ if (!in.markSupported()) {
+ throw new IllegalArgumentException("InputStream does not support mark");
+ }
+ boolean isLegacy = false;
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parser.nextTag();
+ parser.require(XmlPullParser.START_TAG, null, "familyset");
+ String version = parser.getAttributeValue(null, "version");
+ isLegacy = version == null;
+
+ // reset the stream so we can read it
+ in.reset();
+
+ return isLegacy;
+ }
+
+ public static Config parseLegacyFormat(InputStream in, String dirName)
+ throws XmlPullParserException, IOException {
+ try {
+ List<LegacyFontListParser.Family> legacyFamilies = LegacyFontListParser.parse(in);
+ FontListConverter converter = new FontListConverter(legacyFamilies, dirName);
+ return converter.convert();
} finally {
in.close();
}
}
- private static Config readFamilies(XmlPullParser parser)
+ public static Config parseNormalFormat(InputStream in, String dirName)
+ throws XmlPullParserException, IOException {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parser.nextTag();
+ return readFamilies(parser, dirName);
+ }
+
+ private static Config readFamilies(XmlPullParser parser, String dirPath)
throws XmlPullParserException, IOException {
Config config = new Config();
parser.require(XmlPullParser.START_TAG, null, "familyset");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
if (parser.getName().equals("family")) {
- config.families.add(readFamily(parser));
+ config.families.add(readFamily(parser, dirPath));
} else if (parser.getName().equals("alias")) {
config.aliases.add(readAlias(parser));
} else {
@@ -102,7 +163,7 @@ public class FontListParser {
return config;
}
- private static Family readFamily(XmlPullParser parser)
+ private static Family readFamily(XmlPullParser parser, String dirPath)
throws XmlPullParserException, IOException {
String name = parser.getAttributeValue(null, "name");
String lang = parser.getAttributeValue(null, "lang");
@@ -116,7 +177,7 @@ public class FontListParser {
int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));
String filename = parser.nextText();
- String fullFilename = "/system/fonts/" + filename;
+ String fullFilename = dirPath + File.separatorChar + filename;
fonts.add(new Font(fullFilename, weight, isItalic));
} else {
skip(parser);
diff --git a/graphics/java/android/graphics/LegacyFontListParser.java b/graphics/java/android/graphics/LegacyFontListParser.java
new file mode 100644
index 0000000..22923cb
--- /dev/null
+++ b/graphics/java/android/graphics/LegacyFontListParser.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.graphics;
+
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parses an XML font config. Example:
+ *
+ *<familyset>
+ *
+ * <family>
+ * <nameset>
+ * <name>sans-serif</name>
+ * <name>arial</name>
+ * </nameset>
+ * <fileset>
+ * <file>Roboto-Regular.ttf</file>
+ * <file>Roboto-Bold.ttf</file>
+ * <file>Roboto-Italic.ttf</file>
+ * <file>Roboto-BoldItalic.ttf</file>
+ * </fileset>
+ * </family>
+ * <family>
+ * ...
+ * </family>
+ *</familyset>
+ * @hide
+ */
+public class LegacyFontListParser {
+ public static class Family {
+ public List<String> nameset = new ArrayList<String>();
+ public List<String> fileset = new ArrayList<String>();
+
+ public String getName() {
+ if (nameset != null && !nameset.isEmpty()) {
+ return nameset.get(0);
+ }
+ return null;
+ }
+ }
+
+ public static List<Family> parse(InputStream in)
+ throws XmlPullParserException, IOException {
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parser.nextTag();
+ return readFamilySet(parser);
+ } finally {
+ in.close();
+ }
+ }
+
+ private static List<Family> readFamilySet(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ List<Family> families = new ArrayList<Family>();
+ parser.require(XmlPullParser.START_TAG, null, "familyset");
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
+ }
+ String name = parser.getName();
+
+ // Starts by looking for the entry tag
+ if (name.equals("family")) {
+ Family family = readFamily(parser);
+ families.add(family);
+ }
+ }
+ return families;
+ }
+
+ private static Family readFamily(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ Family family = new Family();
+ parser.require(XmlPullParser.START_TAG, null, "family");
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
+ }
+ String name = parser.getName();
+ if (name.equals("nameset")) {
+ List<String> nameset = readNameset(parser);
+ family.nameset = nameset;
+ } else if (name.equals("fileset")) {
+ List<String> fileset = readFileset(parser);
+ family.fileset = fileset;
+ } else {
+ skip(parser);
+ }
+ }
+ return family;
+ }
+
+ private static List<String> readNameset(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ List<String> names = new ArrayList<String>();
+ parser.require(XmlPullParser.START_TAG, null, "nameset");
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
+ }
+ String tagname = parser.getName();
+ if (tagname.equals("name")) {
+ String name = readText(parser);
+ names.add(name);
+ } else {
+ skip(parser);
+ }
+ }
+ return names;
+ }
+
+ private static List<String> readFileset(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ List<String> files = new ArrayList<String>();
+ parser.require(XmlPullParser.START_TAG, null, "fileset");
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
+ }
+ String name = parser.getName();
+ if (name.equals("file")) {
+ String file = readText(parser);
+ files.add(file);
+ } else {
+ skip(parser);
+ }
+ }
+ return files;
+ }
+
+ // For the tags title and summary, extracts their text values.
+ private static String readText(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ String result = "";
+ if (parser.next() == XmlPullParser.TEXT) {
+ result = parser.getText();
+ parser.nextTag();
+ }
+ return result;
+ }
+
+ private static void skip(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ throw new IllegalStateException();
+ }
+ int depth = 1;
+ while (depth != 0) {
+ switch (parser.next()) {
+ case XmlPullParser.END_TAG:
+ depth--;
+ break;
+ case XmlPullParser.START_TAG:
+ depth++;
+ break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index db42314..6aba87b 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,7 +25,6 @@ import android.util.SparseArray;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
@@ -68,6 +67,8 @@ public class Typeface {
static final String FONTS_CONFIG = "fonts.xml";
+ static final String SANS_SERIF_FAMILY_NAME = "sans-serif";
+
/**
* @hide
*/
@@ -81,6 +82,13 @@ public class Typeface {
private int mStyle = 0;
+ // Typefaces that we can garbage collect when changing fonts, and so we don't break public APIs
+ private static Typeface DEFAULT_INTERNAL;
+ private static Typeface DEFAULT_BOLD_INTERNAL;
+ private static Typeface SANS_SERIF_INTERNAL;
+ private static Typeface SERIF_INTERNAL;
+ private static Typeface MONOSPACE_INTERNAL;
+
private static void setDefault(Typeface t) {
sDefaultTypeface = t;
nativeSetDefault(t.native_instance);
@@ -228,7 +236,10 @@ public class Typeface {
for (int i = 0; i < families.length; i++) {
ptrArray[i] = families[i].mNativePtr;
}
- return new Typeface(nativeCreateFromArray(ptrArray));
+
+
+ Typeface typeface = new Typeface(nativeCreateFromArray(ptrArray));
+ return typeface;
}
/**
@@ -267,18 +278,111 @@ public class Typeface {
return fontFamily;
}
+ /**
+ * Adds the family from src with the name familyName as a fallback font in dst
+ * @param src Source font config
+ * @param dst Destination font config
+ * @param familyName Name of family to add as a fallback
+ */
+ private static void addFallbackFontsForFamilyName(FontListParser.Config src,
+ FontListParser.Config dst, String familyName) {
+ for (Family srcFamily : src.families) {
+ if (familyName.equals(srcFamily.name)) {
+ // set the name to null so that it will be added as a fallback
+ srcFamily.name = null;
+ dst.families.add(srcFamily);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Adds any font families in src that do not exist in dst
+ * @param src Source font config
+ * @param dst Destination font config
+ */
+ private static void addMissingFontFamilies(FontListParser.Config src,
+ FontListParser.Config dst) {
+ final int N = dst.families.size();
+ // add missing families
+ for (Family srcFamily : src.families) {
+ boolean addFamily = true;
+ for (int i = 0; i < N && addFamily; i++) {
+ final Family dstFamily = dst.families.get(i);
+ final String dstFamilyName = dstFamily.name;
+ if (dstFamilyName != null && dstFamilyName.equals(srcFamily.name)) {
+ addFamily = false;
+ break;
+ }
+ }
+ if (addFamily) {
+ dst.families.add(srcFamily);
+ }
+ }
+ }
+
+ /**
+ * Adds any aliases in src that do not exist in dst
+ * @param src Source font config
+ * @param dst Destination font config
+ */
+ private static void addMissingFontAliases(FontListParser.Config src,
+ FontListParser.Config dst) {
+ final int N = dst.aliases.size();
+ // add missing aliases
+ for (FontListParser.Alias alias : src.aliases) {
+ boolean addAlias = true;
+ for (int i = 0; i < N && addAlias; i++) {
+ final String dstAliasName = dst.aliases.get(i).name;
+ if (dstAliasName != null && dstAliasName.equals(alias.name)) {
+ addAlias = false;
+ break;
+ }
+ }
+ if (addAlias) {
+ dst.aliases.add(alias);
+ }
+ }
+ }
+
/*
* (non-Javadoc)
*
* This should only be called once, from the static class initializer block.
*/
- private static void init() {
+ private static void init(boolean forceSystemFonts) {
// Load font config and initialize Minikin state
File systemFontConfigLocation = getSystemFontConfigLocation();
- File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
+ File themeFontConfigLocation = getThemeFontConfigLocation();
+
+ File systemConfigFile = new File(systemFontConfigLocation, FONTS_CONFIG);
+ File themeConfigFile = new File(themeFontConfigLocation, FONTS_CONFIG);
+ File configFile = null;
+ File fontDir;
+
+ if (!forceSystemFonts && themeConfigFile.exists()) {
+ configFile = themeConfigFile;
+ fontDir = getThemeFontDirLocation();
+ } else {
+ configFile = systemConfigFile;
+ fontDir = getSystemFontDirLocation();
+ }
+
try {
- FileInputStream fontsIn = new FileInputStream(configFilename);
- FontListParser.Config fontConfig = FontListParser.parse(fontsIn);
+ FontListParser.Config fontConfig = FontListParser.parse(configFile,
+ fontDir.getAbsolutePath());
+ FontListParser.Config systemFontConfig = null;
+
+ // If the fonts are coming from a theme, we will need to make sure that we include
+ // any font families from the system fonts that the theme did not include.
+ // NOTE: All the system font families without names ALWAYS get added.
+ if (configFile == themeConfigFile) {
+ systemFontConfig = FontListParser.parse(systemConfigFile,
+ getSystemFontDirLocation().getAbsolutePath());
+ addFallbackFontsForFamilyName(systemFontConfig, fontConfig, SANS_SERIF_FAMILY_NAME);
+ addMissingFontFamilies(systemFontConfig, fontConfig);
+ addMissingFontAliases(systemFontConfig, fontConfig);
+ }
List<FontFamily> familyList = new ArrayList<FontFamily>();
// Note that the default typeface is always present in the fallback list;
@@ -289,6 +393,7 @@ public class Typeface {
familyList.add(makeFamilyFromParsed(f));
}
}
+
sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
setDefault(Typeface.createFromFamilies(sFallbackFonts));
@@ -324,22 +429,58 @@ public class Typeface {
Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
// TODO: normal in non-Minikin case, remove or make error when Minikin-only
} catch (FileNotFoundException e) {
- Log.e(TAG, "Error opening " + configFilename);
+ Log.e(TAG, "Error opening " + configFile, e);
} catch (IOException e) {
- Log.e(TAG, "Error reading " + configFilename);
+ Log.e(TAG, "Error reading " + configFile, e);
} catch (XmlPullParserException e) {
- Log.e(TAG, "XML parse exception for " + configFilename);
+ Log.e(TAG, "XML parse exception for " + configFile, e);
}
}
+ /** @hide */
+ public static void recreateDefaults() {
+ recreateDefaults(false);
+ }
+
+ /**
+ * Clears caches in java and skia.
+ * Skia will then reparse font config
+ * @hide
+ */
+ public static void recreateDefaults(boolean forceSystemFonts) {
+ sTypefaceCache.clear();
+ sSystemFontMap.clear();
+ init(forceSystemFonts);
+
+ DEFAULT_INTERNAL = create((String) null, 0);
+ DEFAULT_BOLD_INTERNAL = create((String) null, Typeface.BOLD);
+ SANS_SERIF_INTERNAL = create("sans-serif", 0);
+ SERIF_INTERNAL = create("serif", 0);
+ MONOSPACE_INTERNAL = create("monospace", 0);
+
+ DEFAULT.native_instance = DEFAULT_INTERNAL.native_instance;
+ DEFAULT_BOLD.native_instance = DEFAULT_BOLD_INTERNAL.native_instance;
+ SANS_SERIF.native_instance = SANS_SERIF_INTERNAL.native_instance;
+ SERIF.native_instance = SERIF_INTERNAL.native_instance;
+ MONOSPACE.native_instance = MONOSPACE_INTERNAL.native_instance;
+ sDefaults[2] = create((String) null, Typeface.ITALIC);
+ sDefaults[3] = create((String) null, Typeface.BOLD_ITALIC);
+ }
+
static {
- init();
+ init(false);
// Set up defaults and typefaces exposed in public API
- DEFAULT = create((String) null, 0);
- DEFAULT_BOLD = create((String) null, Typeface.BOLD);
- SANS_SERIF = create("sans-serif", 0);
- SERIF = create("serif", 0);
- MONOSPACE = create("monospace", 0);
+ DEFAULT_INTERNAL = create((String) null, 0);
+ DEFAULT_BOLD_INTERNAL = create((String) null, Typeface.BOLD);
+ SANS_SERIF_INTERNAL = create("sans-serif", 0);
+ SERIF_INTERNAL = create("serif", 0);
+ MONOSPACE_INTERNAL = create("monospace", 0);
+
+ DEFAULT = new Typeface(DEFAULT_INTERNAL.native_instance);
+ DEFAULT_BOLD = new Typeface(DEFAULT_BOLD_INTERNAL.native_instance);
+ SANS_SERIF = new Typeface(SANS_SERIF_INTERNAL.native_instance);
+ SERIF = new Typeface(SERIF_INTERNAL.native_instance);
+ MONOSPACE = new Typeface(MONOSPACE_INTERNAL.native_instance);
sDefaults = new Typeface[] {
DEFAULT,
@@ -354,6 +495,18 @@ public class Typeface {
return new File("/system/etc/");
}
+ private static File getSystemFontDirLocation() {
+ return new File("/system/fonts/");
+ }
+
+ private static File getThemeFontConfigLocation() {
+ return new File("/data/system/theme/fonts/");
+ }
+
+ private static File getThemeFontDirLocation() {
+ return new File("/data/system/theme/fonts/");
+ }
+
@Override
protected void finalize() throws Throwable {
try {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 32af59a..3f1f76a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1076,7 +1076,7 @@ public abstract class Drawable {
// drawn to the screen.
if (opts == null) opts = new BitmapFactory.Options();
opts.inScreenDensity = res != null
- ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
+ ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEFAULT;
Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
if (bm != null) {
byte[] np = bm.getNinePatchChunk();
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 1cfccc4..6d3bf3e 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -32,6 +32,7 @@ import android.graphics.PathMeasure;
import android.graphics.PixelFormat;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.PorterDuff.Mode;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -225,9 +226,9 @@ public class VectorDrawable extends Drawable {
private Insets mDpiScaleInsets = Insets.NONE;
// Temp variable, only for saving "new" operation at the draw() time.
- private final float[] mTmpFloats = new float[9];
private final Matrix mTmpMatrix = new Matrix();
private final Rect mTmpBounds = new Rect();
+ private final RectF mTmpDstBounds = new RectF();
public VectorDrawable() {
this(null, null);
@@ -288,11 +289,10 @@ public class VectorDrawable extends Drawable {
// size first. This bitmap size is determined by the bounds and the
// canvas scale.
canvas.getMatrix(mTmpMatrix);
- mTmpMatrix.getValues(mTmpFloats);
- float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
- float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
- int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
- int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
+ mTmpDstBounds.set(mTmpBounds);
+ mTmpMatrix.mapRect(mTmpDstBounds);
+ int scaledWidth = (int) mTmpDstBounds.width();
+ int scaledHeight = (int) mTmpDstBounds.height();
scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);
diff --git a/graphics/tests/localtests/Android.mk b/graphics/tests/localtests/Android.mk
new file mode 100644
index 0000000..0b95ecd
--- /dev/null
+++ b/graphics/tests/localtests/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := FrameworksGraphicsHostTests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+#LOCAL_PACKAGE_NAME := FrameworksGraphicsTests
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#####################################
+
+
diff --git a/graphics/tests/localtests/src/android/graphics/FontListConverterTest.java b/graphics/tests/localtests/src/android/graphics/FontListConverterTest.java
new file mode 100644
index 0000000..60c9053
--- /dev/null
+++ b/graphics/tests/localtests/src/android/graphics/FontListConverterTest.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.graphics;
+
+import android.graphics.FontListParser.Alias;
+import android.graphics.LegacyFontListParser.Family;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class FontListConverterTest extends TestCase {
+ // VALID nameset includes the default name first and
+ // and some other 'aliases' with it.
+ private static final String[] VALID_NAMESET = {
+ "sans-serif",
+ "arial",
+ "helvetica",
+ "tahoma",
+ "verdana"
+ };
+
+ // The correct fileset will have 4 files in
+ // order by type (regular, bold, italic, bolditalic)
+ private static final String[] VALID_FILESET = {
+ "Roboto-Regular.ttf",
+ "Roboto-Bold.ttf",
+ "Roboto-Italic.ttf",
+ "Roboto-BoldItalic.ttf"
+ };
+
+ // The legacy fontlist format considered thin, light, and black styles
+ // each as part of their own familysets. The new format does not, so we need
+ // to provide a test case to adapt this. Note: "condensed" is still considered
+ // to be its own familyset. So we must be careful
+ private static final String[] VALID_ADDITIONAL_STYLE_NAMESET = {
+ "sans-serif-thin"
+ };
+
+ private static final String[] VALID_ADDITIONAL_STYLE_FILESET = {
+ "Roboto-Thin.ttf",
+ "Roboto-ThinItalic.ttf"
+ };
+
+ // thin, light, and black styles are part of the same family but a Roboto "condensed"
+ // or Roboto "slab" would be considered part of a different family. Since the legacy
+ // format would already consider these as a different family, we just have to make sure
+ // they don't get brought back into a common family like thin/light/black
+ private static final String[] VALID_RELATED_FAMILY_NAMESET = {
+ "sans-serif-condensed"
+ };
+
+ private static final String[] VALID_RELATED_FAMILY_FILESET = {
+ "RobotoCondensed-Regular.ttf",
+ "RobotoCondensed-Bold.ttf",
+ "RobotoCondensed-Italic.ttf",
+ "RobotoCondensed-BoldItalic.ttf"
+ };
+
+ // Some typefaces will only have one style.
+ private static final String[] VALID_SINGLE_STYLE_FAMIlY_NAMESET = {
+ "monospace"
+ };
+ private static final String[] VALID_SINGLE_STYLE_FAMIlY_FILESET = {
+ "DroidSansMono.ttf"
+ };
+
+ final String VALID_PATH = "/valid/path/";
+
+ private Family sValidFamily; // eg "sans-serif"
+ private Family sValidAdditionalStyleFamily; // eg "sans-serif-light"
+ private Family sValidRelatedFamily; // eg "sans-serif-condensed"
+ private Family mValidSingleStyleFamily; // eg "monospace" which only uses DroidSansMono.ttf
+
+ protected void setUp() {
+ sValidFamily = new Family();
+ sValidFamily.nameset = new ArrayList<String>(Arrays.asList(VALID_NAMESET));
+ sValidFamily.fileset = new ArrayList<String>(Arrays.asList(VALID_FILESET));
+
+ sValidAdditionalStyleFamily = new Family();
+ sValidAdditionalStyleFamily.nameset =
+ new ArrayList<String>(Arrays.asList(VALID_ADDITIONAL_STYLE_NAMESET));
+ sValidAdditionalStyleFamily.fileset =
+ new ArrayList<String>(Arrays.asList(VALID_ADDITIONAL_STYLE_FILESET));
+
+ sValidRelatedFamily = new Family();
+ sValidRelatedFamily.nameset =
+ new ArrayList<String>(Arrays.asList(VALID_RELATED_FAMILY_NAMESET));
+ sValidRelatedFamily.fileset =
+ new ArrayList<String>(Arrays.asList(VALID_RELATED_FAMILY_FILESET));
+
+ mValidSingleStyleFamily = new Family();
+ }
+
+ @SmallTest
+ public void testValidAdaptedFamilyShouldHaveNameOfNamesetsFirstElement() {
+ FontListConverter adapter = new FontListConverter(sValidFamily, VALID_PATH);
+ FontListParser.Family convertedFamily = adapter.convertFamily(sValidFamily);
+ assertEquals(VALID_NAMESET[0], convertedFamily.name);
+ }
+
+ @SmallTest
+ public void testValidAdaptedFamilyShouldHaveFonts() {
+ FontListConverter adapter = new FontListConverter(sValidFamily, VALID_PATH);
+ FontListParser.Family convertedFamily = adapter.convertFamily(sValidFamily);
+ List<FontListParser.Font> fonts = convertedFamily.fonts;
+ assertEquals(VALID_FILESET.length, fonts.size());
+ }
+
+ @SmallTest
+ public void testValidAdaptedFontsShouldHaveCorrectProperties() {
+ FontListConverter adapter = new FontListConverter(sValidFamily, VALID_PATH);
+ List<FontListParser.Font> fonts = adapter.convertFonts(Arrays.asList(VALID_FILESET));
+
+ assertEquals(VALID_FILESET.length, fonts.size());
+ for(int i=0; i < fonts.size(); i++) {
+ FontListParser.Font font = fonts.get(i);
+ assertEquals(VALID_PATH + VALID_FILESET[i], font.fontName);
+ assertEquals("shouldBeItalic", shouldBeItalic(i), font.isItalic);
+ assertEquals(FontListConverter.WEIGHTS[i], font.weight);
+ }
+ }
+
+ @SmallTest
+ public void testExtraNamesetsShouldConvertToAliases() {
+ List<Family> families = new ArrayList<Family>();
+ families.add(sValidFamily);
+
+ FontListConverter adapter = new FontListConverter(sValidFamily, VALID_PATH);
+ List<FontListParser.Alias> aliases = adapter.createAliases();
+
+ // Be sure the aliases point to the first name in the nameset
+ for(int i = 0; i < aliases.size(); i++) {
+ FontListParser.Alias alias = aliases.get(i);
+ assertEquals(VALID_NAMESET[0], alias.toName);
+ }
+
+ // Be sure the extra namesets are in the alias list
+ for(int i = 1; i < VALID_NAMESET.length; i++) {
+ assertTrue("hasAliasWithName", hasAliasWithName(aliases, VALID_NAMESET[i]));
+ }
+ }
+
+ /**
+ * The legacy format treats thin, light, and black fonts to be different families
+ * The new format treats these as all part of the original
+ * eg sans-serif and sans-serif-thin become one family
+ */
+ @SmallTest
+ public void testAdditionalStylesShouldConvertToSameFamily() {
+ List<Family> families = new ArrayList<Family>();
+ families.add(sValidFamily); //eg "sans-serif"
+ families.add(sValidAdditionalStyleFamily); //eg "sans-serif-light"
+
+ FontListConverter adapter = new FontListConverter(families, VALID_PATH);
+ List<FontListParser.Family> convertedFamilies = adapter.convertFamilies();
+
+ // We started with two similiar families, and now should have one
+ assertEquals(1, convertedFamilies.size());
+
+ // The name of the family should be the base name, no style modifiers
+ // ie "sans-serif" not "sans-serif-light"
+ FontListParser.Family convertedFamily = convertedFamilies.get(0);
+ assertEquals(sValidFamily.nameset.get(0), convertedFamily.name);
+
+ // Verify all the fonts from both families exist now in the converted Family
+ List<String> combinedFileSet = new ArrayList<String>();
+ combinedFileSet.addAll(sValidFamily.fileset);
+ combinedFileSet.addAll(sValidAdditionalStyleFamily.fileset);
+ for(String filename : combinedFileSet) {
+ String fontName = VALID_PATH + filename;
+ assertTrue("hasFontWithName", hasFontWithName(convertedFamily, fontName));
+ }
+ }
+
+ /**
+ * When two families combine, the "varied" family (ie light, light, black) should
+ * have their namesets converted to aliases.
+ * IE sans-serif-light should point to sans-serif because the light family
+ * gets merged to sans-serif
+ */
+ @SmallTest
+ public void testAdditionalStylesNamesShouldBecomeAliases() {
+ List<Family> families = new ArrayList<Family>();
+ families.add(sValidFamily); //eg "sans-serif"
+ families.add(sValidAdditionalStyleFamily); //eg "sans-serif-light"
+
+ FontListConverter adapter = new FontListConverter(families, VALID_PATH);
+ List<Alias> aliases = adapter.createAliases();
+
+ // Subtract 1 from the total length since VALID_NAMESET[0] will be the family name
+ int expectedSize = VALID_NAMESET.length + VALID_ADDITIONAL_STYLE_NAMESET.length - 1;
+ assertEquals(expectedSize, aliases.size());
+
+ // All aliases should point at the base family
+ for(Alias alias : aliases) {
+ assertEquals(VALID_NAMESET[0], alias.toName);
+ }
+
+ // There should be an alias for every name in the merged in family
+ for(String name : VALID_ADDITIONAL_STYLE_NAMESET) {
+ assertTrue("hasAliasWithName", hasAliasWithName(aliases, name));
+ }
+ }
+
+ /**
+ * sans-serif-condensed should not get merged in with sans-serif
+ */
+ @SmallTest
+ public void testSimiliarFontsShouldKeepSameFamily() {
+ List<Family> families = new ArrayList<Family>();
+ families.add(sValidFamily); //eg "sans-serif"
+ families.add(sValidRelatedFamily); //eg "sans-serif-condensed"
+
+ FontListConverter adapter = new FontListConverter(families, VALID_PATH);
+ List<FontListParser.Family> convertedFamilies = adapter.convertFamilies();
+ FontListParser.Family convertedValidFamily =
+ getFontListFamilyWithName(convertedFamilies, VALID_NAMESET[0]);
+ FontListParser.Family convertedRelatedFamily =
+ getFontListFamilyWithName(convertedFamilies, VALID_RELATED_FAMILY_NAMESET[0]);
+
+
+ // Valid family should only have its own fonts. Will fail if these were merged
+ for(String filename : sValidFamily.fileset) {
+ String fontName = VALID_PATH + filename;
+ assertTrue("hasFontWithName", hasFontWithName(convertedValidFamily, fontName));
+ assertFalse("hasFontWIthName", hasFontWithName(convertedRelatedFamily, fontName));
+ }
+
+ // Related family should also only have have its own fonts. Will fail if these were merged
+ for(String filename : sValidRelatedFamily.fileset) {
+ String fontName = VALID_PATH + filename;
+ assertTrue("hasFontWithName", hasFontWithName(convertedRelatedFamily, fontName));
+ assertFalse("hasFontWIthName", hasFontWithName(convertedValidFamily, fontName));
+ }
+ }
+
+ private static boolean hasAliasWithName(List<Alias> aliases, String name) {
+ for (Alias alias : aliases) if (name.equals(alias.name)) return true;
+ return false;
+ }
+
+ private static boolean hasFontWithName(FontListParser.Family family, String name) {
+ for (FontListParser.Font font : family.fonts) {
+ if(font.fontName != null && font.fontName.equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static FontListParser.Family getFontListFamilyWithName(
+ List<FontListParser.Family> families, String name) {
+ for(FontListParser.Family family : families) {
+ if (name.equals(family.name)) return family;
+ }
+ return null;
+ }
+
+ private boolean shouldBeItalic(int index) {
+ // Since the fileset format is regular, bold, italic, bolditalic, anything >= 2 is italic
+ return index >= 2;
+ }
+}
diff --git a/graphics/tests/localtests/src/android/graphics/TypefaceTestSuite.java b/graphics/tests/localtests/src/android/graphics/TypefaceTestSuite.java
new file mode 100644
index 0000000..9ef8421
--- /dev/null
+++ b/graphics/tests/localtests/src/android/graphics/TypefaceTestSuite.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import junit.framework.TestSuite;
+
+public class TypefaceTestSuite {
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite(TypefaceTestSuite.class.getName());
+ suite.addTestSuite(FontListConverterTest.class);
+ return suite;
+ }
+}
diff --git a/include/SeempLog.h b/include/SeempLog.h
new file mode 100644
index 0000000..30ae338
--- /dev/null
+++ b/include/SeempLog.h
@@ -0,0 +1,51 @@
+/*
+
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <dlfcn.h>
+
+#define SEEMPLOG_RECORD(api, params) \
+ static bool shouldTryLoad = true; \
+ static void (*seemp_log_record_func)(int type, const char* msg) = NULL; \
+ \
+ if (shouldTryLoad) { \
+ shouldTryLoad = false; \
+ void* libhandle = dlopen("libSeemplog.so", RTLD_NOW); \
+ if (libhandle != NULL) { \
+ *(void**)(&seemp_log_record_func) = \
+ dlsym(libhandle, "seemp_log_record"); \
+ } \
+ } \
+ if (seemp_log_record_func) \
+ seemp_log_record_func(api, params);
+
+
+
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index 0cfd2b1..de10600 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -75,6 +75,7 @@ public:
static const char* TARGET_PACKAGE_NAME;
static const char* TARGET_APK_PATH;
static const char* IDMAP_DIR;
+ static const char* APK_EXTENSION;
typedef enum CacheMode {
CACHE_UNKNOWN = 0,
@@ -100,7 +101,14 @@ public:
* newly-added asset source.
*/
bool addAssetPath(const String8& path, int32_t* cookie);
- bool addOverlayPath(const String8& path, int32_t* cookie);
+ bool addOverlayPath(const String8& idmapPath, const String8& overlayApkpath, int32_t* cookie,
+ const String8& resApkPath, const String8& targetPkgPath,
+ const String8& prefixPath);
+ bool addCommonOverlayPath(const String8& path, int32_t* cookie,
+ const String8& resApkPath, const String8& prefixPath);
+ bool addIconPath(const String8& path, int32_t* cookie,
+ const String8& resApkPath, const String8& prefixPath, uint32_t pkgIdOverride);
+ bool removeOverlayPath(const String8& path, int32_t cookie);
/*
* Convenience for adding the standard system assets. Uses the
@@ -230,22 +238,33 @@ public:
* Generate idmap data to translate resources IDs between a package and a
* corresponding overlay package.
*/
- bool createIdmap(const char* targetApkPath, const char* overlayApkPath,
- uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize);
+ bool createIdmap(const char* targetApkPath, const char* overlayApkPath, const char* cache_path,
+ uint32_t targetCrc, uint32_t overlayCrc,
+ time_t targetMtime, time_t overlayMtime,
+ uint32_t** outData, size_t* outSize);
+
+ String8 getBasePackageName(uint32_t index);
private:
struct asset_path
{
- asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemOverlay(false) {}
+ asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemOverlay(false),
+ pkgIdOverride(0) {}
String8 path;
FileType type;
String8 idmap;
bool isSystemOverlay;
+ String8 prefixPath;
+ String8 resfilePath;
+ String8 resApkPath;
+ uint32_t pkgIdOverride;
};
Asset* openInPathLocked(const char* fileName, AccessMode mode,
const asset_path& path);
Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode,
+ const asset_path& path, bool usePrefix = true);
+ Asset* openNonAssetInExactPathLocked(const char* fileName, AccessMode mode,
const asset_path& path);
Asset* openInLocaleVendorLocked(const char* fileName, AccessMode mode,
const asset_path& path, const char* locale, const char* vendor);
@@ -256,6 +275,7 @@ private:
const String8& dirName, const String8& fileName);
ZipFileRO* getZipFileLocked(const asset_path& path);
+ ZipFileRO* getZipFileLocked(const String8& path);
Asset* openAssetFromFileLocked(const String8& fileName, AccessMode mode);
Asset* openAssetFromZipLocked(const ZipFileRO* pZipFile,
const ZipEntryRO entry, AccessMode mode, const String8& entryName);
@@ -280,13 +300,17 @@ private:
const ResTable* getResTable(bool required = true) const;
void setLocaleLocked(const char* locale);
void updateResourceParamsLocked() const;
- bool appendPathToResTable(const asset_path& ap) const;
+ bool appendPathToResTable(const asset_path& ap, size_t* entryIdx) const;
Asset* openIdmapLocked(const struct asset_path& ap) const;
void addSystemOverlays(const char* pathOverlaysList, const String8& targetPackagePath,
ResTable* sharedRes, size_t offset) const;
+ String8 getPkgName(const char *apkPath);
+
+ String8 getOverlayResPath(const char* cachePath);
+
class SharedZip : public RefBase {
public:
static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true);
@@ -355,6 +379,8 @@ private:
void addOverlay(const String8& path, const asset_path& overlay);
bool getOverlay(const String8& path, size_t idx, asset_path* out) const;
+
+ void closeZip(const String8& zip);
private:
void closeZip(int idx);
@@ -376,6 +402,9 @@ private:
mutable ResTable* mResources;
ResTable_config* mConfig;
+ String8 mBasePackageName;
+ uint32_t mBasePackageIndex;
+
/*
* Cached data for "loose" files. This lets us avoid poking at the
* filesystem when searching for loose assets. Each entry is the
diff --git a/include/androidfw/AttributeFinder.h b/include/androidfw/AttributeFinder.h
index acf7056..be0f1bd 100644
--- a/include/androidfw/AttributeFinder.h
+++ b/include/androidfw/AttributeFinder.h
@@ -74,6 +74,7 @@ private:
// Package Offsets (best-case, fast look-up).
Iterator mFrameworkStart;
+ Iterator mCMFrameworkStart;
Iterator mAppStart;
// Worst case, we have shared-library resources.
@@ -99,6 +100,9 @@ void BackTrackingAttributeFinder<Derived, Iterator>::jumpToClosestAttribute(cons
case 0x01:
mCurrent = mFrameworkStart;
break;
+ case 0x3f:
+ mCurrent = mCMFrameworkStart;
+ break;
case 0x7f:
mCurrent = mAppStart;
break;
@@ -132,6 +136,9 @@ void BackTrackingAttributeFinder<Derived, Iterator>::markCurrentPackageId(const
case 0x01:
mFrameworkStart = mCurrent;
break;
+ case 0x3f:
+ mCMFrameworkStart = mCurrent;
+ break;
case 0x7f:
mAppStart = mCurrent;
break;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 5130e6c..ae955c6 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1547,10 +1547,11 @@ public:
status_t add(const void* data, size_t size, const int32_t cookie=-1, bool copyData=false);
status_t add(const void* data, size_t size, const void* idmapData, size_t idmapDataSize,
- const int32_t cookie=-1, bool copyData=false);
+ const int32_t cookie=-1, bool copyData=false, const uint32_t pkgIdOverride=0);
status_t add(Asset* asset, const int32_t cookie=-1, bool copyData=false);
- status_t add(Asset* asset, Asset* idmapAsset, const int32_t cookie=-1, bool copyData=false);
+ status_t add(Asset* asset, Asset* idmapAsset, const int32_t cookie=-1, bool copyData=false,
+ const uint32_t pkgIdOverride=0);
status_t add(ResTable* src);
status_t addEmpty(const int32_t cookie);
@@ -1637,7 +1638,7 @@ public:
void lock() const;
ssize_t getBagLocked(uint32_t resID, const bag_entry** outBag,
- uint32_t* outTypeSpecFlags=NULL) const;
+ uint32_t* outTypeSpecFlags=NULL, bool performMapping=true) const;
void unlock() const;
@@ -1830,10 +1831,11 @@ public:
// NO_ERROR; the caller should not free outData.
status_t createIdmap(const ResTable& overlay,
uint32_t targetCrc, uint32_t overlayCrc,
+ time_t targetMtime, time_t overlayMtime,
const char* targetPath, const char* overlayPath,
void** outData, size_t* outSize) const;
- static const size_t IDMAP_HEADER_SIZE_BYTES = 4 * sizeof(uint32_t) + 2 * 256;
+ static const size_t IDMAP_HEADER_SIZE_BYTES = 6 * sizeof(uint32_t) + 2 * 256;
// Retrieve idmap meta-data.
//
@@ -1844,6 +1846,8 @@ public:
uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
String8* pTargetPath, String8* pOverlayPath);
+ void removeAssetsByCookie(const String8 &packageName, int32_t cookie);
+
void print(bool inclValues) const;
static String8 normalizeForOutput(const char* input);
@@ -1857,20 +1861,26 @@ private:
typedef Vector<Type*> TypeList;
status_t addInternal(const void* data, size_t size, const void* idmapData, size_t idmapDataSize,
- const int32_t cookie, bool copyData);
+ const int32_t cookie, bool copyData, const uint32_t pkgIdOverride);
ssize_t getResourcePackageIndex(uint32_t resID) const;
status_t getEntry(
const PackageGroup* packageGroup, int typeIndex, int entryIndex,
const ResTable_config* config,
- Entry* outEntry) const;
+ Entry* outEntry, const bool performMapping=true) const;
uint32_t findEntry(const PackageGroup* group, ssize_t typeIndex, const char16_t* name,
size_t nameLen, uint32_t* outTypeSpecFlags) const;
status_t parsePackage(
- const ResTable_package* const pkg, const Header* const header);
+ const ResTable_package* const pkg, const Header* const header,
+ const uint32_t pkgIdOverride);
+
+ bool isResTypeAllowed(const char* type) const;
+ bool isDynamicPackageId(const uint32_t pkgId) const;
+ bool isProtectedAttr(uint32_t resID) const;
+ status_t removeIdmappedTypesFromPackageGroup(PackageGroup* packageGroup) const;
void print_value(const Package* pkg, const Res_value& value) const;
diff --git a/include/private/time_genoff.h b/include/private/time_genoff.h
new file mode 100644
index 0000000..4df5680
--- /dev/null
+++ b/include/private/time_genoff.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TIME_GENOFF_H__
+#define __TIME_GENOFF_H__
+
+/*
+ * Time genoff base -- To be used by the time setter
+ * Reserved bases to be supported later.
+ */
+typedef enum time_bases {
+ ATS_RTC = 0,
+ ATS_TOD,
+ ATS_USER,
+ ATS_SECURE,
+ ATS_RESERVED_1,
+ ATS_RESERVED_2,
+ ATS_RESERVED_3,
+ ATS_GPS,
+ ATS_1X,
+ ATS_RESERVED_4,
+ ATS_WCDMA,
+ ATS_SNTP,
+ ATS_UTC,
+ ATS_MFLO,
+ ATS_INVALID
+} time_bases_type;
+
+/* Time unit -- Unit in which time is set/get */
+typedef enum time_unit {
+ TIME_STAMP, /* Not supported */
+ TIME_MSEC,
+ TIME_SECS,
+ TIME_JULIAN,
+ TIME_20MS_FRAME, /* Not supported */
+ TIME_INVALID
+} time_unit_type;
+
+/* Operation to be done */
+typedef enum time_genoff_opr {
+ T_SET,
+ T_GET,
+ T_MAX
+} time_genoff_opr_type;
+
+/* Structure to be passed as argument to time_genoff_operation() */
+/*
+ * In set/get: ts_val should be assigned memory and then passed.
+ * if time_unit = TIME_MSEC, TIME_SECS then ts_val = (uint64_t *)
+ * if time_unit = TIME_JULIAN then ts_val = (struct tm *)
+ */
+typedef struct time_genoff_info {
+ time_bases_type base; /* Genoff in consideration */
+ void *ts_val; /* Time to be set/get */
+ time_unit_type unit; /* Time unit */
+ time_genoff_opr_type operation; /* Time operation to be done */
+}time_genoff_info_type;
+
+/* API to be called for time get/set operation */
+int time_genoff_operation(time_genoff_info_type *pargs);
+
+#endif /* __TIME_GENOFF_H__ */
diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h
index c3d34d8..b04be8a 100644
--- a/include/storage/IMountService.h
+++ b/include/storage/IMountService.h
@@ -71,6 +71,7 @@ public:
virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
virtual int32_t decryptStorage(const String16& password) = 0;
virtual int32_t encryptStorage(const String16& password) = 0;
+ virtual int32_t encryptWipeStorage(const String16& password) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 2dc1c96..1add6c3 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,8 +76,13 @@ static const char* kDefaultVendor = "default";
static const char* kAssetsRoot = "assets";
static const char* kAppZipName = NULL; //"classes.jar";
static const char* kSystemAssets = "framework/framework-res.apk";
-static const char* kResourceCache = "resource-cache";
+static const char* kCMSDKAssets = "framework/org.cyanogenmod.platform-res.apk";
static const char* kAndroidManifest = "AndroidManifest.xml";
+static const int kComposedIconAsset = 128;
+
+#ifdef HAVE_ANDROID_OS
+static const char* kResourceCache = "resource-cache";
+#endif
static const char* kExcludeExtension = ".EXCLUDE";
@@ -90,35 +96,9 @@ const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
const char* AssetManager::TARGET_PACKAGE_NAME = "android";
const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
const char* AssetManager::IDMAP_DIR = "/data/resource-cache";
+const char* AssetManager::APK_EXTENSION = ".apk";
namespace {
- String8 idmapPathForPackagePath(const String8& pkgPath)
- {
- const char* root = getenv("ANDROID_DATA");
- LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
- String8 path(root);
- path.appendPath(kResourceCache);
-
- char buf[256]; // 256 chars should be enough for anyone...
- strncpy(buf, pkgPath.string(), 255);
- buf[255] = '\0';
- char* filename = buf;
- while (*filename && *filename == '/') {
- ++filename;
- }
- char* p = filename;
- while (*p) {
- if (*p == '/') {
- *p = '@';
- }
- ++p;
- }
- path.appendPath(filename);
- path.append("@idmap");
-
- return path;
- }
-
/*
* Like strdup(), but uses C++ "new" operator instead of malloc.
*/
@@ -152,7 +132,8 @@ int32_t AssetManager::getGlobalCount()
AssetManager::AssetManager(CacheMode cacheMode)
: mLocale(NULL), mVendor(NULL),
mResources(NULL), mConfig(new ResTable_config),
- mCacheMode(cacheMode), mCacheValid(false)
+ mBasePackageIndex(-1), mCacheMode(cacheMode),
+ mCacheValid(false)
{
int count = android_atomic_inc(&gCount) + 1;
if (kIsDebug) {
@@ -224,6 +205,11 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie)
mAssetPaths.add(ap);
+ if (mResources != NULL) {
+ size_t index = mAssetPaths.size() - 1;
+ appendPathToResTable(ap, &index);
+ }
+
// new paths are always added at the end
if (cookie) {
*cookie = static_cast<int32_t>(mAssetPaths.size());
@@ -237,19 +223,37 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie)
}
#endif
- if (mResources != NULL) {
- appendPathToResTable(ap);
- }
-
return true;
}
-bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
+/**
+ * packagePath: Path to the APK that contains our overlay
+ * cookie: Set by this method. The caller can use this cookie to refer to the asset path that has
+ * been added.
+ * resApkPath: Path to the overlay's processed and cached resources.
+ * targetPkgPath: Path to the APK we are trying to overlay
+ * prefixPath: This is the base path internal to the overlay APK.
+ * For example, if we have theme "com.redtheme.apk"
+ * with a launcher overlay then this theme will have a structure like this:
+ * assets/
+ * com.android.launcher/
+ * res/
+ * drawable/
+ * foo.png
+ * Our resources.arsc will reference foo.png's path as "res/drawable/foo.png"
+ * so we need "assets/com.android.launcher/" as a prefix
+ */
+bool AssetManager::addOverlayPath(const String8& idmapPath, const String8& overlayPackagePath,
+ int32_t* cookie, const String8& resApkPath, const String8& targetPkgPath,
+ const String8& prefixPath)
{
- const String8 idmapPath = idmapPathForPackagePath(packagePath);
-
AutoMutex _l(mLock);
+ ALOGV("overlayApkPath: %s, idmap Path: %s, resApkPath %s, targetPkgPath: %s",
+ overlayPackagePath.string(), idmapPath.string(),
+ resApkPath.string(),
+ targetPkgPath.string());
+
for (size_t i = 0; i < mAssetPaths.size(); ++i) {
if (mAssetPaths[i].idmap == idmapPath) {
*cookie = static_cast<int32_t>(i + 1);
@@ -273,9 +277,9 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
}
delete idmap;
- if (overlayPath != packagePath) {
+ if (overlayPath != overlayPackagePath) {
ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n",
- idmapPath.string(), packagePath.string(), overlayPath.string());
+ idmapPath.string(), overlayPackagePath.string(), overlayPath.string());
return false;
}
if (access(targetPath.string(), R_OK) != 0) {
@@ -295,32 +299,196 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
oap.path = overlayPath;
oap.type = ::getFileType(overlayPath.string());
oap.idmap = idmapPath;
+ oap.resApkPath = resApkPath;
#if 0
ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n",
targetPath.string(), overlayPath.string(), idmapPath.string());
#endif
+ oap.prefixPath = prefixPath; //ex: assets/com.foo.bar
mAssetPaths.add(oap);
*cookie = static_cast<int32_t>(mAssetPaths.size());
if (mResources != NULL) {
- appendPathToResTable(oap);
+ size_t index = mAssetPaths.size() - 1;
+ appendPathToResTable(oap, &index);
}
return true;
}
+bool AssetManager::addCommonOverlayPath(const String8& themePackagePath, int32_t* cookie,
+ const String8& resApkPath, const String8& prefixPath)
+{
+ AutoMutex _l(mLock);
+
+ ALOGV("themePackagePath: %s, resApkPath %s, prefixPath %s",
+ themePackagePath.string(), resApkPath.string(), prefixPath.string());
+
+ // Skip if we have it already.
+ for (size_t i = 0; i < mAssetPaths.size(); ++i) {
+ if (mAssetPaths[i].path == themePackagePath && mAssetPaths[i].resApkPath == resApkPath) {
+ *cookie = static_cast<int32_t>(i + 1);
+ return true;
+ }
+ }
+
+ if (access(themePackagePath.string(), R_OK) != 0) {
+ ALOGW("failed to access file %s: %s\n", themePackagePath.string(), strerror(errno));
+ return false;
+ }
+
+ if (access(resApkPath.string(), R_OK) != 0) {
+ ALOGW("failed to access file %s: %s\n", resApkPath.string(), strerror(errno));
+ return false;
+ }
+
+ asset_path oap;
+ oap.path = themePackagePath;
+ oap.type = ::getFileType(themePackagePath.string());
+ oap.resApkPath = resApkPath;
+ oap.prefixPath = prefixPath;
+ mAssetPaths.add(oap);
+ *cookie = static_cast<int32_t>(mAssetPaths.size());
+
+ if (mResources != NULL) {
+ size_t index = mAssetPaths.size() - 1;
+ appendPathToResTable(oap, &index);
+ }
+
+ return true;
+}
+
+/*
+ * packagePath: Path to the APK that contains our icon assets
+ * cookie: Set by this method. The caller can use this cookie to refer to the added asset path.
+ * resApkPath: Path to the icon APK's processed and cached resources.
+ * prefixPath: This is the base path internal to the icon APK.
+ For example, if we have theme "com.redtheme.apk"
+ * assets/
+ * icons/
+ * res/
+ * drawable/
+ * foo.png
+ * Our restable will reference foo.png's path as "res/drawable/foo.png"
+ * so we need "assets/com.android.launcher/" as a prefix
+ * pkgIdOverride: The package id we want to give. This will overridet the id in the res table.
+ * This is necessary for legacy icon packs because they are compiled with the
+ * standard 7F package id.
+*/
+bool AssetManager::addIconPath(const String8& packagePath, int32_t* cookie,
+ const String8& resApkPath, const String8& prefixPath,
+ uint32_t pkgIdOverride)
+{
+ AutoMutex _l(mLock);
+
+ ALOGV("package path: %s, resApkPath %s, prefixPath %s",
+ packagePath.string(),
+ resApkPath.string(), prefixPath.string());
+
+ // Skip if we have it already.
+ for (size_t i = 0; i < mAssetPaths.size(); i++) {
+ if (mAssetPaths[i].path == packagePath && mAssetPaths[i].resApkPath == resApkPath) {
+ *cookie = static_cast<int32_t>(i + 1);
+ return true;
+ }
+ }
+
+ asset_path oap;
+ oap.path = packagePath;
+ oap.type = ::getFileType(packagePath.string());
+ oap.resApkPath = resApkPath;
+ oap.prefixPath = prefixPath;
+ oap.pkgIdOverride = pkgIdOverride;
+ mAssetPaths.add(oap);
+ *cookie = static_cast<int32_t>(mAssetPaths.size());
+
+ if (mResources != NULL) {
+ size_t index = mAssetPaths.size() - 1;
+ appendPathToResTable(oap, &index);
+ }
+
+ return true;
+}
+
+String8 AssetManager::getPkgName(const char *apkPath) {
+ String8 pkgName;
+
+ asset_path ap;
+ ap.type = kFileTypeRegular;
+ ap.path = String8(apkPath);
+
+ ResXMLTree tree;
+
+ Asset* manifestAsset = openNonAssetInPathLocked(kAndroidManifest, Asset::ACCESS_BUFFER, ap);
+ tree.setTo(manifestAsset->getBuffer(true),
+ manifestAsset->getLength());
+ tree.restart();
+
+ size_t len;
+ ResXMLTree::event_code_t code;
+ while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code != ResXMLTree::START_TAG) {
+ continue;
+ }
+ String8 tag(tree.getElementName(&len));
+ if (tag != "manifest") break; //Manifest does not start with <manifest>
+ size_t len;
+ ssize_t idx = tree.indexOfAttribute(NULL, "package");
+ const char16_t* str = tree.getAttributeStringValue(idx, &len);
+ pkgName = (str ? String8(str, len) : String8());
+
+ }
+
+ manifestAsset->close();
+ return pkgName;
+ }
+
+/**
+ * Returns the base package name as defined in the AndroidManifest.xml
+ */
+String8 AssetManager::getBasePackageName(uint32_t index)
+{
+ if (index >= mAssetPaths.size()) return String8::empty();
+
+ if (mBasePackageName.isEmpty() || mBasePackageIndex != index) {
+ mBasePackageName = getPkgName(mAssetPaths[index].path.string());
+ mBasePackageIndex = index;
+ }
+ return mBasePackageName;
+}
+
+String8 AssetManager::getOverlayResPath(const char* cachePath)
+{
+ String8 resPath(cachePath);
+ resPath.append("/");
+ resPath.append("resources");
+ resPath.append(AssetManager::APK_EXTENSION);
+ return resPath;
+}
+
bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath,
- uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize)
+ const char *cache_path, uint32_t targetCrc, uint32_t overlayCrc,
+ time_t targetMtime, time_t overlayMtime,
+ uint32_t** outData, size_t* outSize)
{
AutoMutex _l(mLock);
const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
ResTable tables[2];
+ //Our overlay APK might use an external restable
+ String8 resPath = getOverlayResPath(cache_path);
+
for (int i = 0; i < 2; ++i) {
asset_path ap;
ap.type = kFileTypeRegular;
ap.path = paths[i];
- Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
+ Asset* ass;
+ if (i == 1 && access(resPath.string(), R_OK) != -1) {
+ ap.path = resPath;
+ ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
+ } else {
+ ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
+ }
if (ass == NULL) {
ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
return false;
@@ -328,7 +496,7 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk
tables[i].add(ass);
}
- return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
+ return tables[0].createIdmap(tables[1], targetCrc, overlayCrc, targetMtime, overlayMtime,
targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
}
@@ -340,7 +508,10 @@ bool AssetManager::addDefaultAssets()
String8 path(root);
path.appendPath(kSystemAssets);
- return addAssetPath(path, NULL);
+ String8 pathCM(root);
+ pathCM.appendPath(kCMSDKAssets);
+
+ return addAssetPath(path, NULL) & addAssetPath(pathCM, NULL);
}
int32_t AssetManager::nextAssetPath(const int32_t cookie) const
@@ -518,6 +689,10 @@ Asset* AssetManager::open(const char* fileName, AccessMode mode)
i--;
ALOGV("Looking for asset '%s' in '%s'\n",
assetName.string(), mAssetPaths.itemAt(i).path.string());
+
+ // Skip theme/icon attached assets
+ if (mAssetPaths.itemAt(i).prefixPath.length() > 0) continue;
+
Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i));
if (pAsset != NULL) {
return pAsset != kExcludedAsset ? pAsset : NULL;
@@ -551,6 +726,10 @@ Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode, int32_t
while (i > 0) {
i--;
ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string());
+
+ // Skip theme/icon attached assets
+ if (mAssetPaths.itemAt(i).prefixPath.length() > 0) continue;
+
Asset* pAsset = openNonAssetInPathLocked(
fileName, mode, mAssetPaths.itemAt(i));
if (pAsset != NULL) {
@@ -581,6 +760,16 @@ Asset* AssetManager::openNonAsset(const int32_t cookie, const char* fileName, Ac
if (pAsset != NULL) {
return pAsset != kExcludedAsset ? pAsset : NULL;
}
+ } else if ((size_t)cookie == kComposedIconAsset) {
+ asset_path ap;
+ String8 path(fileName);
+ ap.type = kFileTypeDirectory;
+ ap.path = path.getPathDir();
+ Asset* pAsset = openNonAssetInPathLocked(
+ path.getPathLeaf().string(), mode, ap);
+ if (pAsset != NULL) {
+ return pAsset;
+ }
}
return NULL;
@@ -610,7 +799,7 @@ FileType AssetManager::getFileType(const char* fileName)
return kFileTypeRegular;
}
-bool AssetManager::appendPathToResTable(const asset_path& ap) const {
+bool AssetManager::appendPathToResTable(const asset_path& ap, size_t* entryIdx) const {
// skip those ap's that correspond to system overlays
if (ap.isSystemOverlay) {
return true;
@@ -622,17 +811,20 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
bool onlyEmptyResources = true;
MY_TRACE_BEGIN(ap.path.string());
Asset* idmap = openIdmapLocked(ap);
- size_t nextEntryIdx = mResources->getTableCount();
ALOGV("Looking for resource asset in '%s'\n", ap.path.string());
- if (ap.type != kFileTypeDirectory) {
- if (nextEntryIdx == 0) {
+ if (!ap.resApkPath.isEmpty()) {
+ // Avoid using prefix path in this case since the compiled resApk will simply have resources.arsc in it
+ ass = const_cast<AssetManager*>(this)->openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap, false);
+ shared = false;
+ } else if (ap.type != kFileTypeDirectory) {
+ if (*entryIdx == 0) {
// The first item is typically the framework resources,
// which we want to avoid parsing every time.
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.getZipResourceTable(ap.path);
if (sharedRes != NULL) {
// skip ahead the number of system overlay packages preloaded
- nextEntryIdx = sharedRes->getTableCount();
+ *entryIdx += sharedRes->getTableCount() - 1;
}
}
if (sharedRes == NULL) {
@@ -650,20 +842,20 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
}
}
- if (nextEntryIdx == 0 && ass != NULL) {
+ if (*entryIdx == 0 && ass != NULL) {
// If this is the first resource table in the asset
// manager, then we are going to cache it so that we
// can quickly copy it out for others.
ALOGV("Creating shared resources for %s", ap.path.string());
sharedRes = new ResTable();
- sharedRes->add(ass, idmap, nextEntryIdx + 1, false);
+ sharedRes->add(ass, idmap, *entryIdx + 1, false, ap.pkgIdOverride);
#ifdef HAVE_ANDROID_OS
const char* data = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
String8 overlaysListPath(data);
overlaysListPath.appendPath(kResourceCache);
overlaysListPath.appendPath("overlays.list");
- addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, nextEntryIdx);
+ addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, *entryIdx);
#endif
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.setZipResourceTable(ap.path, sharedRes);
@@ -685,7 +877,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
mResources->add(sharedRes);
} else {
ALOGV("Parsing resources for %s", ap.path.string());
- mResources->add(ass, idmap, nextEntryIdx + 1, !shared);
+ mResources->add(ass, idmap, *entryIdx + 1, !shared, ap.pkgIdOverride);
}
onlyEmptyResources = false;
@@ -694,7 +886,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
}
} else {
ALOGV("Installing empty resources in to table %p\n", mResources);
- mResources->addEmpty(nextEntryIdx + 1);
+ mResources->addEmpty(*entryIdx + 1);
}
if (idmap != NULL) {
@@ -734,7 +926,7 @@ const ResTable* AssetManager::getResTable(bool required) const
bool onlyEmptyResources = true;
const size_t N = mAssetPaths.size();
for (size_t i=0; i<N; i++) {
- bool empty = appendPathToResTable(mAssetPaths.itemAt(i));
+ bool empty = appendPathToResTable(mAssetPaths.itemAt(i), &i);
onlyEmptyResources = onlyEmptyResources && empty;
}
@@ -811,7 +1003,7 @@ void AssetManager::addSystemOverlays(const char* pathOverlaysList,
if (oass != NULL) {
Asset* oidmap = openIdmapLocked(oap);
offset++;
- sharedRes->add(oass, oidmap, offset + 1, false);
+ sharedRes->add(oass, oidmap, offset + 1, false, oap.pkgIdOverride);
const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
}
@@ -819,6 +1011,32 @@ void AssetManager::addSystemOverlays(const char* pathOverlaysList,
fclose(fin);
}
+bool AssetManager::removeOverlayPath(const String8& packageName, int32_t cookie)
+{
+ AutoMutex _l(mLock);
+
+ const size_t which = ((size_t)cookie)-1;
+ if (which >= mAssetPaths.size()) {
+ ALOGE("cookie was larger than paths size");
+ return false;
+ }
+
+ const asset_path& oap = mAssetPaths.itemAt(which);
+ mZipSet.closeZip(oap.resApkPath);
+
+ mAssetPaths.removeAt(which);
+
+ ResTable* rt = mResources;
+ if (rt == NULL) {
+ ALOGE("Unable to remove overlayPath, ResTable must not be NULL");
+ return false;
+ }
+
+ rt->removeAssetsByCookie(packageName, cookie);
+
+ return true;
+}
+
const ResTable& AssetManager::getResources(bool required) const
{
const ResTable* rt = getResTable(required);
@@ -853,18 +1071,28 @@ void AssetManager::getLocales(Vector<String8>* locales) const
* Open a non-asset file as if it were an asset, searching for it in the
* specified app.
*
+ *
* Pass in a NULL values for "appName" if the common app directory should
* be used.
*/
Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode mode,
- const asset_path& ap)
+ const asset_path& ap, bool usePrefix)
{
Asset* pAsset = NULL;
+ // Append asset_path prefix if needed
+ const char* fileNameFinal = fileName;
+ String8 fileNameWithPrefix;
+ if (usePrefix && ap.prefixPath.length() > 0) {
+ fileNameWithPrefix.append(ap.prefixPath);
+ fileNameWithPrefix.append(fileName);
+ fileNameFinal = fileNameWithPrefix.string();
+ }
+
/* look at the filesystem on disk */
if (ap.type == kFileTypeDirectory) {
String8 path(ap.path);
- path.appendPath(fileName);
+ path.appendPath(fileNameFinal);
pAsset = openAssetFromFileLocked(path, mode);
@@ -882,24 +1110,45 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m
/* look inside the zip file */
} else {
String8 path(fileName);
+ const char* zipPath;
/* check the appropriate Zip file */
- ZipFileRO* pZip = getZipFileLocked(ap);
- if (pZip != NULL) {
- //printf("GOT zip, checking NA '%s'\n", (const char*) path);
- ZipEntryRO entry = pZip->findEntryByName(path.string());
- if (entry != NULL) {
- //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon);
- pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
- pZip->releaseEntry(entry);
+ ZipFileRO* pZip;
+ ZipEntryRO entry;
+
+ if (!ap.resApkPath.isEmpty()) {
+ pZip = getZipFileLocked(ap.resApkPath);
+ if (pZip != NULL) {
+ //printf("GOT zip, checking NA '%s'\n", (const char*) path);
+ entry = pZip->findEntryByName(path.string());
+ if (entry != NULL) {
+ //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon);
+ pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
+ zipPath = ap.resApkPath.string();
+ }
+ }
+ }
+
+ if (pAsset == NULL) {
+ path.setTo(fileNameFinal);
+ pZip = getZipFileLocked(ap);
+ if (pZip != NULL) {
+ //printf("GOT zip, checking NA '%s'\n", (const char*) path);
+ ZipEntryRO entry = pZip->findEntryByName(path.string());
+ if (entry != NULL) {
+ //printf("FOUND NA in Zip file for %s\n", appName ? appName : kAppCommon);
+ pAsset = openAssetFromZipLocked(pZip, entry, mode, path);
+ pZip->releaseEntry(entry);
+ zipPath = ap.path.string();
+ }
}
}
if (pAsset != NULL) {
/* create a "source" name, for debug/display */
pAsset->setAssetSource(
- createZipSourceNameLocked(ZipSet::getPathName(ap.path.string()), String8(""),
- String8(fileName)));
+ createZipSourceNameLocked(ZipSet::getPathName(zipPath), String8(""),
+ String8(path.string())));
}
}
@@ -1111,9 +1360,14 @@ String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* roo
*/
ZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap)
{
+ return getZipFileLocked(ap.path);
+}
+
+ZipFileRO* AssetManager::getZipFileLocked(const String8& path)
+{
ALOGV("getZipFileLocked() in %p\n", this);
- return mZipSet.getZip(ap.path);
+ return mZipSet.getZip(path);
}
/*
@@ -1235,6 +1489,10 @@ AssetDir* AssetManager::openDir(const char* dirName)
while (i > 0) {
i--;
const asset_path& ap = mAssetPaths.itemAt(i);
+
+ // Skip theme/icon attached assets
+ if (ap.prefixPath.length() > 0) continue;
+
if (ap.type == kFileTypeRegular) {
ALOGV("Adding directory %s from zip %s", dirName, ap.path.string());
scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName);
@@ -1776,6 +2034,10 @@ void AssetManager::fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
while (i > 0) {
i--;
const asset_path& ap = mAssetPaths.itemAt(i);
+
+ // Skip theme/icon attached assets
+ if (ap.prefixPath.length() > 0) continue;
+
fncScanAndMergeDirLocked(pMergedInfo, ap, NULL, NULL, dirName);
if (mLocale != NULL)
fncScanAndMergeDirLocked(pMergedInfo, ap, mLocale, NULL, dirName);
@@ -2035,6 +2297,10 @@ ZipFileRO* AssetManager::ZipSet::getZip(const String8& path)
return zip->getZip();
}
+void AssetManager::ZipSet::closeZip(const String8& zip) {
+ closeZip(getIndex(zip));
+}
+
Asset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path)
{
int idx = getIndex(path);
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 62aabb1..5fe0d66 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -60,7 +60,15 @@ namespace android {
#define IDMAP_CURRENT_VERSION 0x00000001
#define APP_PACKAGE_ID 0x7f
+#define CMSDK_PACKAGE_ID 0x3f
#define SYS_PACKAGE_ID 0x01
+#define OVERLAY_APP_PACKAGE_ID 0x61
+#define OVERLAY_SYS_PACKAGE_ID 0x60
+#define OVERLAY_COMMON_PACKAGE_ID 0x5f
+
+// Define attributes from android.R.attr to protect from theme changes
+#define ATTR_WINDOW_NO_TITLE 0x01010056 // windowNoTitle
+#define ATTR_WINDOW_ACTION_BAR 0x010102cd // windowActionBar
static const bool kDebugStringPoolNoisy = false;
static const bool kDebugXMLNoisy = false;
@@ -734,7 +742,7 @@ const char16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
}
#else
// We do not want to be in this case when actually running Android.
- ALOGW("CREATING STRING CACHE OF %zu bytes",
+ ALOGV("CREATING STRING CACHE OF %zu bytes",
static_cast<size_t>(mHeader->stringCount*sizeof(char16_t**)));
#endif
mCache = (char16_t**)calloc(mHeader->stringCount, sizeof(char16_t**));
@@ -3038,6 +3046,8 @@ struct ResTable::Entry {
StringPoolRef typeStr;
StringPoolRef keyStr;
+
+ bool isFromOverlay;
};
struct ResTable::Type
@@ -3057,7 +3067,8 @@ struct ResTable::Type
struct ResTable::Package
{
Package(ResTable* _owner, const Header* _header, const ResTable_package* _package)
- : owner(_owner), header(_header), package(_package), typeIdOffset(0) {
+ : owner(_owner), header(_header), package(_package), typeIdOffset(0),
+ pkgIdOverride(0) {
if (dtohs(package->header.headerSize) == sizeof(package)) {
// The package structure is the same size as the definition.
// This means it contains the typeIdOffset field.
@@ -3073,6 +3084,7 @@ struct ResTable::Package
ResStringPool keyStrings;
size_t typeIdOffset;
+ uint32_t pkgIdOverride;
};
// A group of objects describing a particular resource package.
@@ -3087,6 +3099,7 @@ struct ResTable::PackageGroup
, largestTypeId(0)
, bags(NULL)
, dynamicRefTable(static_cast<uint8_t>(_id))
+ , overlayPackage(NULL)
{ }
~PackageGroup() {
@@ -3178,6 +3191,8 @@ struct ResTable::PackageGroup
// by having these tables in a per-package scope rather than
// per-package-group.
DynamicRefTable dynamicRefTable;
+
+ Package* overlayPackage;
};
struct ResTable::bag_set
@@ -3532,7 +3547,7 @@ ResTable::ResTable(const void* data, size_t size, const int32_t cookie, bool cop
{
memset(&mParams, 0, sizeof(mParams));
memset(mPackageMap, 0, sizeof(mPackageMap));
- addInternal(data, size, NULL, 0, cookie, copyData);
+ addInternal(data, size, NULL, 0, cookie, copyData, 0);
LOG_FATAL_IF(mError != NO_ERROR, "Error parsing resource table");
if (kDebugTableSuperNoisy) {
ALOGI("Creating ResTable %p\n", this);
@@ -3553,12 +3568,12 @@ inline ssize_t ResTable::getResourcePackageIndex(uint32_t resID) const
}
status_t ResTable::add(const void* data, size_t size, const int32_t cookie, bool copyData) {
- return addInternal(data, size, NULL, 0, cookie, copyData);
+ return addInternal(data, size, NULL, 0, cookie, copyData, 0);
}
status_t ResTable::add(const void* data, size_t size, const void* idmapData, size_t idmapDataSize,
- const int32_t cookie, bool copyData) {
- return addInternal(data, size, idmapData, idmapDataSize, cookie, copyData);
+ const int32_t cookie, bool copyData, const uint32_t pkgIdOverride) {
+ return addInternal(data, size, idmapData, idmapDataSize, cookie, copyData, pkgIdOverride);
}
status_t ResTable::add(Asset* asset, const int32_t cookie, bool copyData) {
@@ -3568,10 +3583,11 @@ status_t ResTable::add(Asset* asset, const int32_t cookie, bool copyData) {
return UNKNOWN_ERROR;
}
- return addInternal(data, static_cast<size_t>(asset->getLength()), NULL, 0, cookie, copyData);
+ return addInternal(data, static_cast<size_t>(asset->getLength()), NULL, 0, cookie, copyData, 0);
}
-status_t ResTable::add(Asset* asset, Asset* idmapAsset, const int32_t cookie, bool copyData) {
+status_t ResTable::add(Asset* asset, Asset* idmapAsset, const int32_t cookie, bool copyData,
+ const uint32_t pkgIdOverride) {
const void* data = asset->getBuffer(true);
if (data == NULL) {
ALOGW("Unable to get buffer of resource asset file");
@@ -3590,7 +3606,7 @@ status_t ResTable::add(Asset* asset, Asset* idmapAsset, const int32_t cookie, bo
}
return addInternal(data, static_cast<size_t>(asset->getLength()),
- idmapData, idmapSize, cookie, copyData);
+ idmapData, idmapSize, cookie, copyData, pkgIdOverride);
}
status_t ResTable::add(ResTable* src)
@@ -3644,7 +3660,7 @@ status_t ResTable::addEmpty(const int32_t cookie) {
}
status_t ResTable::addInternal(const void* data, size_t dataSize, const void* idmapData, size_t idmapDataSize,
- const int32_t cookie, bool copyData)
+ const int32_t cookie, bool copyData, const uint32_t pkgIdOverride)
{
if (!data) {
return NO_ERROR;
@@ -3747,7 +3763,11 @@ status_t ResTable::addInternal(const void* data, size_t dataSize, const void* id
return (mError=BAD_TYPE);
}
- if (parsePackage((ResTable_package*)chunk, header) != NO_ERROR) {
+ // Warning: If the pkg id will be overriden and there is more than one package in the
+ // resource table then the caller should make sure there are enough unique ids above
+ // pkgIdOverride.
+ uint32_t idOverride = (pkgIdOverride == 0) ? 0 : pkgIdOverride + curPackage;
+ if (parsePackage((ResTable_package*)chunk, header, idOverride) != NO_ERROR) {
return mError;
}
curPackage++;
@@ -4033,8 +4053,27 @@ void ResTable::unlock() const
mLock.unlock();
}
+// Protected attributes are not permitted to be themed. If a theme
+// does try to change a protected attribute it will be overriden
+// by the app's original value.
+const static uint32_t PROTECTED_ATTRS[] = {
+ ATTR_WINDOW_NO_TITLE,
+ ATTR_WINDOW_ACTION_BAR
+};
+
+bool ResTable::isProtectedAttr(uint32_t resID) const
+{
+ int length = sizeof(PROTECTED_ATTRS) / sizeof(PROTECTED_ATTRS[0]);
+ for(int i=0; i < length; i++) {
+ if (PROTECTED_ATTRS[i] == resID) {
+ return true;
+ }
+ }
+ return false;
+}
+
ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag,
- uint32_t* outTypeSpecFlags) const
+ uint32_t* outTypeSpecFlags, bool performMapping) const
{
if (mError != NO_ERROR) {
return mError;
@@ -4074,7 +4113,7 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag,
}
// First see if we've already computed this bag...
- if (grp->bags) {
+ if (grp->bags && performMapping) {
bag_set** typeSet = grp->bags->get(t);
if (typeSet) {
bag_set* set = typeSet[e];
@@ -4118,7 +4157,7 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag,
// Now collect all bag attributes
Entry entry;
- status_t err = getEntry(grp, t, e, &mParams, &entry);
+ status_t err = getEntry(grp, t, e, &mParams, &entry, performMapping);
if (err != NO_ERROR) {
return err;
}
@@ -4157,7 +4196,8 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag,
const bag_entry* parentBag;
uint32_t parentTypeSpecFlags = 0;
- const ssize_t NP = getBagLocked(resolvedParent, &parentBag, &parentTypeSpecFlags);
+ const ssize_t NP = getBagLocked(resolvedParent, &parentBag, &parentTypeSpecFlags,
+ (resolvedParent != resID || !entry.isFromOverlay));
const size_t NT = ((NP >= 0) ? NP : 0) + N;
set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*NT);
if (set == NULL) {
@@ -4295,6 +4335,68 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag,
set->numAttrs = curEntry;
}
+ if (entry.isFromOverlay) {
+ const bag_entry* originalBag;
+ uint32_t originalTypeSpecFlags = 0;
+ const ssize_t NO = getBagLocked(resID, &originalBag,
+ &originalTypeSpecFlags, false);
+ if (NO <= 0) {
+ ALOGW("Failed to retrieve original bag for 0x%08x", resID);
+ }
+
+ // Now merge in the original attributes...
+ bag_entry* entries = (bag_entry*)(set+1);
+ size_t curEntry = 0;
+ for (int i = 0; i < NO; i++) {
+ const uint32_t newName = originalBag[i].map.name.ident;
+ bool isInside;
+ uint32_t oldName = 0;
+ curEntry = 0;
+
+ while ((isInside=(curEntry < set->numAttrs))
+ && (oldName=entries[curEntry].map.name.ident) < newName) {
+ curEntry++;
+ }
+
+ if ((!isInside) || oldName != newName) {
+ // This is a new attribute... figure out what to do with it.
+ // Need to alloc more memory...
+ size_t prevEntry = curEntry;
+ curEntry = set->availAttrs;
+ set->availAttrs++;
+ const size_t newAvail = set->availAttrs;
+ set = (bag_set*)realloc(set,
+ sizeof(bag_set)
+ + sizeof(bag_entry)*newAvail);
+ if (set == NULL) {
+ return NO_MEMORY;
+ }
+ entries = (bag_entry*)(set+1);
+ if (isInside) {
+ // Going in the middle, need to make space.
+ memmove(entries+prevEntry+1, entries+prevEntry,
+ sizeof(bag_entry)*(set->numAttrs-prevEntry));
+ }
+
+ bag_entry* cur = entries+curEntry;
+
+ cur->stringBlock = originalBag[i].stringBlock;
+ cur->map.name.ident = originalBag[i].map.name.ident;
+ cur->map.value = originalBag[i].map.value;
+ set->typeSpecFlags |= originalTypeSpecFlags;
+ set->numAttrs = set->availAttrs;
+ } else if (isProtectedAttr(newName)) {
+ // The attribute exists in both the original and the new theme bags,
+ // furthermore it is an attribute we don't wish themers to theme, so
+ // give our current themed bag the same value as the original
+ bag_entry* cur = entries+curEntry;
+ cur->stringBlock = originalBag[i].stringBlock;
+ cur->map.name.ident = originalBag[i].map.name.ident;
+ cur->map.value = originalBag[i].map.value;
+ }
+ }
+ }
+
// And this is it...
typeSet[e] = set;
if (set) {
@@ -5038,7 +5140,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
}
uint32_t packageId = Res_GETPACKAGE(rid) + 1;
- if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID) {
+ if (isDynamicPackageId(packageId)) {
outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
}
outValue->data = rid;
@@ -5059,7 +5161,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
outValue->data = rid;
outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
return true;
- } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) {
+ } else if (!isDynamicPackageId(packageId)) {
// We accept packageId's generated as 0x01 in order to support
// building the android system resources
outValue->data = rid;
@@ -5188,6 +5290,13 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
identifierForName(name.string(), name.size(),
type.string(), type.size(),
package.string(), package.size(), &specFlags);
+// HACK
+// This allows themes to reference attributes that are app specific and
+// normally private. Only applies to aapt running on device not host
+// build systems.
+#ifdef HAVE_ANDROID_OS
+ enforcePrivate = false;
+#endif
if (rid != 0) {
if (enforcePrivate) {
if ((specFlags&ResTable_typeSpec::SPEC_PUBLIC) == 0) {
@@ -5792,7 +5901,8 @@ bool ResTable::getResourceFlags(uint32_t resID, uint32_t* outFlags) const {
status_t ResTable::getEntry(
const PackageGroup* packageGroup, int typeIndex, int entryIndex,
const ResTable_config* config,
- Entry* outEntry) const
+ Entry* outEntry,
+ const bool performMapping) const
{
const TypeList& typeList = packageGroup->types[typeIndex];
if (typeList.isEmpty()) {
@@ -5808,6 +5918,8 @@ status_t ResTable::getEntry(
ResTable_config bestConfig;
memset(&bestConfig, 0, sizeof(bestConfig));
+ bool currentTypeIsOverlay = false;
+
// Iterate over the Types of each package.
const size_t typeCount = typeList.size();
for (size_t i = 0; i < typeCount; i++) {
@@ -5815,11 +5927,11 @@ status_t ResTable::getEntry(
int realEntryIndex = entryIndex;
int realTypeIndex = typeIndex;
- bool currentTypeIsOverlay = false;
+ currentTypeIsOverlay = false;
// Runtime overlay packages provide a mapping of app resource
// ID to package resource ID.
- if (typeSpec->idmapEntries.hasEntries()) {
+ if (performMapping && typeSpec->idmapEntries.hasEntries()) {
uint16_t overlayEntryIndex;
if (typeSpec->idmapEntries.lookup(entryIndex, &overlayEntryIndex) != NO_ERROR) {
// No such mapping exists
@@ -5831,7 +5943,7 @@ status_t ResTable::getEntry(
}
if (static_cast<size_t>(realEntryIndex) >= typeSpec->entryCount) {
- ALOGW("For resource 0x%08x, entry index(%d) is beyond type entryCount(%d)",
+ ALOGV("For resource 0x%08x, entry index(%d) is beyond type entryCount(%d)",
Res_MAKEID(packageGroup->id - 1, typeIndex, entryIndex),
entryIndex, static_cast<int>(typeSpec->entryCount));
// We should normally abort here, but some legacy apps declare
@@ -5875,7 +5987,7 @@ status_t ResTable::getEntry(
// Check if this one is less specific than the last found. If so,
// we will skip it. We check starting with things we most care
// about to those we least care about.
- if (!thisConfig.isBetterThan(bestConfig, config)) {
+ if (!currentTypeIsOverlay && !thisConfig.isBetterThan(bestConfig, config)) {
if (!currentTypeIsOverlay || thisConfig.compare(bestConfig) != 0) {
continue;
}
@@ -5926,12 +6038,13 @@ status_t ResTable::getEntry(
outEntry->package = bestPackage;
outEntry->typeStr = StringPoolRef(&bestPackage->typeStrings, actualTypeIndex - bestPackage->typeIdOffset);
outEntry->keyStr = StringPoolRef(&bestPackage->keyStrings, dtohl(entry->key.index));
+ outEntry->isFromOverlay = currentTypeIsOverlay;
}
return NO_ERROR;
}
status_t ResTable::parsePackage(const ResTable_package* const pkg,
- const Header* const header)
+ const Header* const header, const uint32_t pkgIdOverride)
{
const uint8_t* base = (const uint8_t*)pkg;
status_t err = validate_chunk(&pkg->header, sizeof(*pkg) - sizeof(pkg->typeIdOffset),
@@ -5965,15 +6078,14 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
uint32_t id = dtohl(pkg->id);
KeyedVector<uint8_t, IdmapEntries> idmapEntries;
+ uint8_t targetPackageId = 0;
if (header->resourceIDMap != NULL) {
- uint8_t targetPackageId = 0;
status_t err = parseIdmap(header->resourceIDMap, header->resourceIDMapSize, &targetPackageId, &idmapEntries);
if (err != NO_ERROR) {
ALOGW("Overlay is broken");
return (mError=err);
}
- id = targetPackageId;
}
if (id >= 256) {
@@ -5984,11 +6096,17 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
id = mNextPackageId++;
}
+ if (pkgIdOverride != 0) {
+ ALOGV("Overriding pkg id %d with %d", id, pkgIdOverride);
+ id = pkgIdOverride;
+ }
+
PackageGroup* group = NULL;
Package* package = new Package(this, header, pkg);
if (package == NULL) {
return (mError=NO_MEMORY);
}
+ package->pkgIdOverride = pkgIdOverride;
err = package->typeStrings.setTo(base+dtohl(pkg->typeStrings),
header->dataEnd-(base+dtohl(pkg->typeStrings)));
@@ -6043,6 +6161,15 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
return (mError=err);
}
+ // Get the target group if this is an overlay
+ PackageGroup* targetGroup = NULL;
+ if (header->resourceIDMap != NULL) {
+ targetGroup = mPackageGroups.itemAt(mPackageMap[targetPackageId] - 1);
+ if (targetGroup != NULL) {
+ targetGroup->overlayPackage = package;
+ }
+ }
+
// Iterate through all chunks.
const ResChunk_header* chunk =
(const ResChunk_header*)(((const uint8_t*)pkg)
@@ -6092,16 +6219,12 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
if (newEntryCount > 0) {
uint8_t typeIndex = typeSpec->id - 1;
- ssize_t idmapIndex = idmapEntries.indexOfKey(typeSpec->id);
- if (idmapIndex >= 0) {
- typeIndex = idmapEntries[idmapIndex].targetTypeId() - 1;
- }
TypeList& typeList = group->types.editItemAt(typeIndex);
if (!typeList.isEmpty()) {
const Type* existingType = typeList[0];
- if (existingType->entryCount != newEntryCount && idmapIndex < 0) {
- ALOGW("ResTable_typeSpec entry count inconsistent: given %d, previously %d",
+ if (existingType->entryCount != newEntryCount) {
+ ALOGV("ResTable_typeSpec entry count inconsistent: given %d, previously %d",
(int) newEntryCount, (int) existingType->entryCount);
// We should normally abort here, but some legacy apps declare
// resources in the 'android' package (old bug in AAPT).
@@ -6112,11 +6235,23 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
t->typeSpec = typeSpec;
t->typeSpecFlags = (const uint32_t*)(
((const uint8_t*)typeSpec) + dtohs(typeSpec->header.headerSize));
- if (idmapIndex >= 0) {
- t->idmapEntries = idmapEntries[idmapIndex];
- }
typeList.add(t);
group->largestTypeId = max(group->largestTypeId, typeSpec->id);
+
+ // Add this type spec to the targetGroup
+ if (targetGroup != NULL) {
+ ssize_t idmapIndex = idmapEntries.indexOfKey(typeSpec->id);
+ if (idmapIndex >= 0) {
+ typeIndex = idmapEntries[idmapIndex].targetTypeId() - 1;
+ TypeList& typeList = targetGroup->types.editItemAt(typeIndex);
+ Type* t = new Type(header, package, newEntryCount);
+ t->idmapEntries = idmapEntries[idmapIndex];
+ t->typeSpec = typeSpec;
+ t->typeSpecFlags = (const uint32_t*)(
+ ((const uint8_t*)typeSpec) + dtohs(typeSpec->header.headerSize));
+ typeList.add(t);
+ }
+ }
} else {
ALOGV("Skipping empty ResTable_typeSpec for type %d", typeSpec->id);
}
@@ -6160,10 +6295,6 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
if (newEntryCount > 0) {
uint8_t typeIndex = type->id - 1;
- ssize_t idmapIndex = idmapEntries.indexOfKey(type->id);
- if (idmapIndex >= 0) {
- typeIndex = idmapEntries[idmapIndex].targetTypeId() - 1;
- }
TypeList& typeList = group->types.editItemAt(typeIndex);
if (typeList.isEmpty()) {
@@ -6191,6 +6322,30 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
ALOGI("Adding config to type %d: %s\n", type->id,
thisConfig.toString().string());
}
+
+ // Add this type to the targetGroup
+ if (targetGroup != NULL) {
+ ssize_t idmapIndex = idmapEntries.indexOfKey(type->id);
+ if (idmapIndex >= 0) {
+ typeIndex = idmapEntries[idmapIndex].targetTypeId() - 1;
+ TypeList& typeList = targetGroup->types.editItemAt(typeIndex);
+ if (typeList.isEmpty()) {
+ ALOGE("No TypeSpec for type %d", type->id);
+ return (mError=BAD_TYPE);
+ }
+ Type* t = typeList.editItemAt(typeList.size() - 1);
+ if (newEntryCount != t->entryCount) {
+ ALOGE("ResTable_type entry count inconsistent: given %d, previously %d",
+ (int)newEntryCount, (int)t->entryCount);
+ return (mError=BAD_TYPE);
+ }
+ if (t->package != package) {
+ ALOGE("No TypeSpec for type %d", type->id);
+ return (mError=BAD_TYPE);
+ }
+ t->configs.add(type);
+ }
+ }
} else {
ALOGV("Skipping empty ResTable_type for type %d", type->id);
}
@@ -6232,6 +6387,10 @@ DynamicRefTable::DynamicRefTable(uint8_t packageId)
// Reserved package ids
mLookupTable[APP_PACKAGE_ID] = APP_PACKAGE_ID;
mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
+ mLookupTable[CMSDK_PACKAGE_ID] = CMSDK_PACKAGE_ID;
+ mLookupTable[OVERLAY_APP_PACKAGE_ID] = OVERLAY_APP_PACKAGE_ID;
+ mLookupTable[OVERLAY_SYS_PACKAGE_ID] = OVERLAY_SYS_PACKAGE_ID;
+ mLookupTable[OVERLAY_COMMON_PACKAGE_ID] = OVERLAY_COMMON_PACKAGE_ID;
}
status_t DynamicRefTable::load(const ResTable_lib_header* const header)
@@ -6310,7 +6469,8 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const {
uint32_t res = *resId;
size_t packageId = Res_GETPACKAGE(res) + 1;
- if (packageId == APP_PACKAGE_ID) {
+ if (packageId == APP_PACKAGE_ID || packageId == OVERLAY_APP_PACKAGE_ID ||
+ packageId == OVERLAY_SYS_PACKAGE_ID || packageId == OVERLAY_COMMON_PACKAGE_ID) {
// No lookup needs to be done, app package IDs are absolute.
return NO_ERROR;
}
@@ -6362,6 +6522,7 @@ struct IdmapTypeMap {
status_t ResTable::createIdmap(const ResTable& overlay,
uint32_t targetCrc, uint32_t overlayCrc,
+ time_t targetMtime, time_t overlayMtime,
const char* targetPath, const char* overlayPath,
void** outData, size_t* outSize) const
{
@@ -6379,8 +6540,10 @@ status_t ResTable::createIdmap(const ResTable& overlay,
KeyedVector<uint8_t, IdmapTypeMap> map;
- // overlaid packages are assumed to contain only one package group
- const PackageGroup* pg = mPackageGroups[0];
+ // Overlaid packages are assumed to contain only one package group or two package group
+ // as one is "system package(android)", and another is "application package". So we need
+ // to use the last package group to create idmap.
+ const PackageGroup* pg = mPackageGroups[mPackageGroups.size() - 1];
// starting size is header
*outSize = ResTable::IDMAP_HEADER_SIZE_BYTES;
@@ -6393,77 +6556,103 @@ status_t ResTable::createIdmap(const ResTable& overlay,
char16_t tmpName[sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])];
strcpy16_dtoh(tmpName, overlayPackageStruct->name, sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0]));
const String16 overlayPackage(tmpName);
+ Package* pkg;
+ size_t typeCount;
+ uint32_t pkg_id;
+
+ const uint32_t groupCount = mPackageGroups.size();
+ for (int groupIdx = groupCount - 1; groupIdx >= 0; groupIdx--) {
+ pg = mPackageGroups[groupIdx];
+ pkg = pg->packages[0];
+ typeCount = pg->types.size();
+ pkg_id = pkg->package->id << 24;
+
+ for (size_t typeIndex = 0; typeIndex < typeCount; ++typeIndex) {
+ const TypeList& typeList = pg->types[typeIndex];
+ if (typeList.isEmpty()) {
+ continue;
+ }
- for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) {
- const TypeList& typeList = pg->types[typeIndex];
- if (typeList.isEmpty()) {
- continue;
- }
+ const Type* typeConfigs = typeList[0];
+
+ IdmapTypeMap typeMap;
+ typeMap.overlayTypeId = -1;
+ typeMap.entryOffset = 0;
- const Type* typeConfigs = typeList[0];
+ for (size_t entryIndex = 0; entryIndex < typeConfigs->entryCount; ++entryIndex) {
+ uint32_t resID = Res_MAKEID(pg->id - 1, typeIndex, entryIndex);
+ resource_name resName;
+ if (!this->getResourceName(resID, false, &resName)) {
+ if (typeMap.entryMap.isEmpty()) {
+ typeMap.entryOffset++;
+ }
+ continue;
+ }
- IdmapTypeMap typeMap;
- typeMap.overlayTypeId = -1;
- typeMap.entryOffset = 0;
+ // check if resource type is "allowed", if not continue
+ String8 type8;
+ if (resName.type8 != NULL) {
+ type8 = String8(resName.type8, resName.typeLen);
+ } else {
+ type8 = String8(resName.type, resName.typeLen);
+ }
+ if (!isResTypeAllowed(type8.string())) {
+ if (typeMap.entryMap.isEmpty()) {
+ typeMap.entryOffset++;
+ }
+ continue;
+ }
- for (size_t entryIndex = 0; entryIndex < typeConfigs->entryCount; ++entryIndex) {
- uint32_t resID = Res_MAKEID(pg->id - 1, typeIndex, entryIndex);
- resource_name resName;
- if (!this->getResourceName(resID, false, &resName)) {
- if (typeMap.entryMap.isEmpty()) {
- typeMap.entryOffset++;
+ const String16 overlayType(resName.type, resName.typeLen);
+ const String16 overlayName(resName.name, resName.nameLen);
+ uint32_t overlayResID = overlay.identifierForName(overlayName.string(),
+ overlayName.size(),
+ overlayType.string(),
+ overlayType.size(),
+ overlayPackage.string(),
+ overlayPackage.size());
+ if (overlayResID == 0) {
+ if (typeMap.entryMap.isEmpty()) {
+ typeMap.entryOffset++;
+ }
+ continue;
+ } else {
+ overlayResID = pkg_id | (0x00ffffff & overlayResID);
}
- continue;
- }
- const String16 overlayType(resName.type, resName.typeLen);
- const String16 overlayName(resName.name, resName.nameLen);
- uint32_t overlayResID = overlay.identifierForName(overlayName.string(),
- overlayName.size(),
- overlayType.string(),
- overlayType.size(),
- overlayPackage.string(),
- overlayPackage.size());
- if (overlayResID == 0) {
- if (typeMap.entryMap.isEmpty()) {
- typeMap.entryOffset++;
+ if (typeMap.overlayTypeId == -1) {
+ typeMap.overlayTypeId = Res_GETTYPE(overlayResID) + 1;
}
- continue;
- }
- if (typeMap.overlayTypeId == -1) {
- typeMap.overlayTypeId = Res_GETTYPE(overlayResID) + 1;
- }
+ if (Res_GETTYPE(overlayResID) + 1 != static_cast<size_t>(typeMap.overlayTypeId)) {
+ ALOGE("idmap: can't mix type ids in entry map. Resource 0x%08x maps to 0x%08x"
+ " but entries should map to resources of type %02zx",
+ resID, overlayResID, typeMap.overlayTypeId);
+ return BAD_TYPE;
+ }
- if (Res_GETTYPE(overlayResID) + 1 != static_cast<size_t>(typeMap.overlayTypeId)) {
- ALOGE("idmap: can't mix type ids in entry map. Resource 0x%08x maps to 0x%08x"
- " but entries should map to resources of type %02zx",
- resID, overlayResID, typeMap.overlayTypeId);
- return BAD_TYPE;
+ if (typeMap.entryOffset + typeMap.entryMap.size() < entryIndex) {
+ // pad with 0xffffffff's (indicating non-existing entries) before adding this entry
+ size_t index = typeMap.entryMap.size();
+ size_t numItems = entryIndex - (typeMap.entryOffset + index);
+ if (typeMap.entryMap.insertAt(0xffffffff, index, numItems) < 0) {
+ return NO_MEMORY;
+ }
+ }
+ typeMap.entryMap.add(Res_GETENTRY(overlayResID));
}
- if (typeMap.entryOffset + typeMap.entryMap.size() < entryIndex) {
- // pad with 0xffffffff's (indicating non-existing entries) before adding this entry
- size_t index = typeMap.entryMap.size();
- size_t numItems = entryIndex - (typeMap.entryOffset + index);
- if (typeMap.entryMap.insertAt(0xffffffff, index, numItems) < 0) {
+ if (!typeMap.entryMap.isEmpty()) {
+ if (map.add(static_cast<uint8_t>(typeIndex), typeMap) < 0) {
return NO_MEMORY;
}
+ *outSize += (4 * sizeof(uint16_t)) + (typeMap.entryMap.size() * sizeof(uint32_t));
}
- typeMap.entryMap.add(Res_GETENTRY(overlayResID));
- }
-
- if (!typeMap.entryMap.isEmpty()) {
- if (map.add(static_cast<uint8_t>(typeIndex), typeMap) < 0) {
- return NO_MEMORY;
- }
- *outSize += (4 * sizeof(uint16_t)) + (typeMap.entryMap.size() * sizeof(uint32_t));
}
}
if (map.isEmpty()) {
ALOGW("idmap: no resources in overlay package present in base package");
- return UNKNOWN_ERROR;
}
if ((*outData = malloc(*outSize)) == NULL) {
@@ -6475,6 +6664,8 @@ status_t ResTable::createIdmap(const ResTable& overlay,
*data++ = htodl(IDMAP_CURRENT_VERSION);
*data++ = htodl(targetCrc);
*data++ = htodl(overlayCrc);
+ *data++ = htodl(targetMtime);
+ *data++ = htodl(overlayMtime);
const char* paths[] = { targetPath, overlayPath };
for (int j = 0; j < 2; ++j) {
char* p = (char*)data;
@@ -6531,14 +6722,107 @@ bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
*pOverlayCrc = dtohl(map[3]);
}
if (pTargetPath) {
- pTargetPath->setTo(reinterpret_cast<const char*>(map + 4));
+ pTargetPath->setTo(reinterpret_cast<const char*>(map + 6));
}
if (pOverlayPath) {
- pOverlayPath->setTo(reinterpret_cast<const char*>(map + 4 + 256 / sizeof(uint32_t)));
+ pOverlayPath->setTo(reinterpret_cast<const char*>(map + 6 + 256 / sizeof(uint32_t)));
}
return true;
}
+void ResTable::removeAssetsByCookie(const String8& /* packageName */, int32_t cookie)
+{
+ mError = NO_ERROR;
+ size_t pgCount = mPackageGroups.size();
+ for (size_t pgIndex = 0; pgIndex < pgCount; pgIndex++) {
+ PackageGroup* pg = mPackageGroups[pgIndex];
+ size_t pkgCount = pg->packages.size();
+ size_t index = pkgCount;
+ for (size_t pkgIndex = 0; pkgIndex < pkgCount; pkgIndex++) {
+ const Package* pkg = pg->packages[pkgIndex];
+ if (pkg->header->cookie == cookie) {
+ index = pkgIndex;
+ break;
+ }
+ }
+ if (index < pkgCount) {
+ const Package* pkg = pg->packages[index];
+ uint32_t id = dtohl(pkg->package->id);
+ if (pkg->pkgIdOverride != 0) {
+ id = pkg->pkgIdOverride;
+ }
+ if (id != 0 && id < 256 && pkgCount == 1) {
+ mPackageMap[id] = 0;
+ }
+ // Check if this package is being reference in any other groups and remove it
+ size_t N = mPackageGroups.size();
+ for (size_t i = 0; i < N; i++) {
+ PackageGroup* grp = mPackageGroups.itemAt(i);
+ if (grp->overlayPackage == pkg) {
+ removeIdmappedTypesFromPackageGroup(grp);
+ grp->clearBagCache();
+ grp->overlayPackage = NULL;
+ }
+ }
+ if (pkgCount == 1) {
+ mPackageGroups.removeAt(pgIndex);
+ delete pg;
+ } else {
+ pg->packages.removeAt(index);
+ delete pkg;
+ }
+ break;
+ }
+ }
+ size_t N = mHeaders.size();
+ for (size_t i = 0; i < N; i++) {
+ Header* header = mHeaders[i];
+ if (header->cookie == cookie) {
+ if (header->ownedData != NULL) {
+ free(header->ownedData);
+ }
+ mHeaders.removeAt(i);
+ break;
+ }
+ }
+}
+
+bool ResTable::isResTypeAllowed(const char* type) const {
+ if (type == NULL) return false;
+ const char* allowedResources[] = { "color", "dimen", "drawable", "mipmap", "style", "anim" };
+ // ALLOWED_RESOURCE_COUNT should match the number of elements in allowedResources
+ const uint32_t ALLOWED_RESOURCE_COUNT = 6;
+ for (uint32_t i = 0; i < ALLOWED_RESOURCE_COUNT; i++) {
+ if (strstr(type, allowedResources[i]) != NULL) return true;
+ }
+ return false;
+}
+
+bool ResTable::isDynamicPackageId(const uint32_t pkgId) const {
+ return pkgId != APP_PACKAGE_ID && pkgId != SYS_PACKAGE_ID
+ && pkgId != OVERLAY_APP_PACKAGE_ID && pkgId != OVERLAY_SYS_PACKAGE_ID
+ && pkgId != OVERLAY_COMMON_PACKAGE_ID && pkgId != CMSDK_PACKAGE_ID;
+}
+
+status_t ResTable::removeIdmappedTypesFromPackageGroup(PackageGroup* packageGroup) const {
+ for (size_t idx = 0; idx < Res_MAXTYPE; idx++) {
+ const TypeList& typeList = packageGroup->types[idx];
+ if (!typeList.isEmpty()) {
+ TypeList& editTypeList = packageGroup->types.editItemAt(idx);
+ // Iterate over the Types of each package.
+ for (Vector<Type*>::iterator iter = editTypeList.begin();
+ iter != editTypeList.end();) {
+ Type* type = *iter;
+ if (type->idmapEntries.hasEntries()) {
+ iter = editTypeList.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+ }
+ }
+ return NO_ERROR;
+}
#define CHAR16_TO_CSTR(c16, len) (String8(String16(c16,len)).string())
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index a353575..5fd17cc 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -25,23 +25,17 @@ testFiles := \
ByteBucketArray_test.cpp \
Config_test.cpp \
ConfigLocale_test.cpp \
- Idmap_test.cpp \
+ PackageIdOverride_test.cpp \
ResTable_test.cpp \
Split_test.cpp \
TestHelpers.cpp \
Theme_test.cpp \
+ ThemesBags_test.cpp \
+ ThemesIdmap_test.cpp \
TypeWrappers_test.cpp \
ZipUtils_test.cpp
-androidfw_test_cflags := \
- -Wall \
- -Werror \
- -Wunused \
- -Wunreachable-code \
- -Wno-missing-field-initializers \
-# gtest is broken.
-androidfw_test_cflags += -Wno-unnamed-type-template-args
# ==========================================================
# Build the host tests: libandroidfw_tests
@@ -49,7 +43,7 @@ androidfw_test_cflags += -Wno-unnamed-type-template-args
include $(CLEAR_VARS)
LOCAL_MODULE := libandroidfw_tests
-LOCAL_CFLAGS := $(androidfw_test_cflags)
+
LOCAL_SRC_FILES := $(testFiles)
LOCAL_STATIC_LIBRARIES := \
libandroidfw \
@@ -67,7 +61,6 @@ ifneq ($(SDK_ONLY),true)
include $(CLEAR_VARS)
LOCAL_MODULE := libandroidfw_tests
-LOCAL_CFLAGS := $(androidfw_test_cflags)
LOCAL_SRC_FILES := $(testFiles) \
BackupData_test.cpp \
ObbFile_test.cpp \
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index f50c178..181a7cc 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -50,7 +50,7 @@ protected:
ASSERT_EQ(NO_ERROR, mTargetTable.add(basic_arsc, basic_arsc_len));
ASSERT_EQ(NO_ERROR, mOverlayTable.add(overlay_arsc, overlay_arsc_len));
char targetName[256] = "com.android.test.basic";
- ASSERT_EQ(NO_ERROR, mTargetTable.createIdmap(mOverlayTable, 0, 0,
+ ASSERT_EQ(NO_ERROR, mTargetTable.createIdmap(mOverlayTable, 0, 0, 0, 0,
targetName, targetName, &mData, &mDataSize));
}
diff --git a/libs/androidfw/tests/PackageIdOverride_test.cpp b/libs/androidfw/tests/PackageIdOverride_test.cpp
new file mode 100644
index 0000000..c1d645f
--- /dev/null
+++ b/libs/androidfw/tests/PackageIdOverride_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/ResourceTypes.h>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include "TestHelpers.h"
+#include "data/cm/override/R.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+namespace {
+
+#include "data/cm/override/override_arsc.h"
+
+TEST(PackageIdOverrideTest, shouldOverridePackageId) {
+ const uint32_t pkgIdOverride = 0x42;
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(override_arsc, override_arsc_len, NULL, 0, -1, false,
+ pkgIdOverride));
+
+ Res_value val;
+ // we should not be able to retrieve the resource using the build time package id
+ uint32_t resId = override::R::string::string1;
+ ssize_t block = table.getResource(resId, &val, false);
+ ASSERT_LT(block, 0);
+
+ // now make sure we can access the resource using the runtime package id
+ resId = (override::R::string::string1 & 0x00ffffff) | (pkgIdOverride << 24);
+ block = table.getResource(resId, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ const ResStringPool* pool = table.getTableStringBlock(block);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
+
+ size_t strLen;
+ const char16_t* targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("string1"), String16(targetStr16, strLen));
+}
+
+}
diff --git a/libs/androidfw/tests/ThemesBags_test.cpp b/libs/androidfw/tests/ThemesBags_test.cpp
new file mode 100644
index 0000000..b1d7c19
--- /dev/null
+++ b/libs/androidfw/tests/ThemesBags_test.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/ResourceTypes.h>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include "TestHelpers.h"
+#include "data/cm/system/R.h"
+#include "data/cm/app/R.h"
+#include "data/cm/bags/R.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+namespace {
+
+/**
+ * Include a binary resource table.
+ *
+ * Package: android
+ */
+#include "data/cm/system/system_arsc.h"
+
+/**
+ * Include a binary resource table.
+ *
+ * Package: com.android.app
+ */
+#include "data/cm/app/app_arsc.h"
+
+/**
+ * Include a binary resource table.
+ * This table is an overlay.
+ *
+ * Package: com.android.test.bags
+ */
+#include "data/cm/bags/bags_arsc.h"
+
+enum { MAY_NOT_BE_BAG = false };
+
+class BagsTest : public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(app_arsc, app_arsc_len));
+ ASSERT_EQ(NO_ERROR, mOverlayTable.add(bags_arsc, bags_arsc_len));
+ char targetName[256] = "com.android.app";
+ ASSERT_EQ(NO_ERROR, mTargetTable.createIdmap(mOverlayTable, 0, 0, 0, 0,
+ targetName, targetName, &mData, &mDataSize));
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(system_arsc, system_arsc_len));
+ }
+
+ virtual void TearDown() {
+ free(mData);
+ }
+
+ ResTable mTargetTable;
+ ResTable mOverlayTable;
+ void* mData;
+ size_t mDataSize;
+};
+
+TEST_F(BagsTest, canLoadIdmap) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(bags_arsc, bags_arsc_len, mData, mDataSize));
+}
+
+TEST_F(BagsTest, overlayOverridesStyleAttribute) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(bags_arsc, bags_arsc_len, mData, mDataSize));
+
+ ResTable::Theme theme2(mTargetTable);
+ ASSERT_EQ(NO_ERROR, theme2.applyStyle(app::R::style::Theme_Two));
+
+ Res_value val;
+ ASSERT_GE(theme2.getAttribute(android::R::attr::background, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xff0000ff), val.data);
+}
+
+TEST_F(BagsTest, overlayCanResolveReferencesToOwnPackage) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(bags_arsc, bags_arsc_len, mData, mDataSize));
+
+ ResTable::Theme theme2(mTargetTable);
+ ASSERT_EQ(NO_ERROR, theme2.applyStyle(app::R::style::Theme_Two));
+
+ Res_value attr;
+ ssize_t block = theme2.getAttribute(android::R::attr::foreground, &attr);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, attr.dataType);
+ ASSERT_EQ(uint32_t(bags::R::color::magenta), attr.data);
+ Res_value val;
+ block = mTargetTable.getResource(attr.data, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xffff00ff), val.data);
+}
+
+TEST_F(BagsTest, overlayCanReferenceOwnStyle) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(bags_arsc, bags_arsc_len, mData, mDataSize));
+
+ ResTable::Theme theme3(mTargetTable);
+ ASSERT_EQ(NO_ERROR, theme3.applyStyle(app::R::style::Theme_Three));
+
+ Res_value attr;
+ ssize_t block = theme3.getAttribute(android::R::attr::foreground, &attr);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, attr.dataType);
+ ASSERT_EQ(uint32_t(bags::R::color::cyan), attr.data);
+ Res_value val;
+ block = mTargetTable.getResource(attr.data, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xff00ffff), val.data);
+
+ // verify that we still get the parent attribute for background
+ block = theme3.getAttribute(android::R::attr::background, &attr);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, attr.dataType);
+ ASSERT_EQ(uint32_t(0xffff0000), attr.data);
+}
+
+TEST_F(BagsTest, overlaidStyleContainsMissingAttributes) {
+ const uint32_t SOME_DIMEN_VALUE = 0x00003001;
+
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(bags_arsc, bags_arsc_len, mData, mDataSize));
+
+ ResTable::Theme theme(mTargetTable);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(app::R::style::Theme_Four));
+
+ // First let's make sure we have the themed style by checking the background attribute
+ Res_value attr;
+ ssize_t block = theme.getAttribute(android::R::attr::background, &attr);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, attr.dataType);
+ ASSERT_EQ(uint32_t(0xffaabbcc), attr.data);
+
+ // Now check if the someDimen attribute in the parent was merged in correctly since the theme
+ // does not contain this attribute in the overlaid style
+ block = theme.getAttribute(android::R::attr::some_dimen, &attr);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_DIMENSION, attr.dataType);
+ ASSERT_EQ(SOME_DIMEN_VALUE, attr.data);
+}
+
+TEST_F(BagsTest, protectedAttributeNotOverlaid) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(bags_arsc, bags_arsc_len, mData, mDataSize));
+
+ ResTable::Theme theme(mTargetTable);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(app::R::style::Theme_Two));
+ Res_value val;
+ ASSERT_GE(theme.getAttribute(android::R::attr::windowNoTitle, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_BOOLEAN, val.dataType);
+ ASSERT_NE(0, val.data);
+}
+
+}
diff --git a/libs/androidfw/tests/ThemesIdmap_test.cpp b/libs/androidfw/tests/ThemesIdmap_test.cpp
new file mode 100644
index 0000000..50f16c8
--- /dev/null
+++ b/libs/androidfw/tests/ThemesIdmap_test.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/ResourceTypes.h>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include "TestHelpers.h"
+#include "data/cm/basic/R.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+namespace {
+
+/**
+ * Include a binary resource table.
+ *
+ * Package: com.android.test.basic
+ */
+#include "data/cm/basic/basic_arsc.h"
+
+/**
+ * Include a binary resource table.
+ * This table is an overlay.
+ *
+ * Package: com.android.test.basic
+ */
+#include "data/cm/overlay/overlay_arsc.h"
+
+enum { MAY_NOT_BE_BAG = false };
+
+class IdmapTest : public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(basic_arsc, basic_arsc_len));
+ ASSERT_EQ(NO_ERROR, mOverlayTable.add(overlay_arsc, overlay_arsc_len));
+ char targetName[256] = "com.android.test.basic";
+ ASSERT_EQ(NO_ERROR, mTargetTable.createIdmap(mOverlayTable, 0, 0, 0, 0,
+ targetName, targetName, &mData, &mDataSize));
+ }
+
+ virtual void TearDown() {
+ free(mData);
+ }
+
+ ResTable mTargetTable;
+ ResTable mOverlayTable;
+ void* mData;
+ size_t mDataSize;
+};
+
+TEST_F(IdmapTest, canLoadIdmap) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+}
+
+TEST_F(IdmapTest, overlayOverridesResourceValue) {
+ Res_value val;
+ ssize_t block = mTargetTable.getResource(base::R::dimen::dimen1, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_DIMENSION, val.dataType);
+ ASSERT_NE(val.data, 0);
+
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+
+ Res_value newVal;
+ ssize_t newBlock = mTargetTable.getResource(base::R::dimen::dimen1, &newVal, false);
+ ASSERT_GE(newBlock, 0);
+ ASSERT_NE(block, newBlock);
+ ASSERT_EQ(Res_value::TYPE_DIMENSION, newVal.dataType);
+ ASSERT_NE(val.data, newVal.data);
+}
+
+TEST_F(IdmapTest, overlaidResourceHasSameName) {
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+
+ ResTable::resource_name resName;
+ ASSERT_TRUE(mTargetTable.getResourceName(base::R::drawable::drawable1, false, &resName));
+
+ ASSERT_TRUE(resName.package != NULL);
+ ASSERT_TRUE(resName.type != NULL);
+ ASSERT_TRUE(resName.name != NULL);
+
+ EXPECT_EQ(String16("com.android.test.basic"), String16(resName.package, resName.packageLen));
+ EXPECT_EQ(String16("drawable"), String16(resName.type, resName.typeLen));
+ EXPECT_EQ(String16("drawable1"), String16(resName.name, resName.nameLen));
+}
+
+TEST_F(IdmapTest, overlayDoesNotOverlayStringResource) {
+ Res_value val;
+ ssize_t block = mTargetTable.getResource(base::R::string::test2, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ const ResStringPool* pool = mTargetTable.getTableStringBlock(block);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
+
+ size_t strLen;
+ const char16_t* targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("test2"), String16(targetStr16, strLen));
+
+ ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+
+ ssize_t newBlock = mTargetTable.getResource(base::R::string::test2, &val, false);
+ ASSERT_GE(newBlock, 0);
+ ASSERT_EQ(block, newBlock);
+ // the above check should be enough but just to be sure we'll check the string
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ pool = mTargetTable.getTableStringBlock(newBlock);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
+
+ targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("test2"), String16(targetStr16, strLen));
+}
+
+} // namespace
diff --git a/libs/androidfw/tests/data/app/R.h b/libs/androidfw/tests/data/app/R.h
index 23e68e3..dfae98e 100644
--- a/libs/androidfw/tests/data/app/R.h
+++ b/libs/androidfw/tests/data/app/R.h
@@ -29,6 +29,15 @@ namespace attr {
namespace style {
enum {
Theme_One = 0x7f020000, // default
+ Theme_Two = 0x7f020001, // default
+ Theme_Three = 0x7f020002, // default
+ Theme_Four = 0x7f020003, // default
+ };
+}
+
+namespace color {
+ enum {
+ app_color = 0x7f030000, // default
};
}
diff --git a/libs/androidfw/tests/data/app/app_arsc.h b/libs/androidfw/tests/data/app/app_arsc.h
index d5d9a3b..be8a79a 100644
--- a/libs/androidfw/tests/data/app/app_arsc.h
+++ b/libs/androidfw/tests/data/app/app_arsc.h
@@ -1,8 +1,8 @@
unsigned char app_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x0c, 0x00, 0x18, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x9c, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf0, 0x03, 0x00, 0x00,
0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
0x64, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00,
@@ -25,38 +25,67 @@ unsigned char app_arsc[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6e, 0x00,
- 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x26, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x4f, 0x00,
+ 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00, 0x77, 0x00,
+ 0x6f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00, 0x68, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x46, 0x00, 0x6f, 0x00,
+ 0x75, 0x00, 0x72, 0x00, 0x00, 0x00, 0x09, 0x00, 0x61, 0x00, 0x70, 0x00,
+ 0x70, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f,
+ 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x05,
+ 0x01, 0x30, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d,
+ 0xff, 0xff, 0xff, 0xff
};
-unsigned int app_arsc_len = 708;
+unsigned int app_arsc_len = 1048;
diff --git a/libs/androidfw/tests/data/app/res/values/values.xml b/libs/androidfw/tests/data/app/res/values/values.xml
index c1cf64c..a31e65b 100644
--- a/libs/androidfw/tests/data/app/res/values/values.xml
+++ b/libs/androidfw/tests/data/app/res/values/values.xml
@@ -16,7 +16,22 @@
<resources>
<attr name="number" format="integer"/>
+
<style name="Theme.One" parent="@android:style/Theme.One">
<item name="number">1</item>
</style>
+
+ <style name="Theme.Two" parent="@android:style/Theme.One">
+ <item name="number">2</item>
+ </style>
+
+ <style name="Theme.Three" parent="@android:style/Theme.One">
+ <item name="number">3</item>
+ </style>
+
+ <style name="Theme.Four" parent="@android:style/Theme.One">
+ <item name="android:someDimen">48dp</item>
+ </style>
+
+ <color name="app_color">#ffffff</color>
</resources>
diff --git a/libs/androidfw/tests/data/bags/AndroidManifest.xml b/libs/androidfw/tests/data/bags/AndroidManifest.xml
new file mode 100644
index 0000000..69cf30a
--- /dev/null
+++ b/libs/androidfw/tests/data/bags/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.bags">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/bags/R.h b/libs/androidfw/tests/data/bags/R.h
new file mode 100644
index 0000000..bdb9254
--- /dev/null
+++ b/libs/androidfw/tests/data/bags/R.h
@@ -0,0 +1,26 @@
+#ifndef __BAGS_R_H
+#define __BAGS_R_H
+
+namespace bags {
+namespace R {
+
+namespace style {
+ enum {
+ Theme_Two = 0x61020000, // default
+ Theme_Three = 0x61020001, // default
+ Overlay = 0x61020002, // default
+ };
+}
+
+namespace color {
+ enum {
+ app_color = 0x61030000, // default
+ magenta = 0x61030001, // default
+ cyan = 0x61030002, // default
+ };
+}
+
+} // namespace R
+} // namespace bags
+
+#endif // __BAGS_R_H
diff --git a/libs/androidfw/tests/data/bags/bags_arsc.h b/libs/androidfw/tests/data/bags/bags_arsc.h
new file mode 100644
index 0000000..324cd9c
--- /dev/null
+++ b/libs/androidfw/tests/data/bags/bags_arsc.h
@@ -0,0 +1,88 @@
+unsigned char bags_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xd4, 0x03, 0x00, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x67, 0x00, 0x73, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00,
+ 0x77, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4f, 0x00,
+ 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x2e, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x5f, 0x00,
+ 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00,
+ 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x04, 0x00, 0x63, 0x00, 0x79, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+ 0xd0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0xff, 0x00, 0x00, 0xff,
+ 0x01, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x61,
+ 0x56, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x61,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x61, 0x10, 0x00, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0xcc, 0xbb, 0xaa, 0xff,
+ 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d,
+ 0x00, 0x00, 0x00, 0xff, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x1d, 0xff, 0x00, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d, 0xff, 0xff, 0x00, 0xff
+};
+unsigned int bags_arsc_len = 1020;
diff --git a/libs/androidfw/tests/data/bags/build b/libs/androidfw/tests/data/bags/build
new file mode 100755
index 0000000..9047b18
--- /dev/null
+++ b/libs/androidfw/tests/data/bags/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -M AndroidManifest.xml -I ../system/bundle.apk -S res -x 97 -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc bags.arsc && \
+xxd -i bags.arsc > bags_arsc.h
diff --git a/libs/androidfw/tests/data/bags/res/values/values.xml b/libs/androidfw/tests/data/bags/res/values/values.xml
new file mode 100644
index 0000000..32bcf74
--- /dev/null
+++ b/libs/androidfw/tests/data/bags/res/values/values.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="Theme.Two" parent="@android:style/Theme.One">
+ <item name="android:background">#0000ff</item>
+ <item name="android:foreground">@color/magenta</item>
+ <item name="android:windowNoTitle">false</item>
+ </style>
+
+ <style name="Theme.Three" parent="@style/Overlay"/>
+
+ <style name="Overlay" parent="@android:style/Theme.One">
+ <item name="android:foreground">@color/cyan</item>
+ </style>
+
+ <style name="Theme.Four" parent="@android:style/Theme.One">
+ <item name="android:background">#aabbcc</item>
+ </style>
+
+ <color name="app_color">#000000</color>
+ <color name="magenta">#ff00ff</color>
+ <color name="cyan">#00ffff</color>
+
+</resources>
diff --git a/libs/androidfw/tests/data/basic/res/drawable/drawable1.png b/libs/androidfw/tests/data/basic/res/drawable/drawable1.png
new file mode 100644
index 0000000..94660d3
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/res/drawable/drawable1.png
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index a010cca..cc41f9b 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -38,4 +38,7 @@
<item>2</item>
<item>3</item>
</integer-array>
+
+ <dimen name="dimen1">48dp</dimen>
+ <dimen name="dimen2">16px</dimen>
</resources>
diff --git a/libs/androidfw/tests/data/cm/app/AndroidManifest.xml b/libs/androidfw/tests/data/cm/app/AndroidManifest.xml
new file mode 100644
index 0000000..bfa3a39
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/app/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.app">
+</manifest>
diff --git a/libs/androidfw/tests/data/cm/app/R.h b/libs/androidfw/tests/data/cm/app/R.h
new file mode 100644
index 0000000..fd91728
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/app/R.h
@@ -0,0 +1,31 @@
+#ifndef __APP_R_H
+#define __APP_R_H
+
+namespace app {
+namespace R {
+
+namespace attr {
+ enum {
+ number = 0x7f010000, // default
+ };
+}
+
+namespace style {
+ enum {
+ Theme_One = 0x7f020000, // default
+ Theme_Two = 0x7f020001, // default
+ Theme_Three = 0x7f020002, // default
+ Theme_Four = 0x7f020003, // default
+ };
+}
+
+namespace color {
+ enum {
+ app_color = 0x7f030000, // default
+ };
+}
+
+} // namespace R
+} // namespace app
+
+#endif // __APP_R_H
diff --git a/libs/androidfw/tests/data/cm/app/app_arsc.h b/libs/androidfw/tests/data/cm/app/app_arsc.h
new file mode 100644
index 0000000..be8a79a
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/app/app_arsc.h
@@ -0,0 +1,91 @@
+unsigned char app_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x18, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf0, 0x03, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x26, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x4f, 0x00,
+ 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00, 0x77, 0x00,
+ 0x6f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00, 0x68, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x46, 0x00, 0x6f, 0x00,
+ 0x75, 0x00, 0x72, 0x00, 0x00, 0x00, 0x09, 0x00, 0x61, 0x00, 0x70, 0x00,
+ 0x70, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f,
+ 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x05,
+ 0x01, 0x30, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d,
+ 0xff, 0xff, 0xff, 0xff
+};
+unsigned int app_arsc_len = 1048;
diff --git a/libs/androidfw/tests/data/cm/app/build b/libs/androidfw/tests/data/cm/app/build
new file mode 100755
index 0000000..89c4641
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/app/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -v -I ../system/bundle.apk -M AndroidManifest.xml -S res -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc app.arsc && \
+xxd -i app.arsc > app_arsc.h
diff --git a/libs/androidfw/tests/data/cm/app/res/values/values.xml b/libs/androidfw/tests/data/cm/app/res/values/values.xml
new file mode 100644
index 0000000..6f11070
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/app/res/values/values.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <attr name="number" format="integer"/>
+
+ <style name="Theme.One" parent="@android:style/Theme.One">
+ <item name="number">1</item>
+ </style>
+
+ <style name="Theme.Two" parent="@android:style/Theme.One">
+ <item name="number">2</item>
+ </style>
+
+ <style name="Theme.Three" parent="@android:style/Theme.One">
+ <item name="number">3</item>
+ </style>
+
+ <style name="Theme.Four" parent="@android:style/Theme.One">
+ <item name="android:someDimen">48dp</item>
+ </style>
+
+ <color name="app_color">#ffffff</color>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/bags/AndroidManifest.xml b/libs/androidfw/tests/data/cm/bags/AndroidManifest.xml
new file mode 100644
index 0000000..69cf30a
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/bags/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.bags">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/cm/bags/R.h b/libs/androidfw/tests/data/cm/bags/R.h
new file mode 100644
index 0000000..bdb9254
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/bags/R.h
@@ -0,0 +1,26 @@
+#ifndef __BAGS_R_H
+#define __BAGS_R_H
+
+namespace bags {
+namespace R {
+
+namespace style {
+ enum {
+ Theme_Two = 0x61020000, // default
+ Theme_Three = 0x61020001, // default
+ Overlay = 0x61020002, // default
+ };
+}
+
+namespace color {
+ enum {
+ app_color = 0x61030000, // default
+ magenta = 0x61030001, // default
+ cyan = 0x61030002, // default
+ };
+}
+
+} // namespace R
+} // namespace bags
+
+#endif // __BAGS_R_H
diff --git a/libs/androidfw/tests/data/cm/bags/bags_arsc.h b/libs/androidfw/tests/data/cm/bags/bags_arsc.h
new file mode 100644
index 0000000..324cd9c
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/bags/bags_arsc.h
@@ -0,0 +1,88 @@
+unsigned char bags_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xd4, 0x03, 0x00, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x67, 0x00, 0x73, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00,
+ 0x77, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4f, 0x00,
+ 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x2e, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x5f, 0x00,
+ 0x63, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00,
+ 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x04, 0x00, 0x63, 0x00, 0x79, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+ 0xd0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x44, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0xff, 0x00, 0x00, 0xff,
+ 0x01, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x61,
+ 0x56, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x61,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x61, 0x10, 0x00, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0xcc, 0xbb, 0xaa, 0xff,
+ 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d,
+ 0x00, 0x00, 0x00, 0xff, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x1d, 0xff, 0x00, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d, 0xff, 0xff, 0x00, 0xff
+};
+unsigned int bags_arsc_len = 1020;
diff --git a/libs/androidfw/tests/data/cm/bags/build b/libs/androidfw/tests/data/cm/bags/build
new file mode 100755
index 0000000..9047b18
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/bags/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -M AndroidManifest.xml -I ../system/bundle.apk -S res -x 97 -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc bags.arsc && \
+xxd -i bags.arsc > bags_arsc.h
diff --git a/libs/androidfw/tests/data/cm/bags/res/values/values.xml b/libs/androidfw/tests/data/cm/bags/res/values/values.xml
new file mode 100644
index 0000000..32bcf74
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/bags/res/values/values.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="Theme.Two" parent="@android:style/Theme.One">
+ <item name="android:background">#0000ff</item>
+ <item name="android:foreground">@color/magenta</item>
+ <item name="android:windowNoTitle">false</item>
+ </style>
+
+ <style name="Theme.Three" parent="@style/Overlay"/>
+
+ <style name="Overlay" parent="@android:style/Theme.One">
+ <item name="android:foreground">@color/cyan</item>
+ </style>
+
+ <style name="Theme.Four" parent="@android:style/Theme.One">
+ <item name="android:background">#aabbcc</item>
+ </style>
+
+ <color name="app_color">#000000</color>
+ <color name="magenta">#ff00ff</color>
+ <color name="cyan">#00ffff</color>
+
+</resources>
diff --git a/libs/androidfw/tests/data/cm/basic/AndroidManifest.xml b/libs/androidfw/tests/data/cm/basic/AndroidManifest.xml
new file mode 100644
index 0000000..a56ac18
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.basic">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/cm/basic/R.h b/libs/androidfw/tests/data/cm/basic/R.h
new file mode 100644
index 0000000..36bb1de
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/R.h
@@ -0,0 +1,68 @@
+#ifndef __BASE_R_H
+#define __BASE_R_H
+
+namespace base {
+namespace R {
+
+namespace attr {
+ enum {
+ attr1 = 0x7f010000, // default
+ attr2 = 0x7f010001, // default
+ };
+}
+
+namespace drawable {
+ enum {
+ drawable1 = 0x7f020000, // default
+ };
+}
+
+namespace layout {
+ enum {
+ main = 0x7f030000, // default, fr-sw600dp-v13
+ };
+}
+
+namespace string {
+ enum {
+ test1 = 0x7f040000, // default
+ test2 = 0x7f040001, // default
+
+ test3 = 0x7f0a0000, // default (in feature)
+ test4 = 0x7f0a0001, // default (in feature)
+ };
+}
+
+namespace integer {
+ enum {
+ number1 = 0x7f050000, // default, sv
+ number2 = 0x7f050001, // default
+
+ test3 = 0x7f0b0000, // default (in feature)
+ };
+}
+
+namespace style {
+ enum {
+ Theme1 = 0x7f060000, // default
+ Theme2 = 0x7f060001, // default
+ };
+}
+
+namespace array {
+ enum {
+ integerArray1 = 0x7f070000, // default
+ };
+}
+
+namespace dimen {
+ enum {
+ dimen1 = 0x7f080000, // default
+ dimen2 = 0x7f080001, // default
+ };
+}
+
+} // namespace R
+} // namespace base
+
+#endif // __BASE_R_H
diff --git a/libs/androidfw/tests/data/cm/basic/basic_arsc.h b/libs/androidfw/tests/data/cm/basic/basic_arsc.h
new file mode 100644
index 0000000..370c77c
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/basic_arsc.h
@@ -0,0 +1,194 @@
+unsigned char basic_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0xf4, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x62, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00,
+ 0x1a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x64, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00, 0x77, 0x00,
+ 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x31, 0x00, 0x2e, 0x00,
+ 0x70, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x13, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x2f, 0x00, 0x6d, 0x00, 0x61, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00,
+ 0x00, 0x00, 0x22, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00,
+ 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,
+ 0x2d, 0x00, 0x66, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x73, 0x00, 0x77, 0x00,
+ 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x64, 0x00, 0x70, 0x00, 0x2d, 0x00,
+ 0x76, 0x00, 0x31, 0x00, 0x33, 0x00, 0x2f, 0x00, 0x6d, 0x00, 0x61, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
+ 0xf0, 0x07, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+ 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
+ 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
+ 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
+ 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0xb8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x08, 0x00, 0x64, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
+ 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x64, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
+ 0xbc, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00,
+ 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x31, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x54, 0x00, 0x68, 0x00,
+ 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
+ 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x64, 0x00,
+ 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f, 0x01, 0x02, 0x44, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x90, 0x01, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f,
+ 0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f,
+ 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x7f, 0x10, 0x00, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x05, 0x01, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00
+};
+unsigned int basic_arsc_len = 2292;
diff --git a/libs/androidfw/tests/data/cm/basic/build b/libs/androidfw/tests/data/cm/basic/build
new file mode 100755
index 0000000..036e468
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/build
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
+
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split fr,de -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc basic.arsc && \
+xxd -i basic.arsc > basic_arsc.h && \
+unzip bundle_de_fr.apk resources.arsc && \
+mv resources.arsc split_de_fr.arsc && \
+xxd -i split_de_fr.arsc > split_de_fr_arsc.h
diff --git a/libs/androidfw/tests/data/cm/basic/res/drawable/drawable1.png b/libs/androidfw/tests/data/cm/basic/res/drawable/drawable1.png
new file mode 100644
index 0000000..94660d3
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/drawable/drawable1.png
Binary files differ
diff --git a/libs/androidfw/tests/data/cm/basic/res/layout-fr-sw600dp/main.xml b/libs/androidfw/tests/data/cm/basic/res/layout-fr-sw600dp/main.xml
new file mode 100644
index 0000000..05ffd58
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/layout-fr-sw600dp/main.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge>
+</merge>
diff --git a/libs/androidfw/tests/data/cm/basic/res/layout/main.xml b/libs/androidfw/tests/data/cm/basic/res/layout/main.xml
new file mode 100644
index 0000000..05ffd58
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/layout/main.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge>
+</merge>
diff --git a/libs/androidfw/tests/data/cm/basic/res/values-de/values.xml b/libs/androidfw/tests/data/cm/basic/res/values-de/values.xml
new file mode 100644
index 0000000..103c6a3
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/values-de/values.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="test1">versuch 1</string>
+ <string name="test2">versuch 2</string>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/basic/res/values-fr/values.xml b/libs/androidfw/tests/data/cm/basic/res/values-fr/values.xml
new file mode 100644
index 0000000..1806a2d
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/values-fr/values.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="test1">essai 1</string>
+ <string name="test2">essai 2</string>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/basic/res/values-sv/values.xml b/libs/androidfw/tests/data/cm/basic/res/values-sv/values.xml
new file mode 100644
index 0000000..9d52307
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/values-sv/values.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="number1">400</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/basic/res/values/values.xml b/libs/androidfw/tests/data/cm/basic/res/values/values.xml
new file mode 100644
index 0000000..0d22a4c
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/res/values/values.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <attr name="attr1" format="reference|integer" />
+ <attr name="attr2" format="reference|integer" />
+
+ <string name="test1">test1</string>
+ <string name="test2">test2</string>
+
+ <integer name="number1">200</integer>
+ <integer name="number2">@array/integerArray1</integer>
+
+ <style name="Theme1">
+ <item name="com.android.test.basic:attr1">100</item>
+ <item name="com.android.test.basic:attr2">@integer/number1</item>
+ </style>
+
+ <style name="Theme2" parent="@com.android.test.basic:style/Theme1">
+ <item name="com.android.test.basic:attr1">300</item>
+ </style>
+
+ <integer-array name="integerArray1">
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </integer-array>
+
+ <dimen name="dimen1">48dp</dimen>
+ <dimen name="dimen2">16px</dimen>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/cm/basic/split_de_fr_arsc.h
new file mode 100644
index 0000000..23cb3b7
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/basic/split_de_fr_arsc.h
@@ -0,0 +1,92 @@
+unsigned char split_de_fr_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x2c, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x76, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00,
+ 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x09, 0x00, 0x76, 0x00, 0x65, 0x00,
+ 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00,
+ 0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xa4, 0x03, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0xb8, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x08, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
+ 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00,
+ 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+unsigned int split_de_fr_arsc_len = 1068;
diff --git a/libs/androidfw/tests/data/cm/overlay/AndroidManifest.xml b/libs/androidfw/tests/data/cm/overlay/AndroidManifest.xml
new file mode 100644
index 0000000..a56ac18
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.basic">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/cm/overlay/build b/libs/androidfw/tests/data/cm/overlay/build
new file mode 100755
index 0000000..87cf6de
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/overlay/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc overlay.arsc && \
+xxd -i overlay.arsc > overlay_arsc.h
diff --git a/libs/androidfw/tests/data/cm/overlay/overlay_arsc.h b/libs/androidfw/tests/data/cm/overlay/overlay_arsc.h
new file mode 100644
index 0000000..2d59417
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/overlay/overlay_arsc.h
@@ -0,0 +1,103 @@
+unsigned char overlay_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0xa8, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x1a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x64, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00, 0x77, 0x00,
+ 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x31, 0x00, 0x2e, 0x00,
+ 0x70, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x74, 0x00,
+ 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x6f, 0x00,
+ 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x20, 0x04, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
+ 0x2e, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00,
+ 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x3e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x08, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00,
+ 0x67, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x09, 0x00, 0x64, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
+ 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00,
+ 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00,
+ 0x6e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x0b, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x02, 0x38, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05,
+ 0x01, 0x0c, 0x00, 0x00
+};
+unsigned int overlay_arsc_len = 1192;
diff --git a/libs/androidfw/tests/data/cm/overlay/res/drawable/drawable1.png b/libs/androidfw/tests/data/cm/overlay/res/drawable/drawable1.png
new file mode 100644
index 0000000..a7045ed
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/overlay/res/drawable/drawable1.png
Binary files differ
diff --git a/libs/androidfw/tests/data/cm/overlay/res/values/values.xml b/libs/androidfw/tests/data/cm/overlay/res/values/values.xml
new file mode 100644
index 0000000..5bf0427
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/overlay/res/values/values.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="test2">test2-overlay</string>
+ <integer-array name="integerArray1">
+ <item>10</item>
+ <item>11</item>
+ </integer-array>
+
+ <dimen name="dimen1">56sp</dimen>
+ <dimen name="dimen2">12dp</dimen>
+
+</resources>
diff --git a/libs/androidfw/tests/data/cm/override/AndroidManifest.xml b/libs/androidfw/tests/data/cm/override/AndroidManifest.xml
new file mode 100644
index 0000000..ed26054
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/override/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.override">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/cm/override/R.h b/libs/androidfw/tests/data/cm/override/R.h
new file mode 100644
index 0000000..a57c6b1
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/override/R.h
@@ -0,0 +1,16 @@
+#ifndef __BASE_R_H
+#define __BASE_R_H
+
+namespace override {
+namespace R {
+
+namespace string {
+ enum {
+ string1 = 0x7f020000, // default
+ };
+}
+
+} // namespace R
+} // namespace base
+
+#endif // __BASE_R_H
diff --git a/libs/androidfw/tests/data/cm/override/build b/libs/androidfw/tests/data/cm/override/build
new file mode 100755
index 0000000..f6ba33d
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/override/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc override.arsc && \
+xxd -i override.arsc > override_arsc.h
diff --git a/libs/androidfw/tests/data/cm/override/override_arsc.h b/libs/androidfw/tests/data/cm/override/override_arsc.h
new file mode 100644
index 0000000..2598635
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/override/override_arsc.h
@@ -0,0 +1,53 @@
+unsigned char override_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x50, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x10, 0x02, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00
+};
+unsigned int override_arsc_len = 592;
diff --git a/libs/androidfw/tests/data/cm/override/res/values/values.xml b/libs/androidfw/tests/data/cm/override/res/values/values.xml
new file mode 100644
index 0000000..7b607ef
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/override/res/values/values.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="string1">string1</string>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/system/AndroidManifest.xml b/libs/androidfw/tests/data/cm/system/AndroidManifest.xml
new file mode 100644
index 0000000..af105ee
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/system/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+</manifest>
diff --git a/libs/androidfw/tests/data/cm/system/R.h b/libs/androidfw/tests/data/cm/system/R.h
new file mode 100644
index 0000000..ba83b89
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/system/R.h
@@ -0,0 +1,26 @@
+#ifndef __ANDROID_R_H
+#define __ANDROID_R_H
+
+namespace android {
+namespace R {
+
+namespace attr {
+ enum {
+ background = 0x01010000, // default
+ foreground = 0x01010001, // default
+ some_dimen = 0x01010002, // default
+ another_dimen = 0x01010003, // default
+ windowNoTitle = 0x01010056, // default
+ };
+}
+
+namespace style {
+ enum {
+ Theme_One = 0x01020000, // default
+ };
+}
+
+} // namespace R
+} // namespace android
+
+#endif // __ANDROID_R_H
diff --git a/libs/androidfw/tests/data/cm/system/build b/libs/androidfw/tests/data/cm/system/build
new file mode 100755
index 0000000..2a3ac0b
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/system/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -x -M AndroidManifest.xml -S res -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc system.arsc && \
+xxd -i system.arsc > system_arsc.h
diff --git a/libs/androidfw/tests/data/cm/system/res/values/filler.xml b/libs/androidfw/tests/data/cm/system/res/values/filler.xml
new file mode 100644
index 0000000..27af8dc
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/system/res/values/filler.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Filler so we can test the protected attribute "windowNoTitle" -->
+ <java-symbol name="dummyAttr04" type="attr" id="0x01010004" />
+ <java-symbol name="dummyAttr05" type="attr" id="0x01010005" />
+ <java-symbol name="dummyAttr06" type="attr" id="0x01010006" />
+ <java-symbol name="dummyAttr07" type="attr" id="0x01010007" />
+ <java-symbol name="dummyAttr08" type="attr" id="0x01010008" />
+ <java-symbol name="dummyAttr09" type="attr" id="0x01010009" />
+ <java-symbol name="dummyAttr0a" type="attr" id="0x0101000a" />
+ <java-symbol name="dummyAttr0b" type="attr" id="0x0101000b" />
+ <java-symbol name="dummyAttr0c" type="attr" id="0x0101000c" />
+ <java-symbol name="dummyAttr0d" type="attr" id="0x0101000d" />
+ <java-symbol name="dummyAttr0e" type="attr" id="0x0101000e" />
+ <java-symbol name="dummyAttr0f" type="attr" id="0x0101000f" />
+ <java-symbol name="dummyAttr10" type="attr" id="0x01010010" />
+ <java-symbol name="dummyAttr11" type="attr" id="0x01010011" />
+ <java-symbol name="dummyAttr12" type="attr" id="0x01010012" />
+ <java-symbol name="dummyAttr13" type="attr" id="0x01010013" />
+ <java-symbol name="dummyAttr14" type="attr" id="0x01010014" />
+ <java-symbol name="dummyAttr15" type="attr" id="0x01010015" />
+ <java-symbol name="dummyAttr16" type="attr" id="0x01010016" />
+ <java-symbol name="dummyAttr17" type="attr" id="0x01010017" />
+ <java-symbol name="dummyAttr18" type="attr" id="0x01010018" />
+ <java-symbol name="dummyAttr19" type="attr" id="0x01010019" />
+ <java-symbol name="dummyAttr1a" type="attr" id="0x0101001a" />
+ <java-symbol name="dummyAttr1b" type="attr" id="0x0101001b" />
+ <java-symbol name="dummyAttr1c" type="attr" id="0x0101001c" />
+ <java-symbol name="dummyAttr1d" type="attr" id="0x0101001d" />
+ <java-symbol name="dummyAttr1e" type="attr" id="0x0101001e" />
+ <java-symbol name="dummyAttr1f" type="attr" id="0x0101001f" />
+ <java-symbol name="dummyAttr20" type="attr" id="0x01010020" />
+ <java-symbol name="dummyAttr21" type="attr" id="0x01010021" />
+ <java-symbol name="dummyAttr22" type="attr" id="0x01010022" />
+ <java-symbol name="dummyAttr23" type="attr" id="0x01010023" />
+ <java-symbol name="dummyAttr24" type="attr" id="0x01010024" />
+ <java-symbol name="dummyAttr25" type="attr" id="0x01010025" />
+ <java-symbol name="dummyAttr26" type="attr" id="0x01010026" />
+ <java-symbol name="dummyAttr27" type="attr" id="0x01010027" />
+ <java-symbol name="dummyAttr28" type="attr" id="0x01010028" />
+ <java-symbol name="dummyAttr29" type="attr" id="0x01010029" />
+ <java-symbol name="dummyAttr2a" type="attr" id="0x0101002a" />
+ <java-symbol name="dummyAttr2b" type="attr" id="0x0101002b" />
+ <java-symbol name="dummyAttr2c" type="attr" id="0x0101002c" />
+ <java-symbol name="dummyAttr2d" type="attr" id="0x0101002d" />
+ <java-symbol name="dummyAttr2e" type="attr" id="0x0101002e" />
+ <java-symbol name="dummyAttr2f" type="attr" id="0x0101002f" />
+ <java-symbol name="dummyAttr30" type="attr" id="0x01010030" />
+ <java-symbol name="dummyAttr31" type="attr" id="0x01010031" />
+ <java-symbol name="dummyAttr32" type="attr" id="0x01010032" />
+ <java-symbol name="dummyAttr33" type="attr" id="0x01010033" />
+ <java-symbol name="dummyAttr34" type="attr" id="0x01010034" />
+ <java-symbol name="dummyAttr35" type="attr" id="0x01010035" />
+ <java-symbol name="dummyAttr36" type="attr" id="0x01010036" />
+ <java-symbol name="dummyAttr37" type="attr" id="0x01010037" />
+ <java-symbol name="dummyAttr38" type="attr" id="0x01010038" />
+ <java-symbol name="dummyAttr39" type="attr" id="0x01010039" />
+ <java-symbol name="dummyAttr3a" type="attr" id="0x0101003a" />
+ <java-symbol name="dummyAttr3b" type="attr" id="0x0101003b" />
+ <java-symbol name="dummyAttr3c" type="attr" id="0x0101003c" />
+ <java-symbol name="dummyAttr3d" type="attr" id="0x0101003d" />
+ <java-symbol name="dummyAttr3e" type="attr" id="0x0101003e" />
+ <java-symbol name="dummyAttr3f" type="attr" id="0x0101003f" />
+ <java-symbol name="dummyAttr40" type="attr" id="0x01010040" />
+ <java-symbol name="dummyAttr41" type="attr" id="0x01010041" />
+ <java-symbol name="dummyAttr42" type="attr" id="0x01010042" />
+ <java-symbol name="dummyAttr43" type="attr" id="0x01010043" />
+ <java-symbol name="dummyAttr44" type="attr" id="0x01010044" />
+ <java-symbol name="dummyAttr45" type="attr" id="0x01010045" />
+ <java-symbol name="dummyAttr46" type="attr" id="0x01010046" />
+ <java-symbol name="dummyAttr47" type="attr" id="0x01010047" />
+ <java-symbol name="dummyAttr48" type="attr" id="0x01010048" />
+ <java-symbol name="dummyAttr49" type="attr" id="0x01010049" />
+ <java-symbol name="dummyAttr4a" type="attr" id="0x0101004a" />
+ <java-symbol name="dummyAttr4b" type="attr" id="0x0101004b" />
+ <java-symbol name="dummyAttr4c" type="attr" id="0x0101004c" />
+ <java-symbol name="dummyAttr4d" type="attr" id="0x0101004d" />
+ <java-symbol name="dummyAttr4e" type="attr" id="0x0101004e" />
+ <java-symbol name="dummyAttr4f" type="attr" id="0x0101004f" />
+ <java-symbol name="dummyAttr50" type="attr" id="0x01010050" />
+ <java-symbol name="dummyAttr51" type="attr" id="0x01010051" />
+ <java-symbol name="dummyAttr52" type="attr" id="0x01010052" />
+ <java-symbol name="dummyAttr53" type="attr" id="0x01010053" />
+ <java-symbol name="dummyAttr54" type="attr" id="0x01010054" />
+ <java-symbol name="dummyAttr55" type="attr" id="0x01010055" />
+ <attr name="dummyAttr04" format="reference"/>
+ <attr name="dummyAttr05" format="reference"/>
+ <attr name="dummyAttr06" format="reference"/>
+ <attr name="dummyAttr07" format="reference"/>
+ <attr name="dummyAttr08" format="reference"/>
+ <attr name="dummyAttr09" format="reference"/>
+ <attr name="dummyAttr0a" format="reference"/>
+ <attr name="dummyAttr0b" format="reference"/>
+ <attr name="dummyAttr0c" format="reference"/>
+ <attr name="dummyAttr0d" format="reference"/>
+ <attr name="dummyAttr0e" format="reference"/>
+ <attr name="dummyAttr0f" format="reference"/>
+ <attr name="dummyAttr10" format="reference"/>
+ <attr name="dummyAttr11" format="reference"/>
+ <attr name="dummyAttr12" format="reference"/>
+ <attr name="dummyAttr13" format="reference"/>
+ <attr name="dummyAttr14" format="reference"/>
+ <attr name="dummyAttr15" format="reference"/>
+ <attr name="dummyAttr16" format="reference"/>
+ <attr name="dummyAttr17" format="reference"/>
+ <attr name="dummyAttr18" format="reference"/>
+ <attr name="dummyAttr19" format="reference"/>
+ <attr name="dummyAttr1a" format="reference"/>
+ <attr name="dummyAttr1b" format="reference"/>
+ <attr name="dummyAttr1c" format="reference"/>
+ <attr name="dummyAttr1d" format="reference"/>
+ <attr name="dummyAttr1e" format="reference"/>
+ <attr name="dummyAttr1f" format="reference"/>
+ <attr name="dummyAttr20" format="reference"/>
+ <attr name="dummyAttr21" format="reference"/>
+ <attr name="dummyAttr22" format="reference"/>
+ <attr name="dummyAttr23" format="reference"/>
+ <attr name="dummyAttr24" format="reference"/>
+ <attr name="dummyAttr25" format="reference"/>
+ <attr name="dummyAttr26" format="reference"/>
+ <attr name="dummyAttr27" format="reference"/>
+ <attr name="dummyAttr28" format="reference"/>
+ <attr name="dummyAttr29" format="reference"/>
+ <attr name="dummyAttr2a" format="reference"/>
+ <attr name="dummyAttr2b" format="reference"/>
+ <attr name="dummyAttr2c" format="reference"/>
+ <attr name="dummyAttr2d" format="reference"/>
+ <attr name="dummyAttr2e" format="reference"/>
+ <attr name="dummyAttr2f" format="reference"/>
+ <attr name="dummyAttr30" format="reference"/>
+ <attr name="dummyAttr31" format="reference"/>
+ <attr name="dummyAttr32" format="reference"/>
+ <attr name="dummyAttr33" format="reference"/>
+ <attr name="dummyAttr34" format="reference"/>
+ <attr name="dummyAttr35" format="reference"/>
+ <attr name="dummyAttr36" format="reference"/>
+ <attr name="dummyAttr37" format="reference"/>
+ <attr name="dummyAttr38" format="reference"/>
+ <attr name="dummyAttr39" format="reference"/>
+ <attr name="dummyAttr3a" format="reference"/>
+ <attr name="dummyAttr3b" format="reference"/>
+ <attr name="dummyAttr3c" format="reference"/>
+ <attr name="dummyAttr3d" format="reference"/>
+ <attr name="dummyAttr3e" format="reference"/>
+ <attr name="dummyAttr3f" format="reference"/>
+ <attr name="dummyAttr40" format="reference"/>
+ <attr name="dummyAttr41" format="reference"/>
+ <attr name="dummyAttr42" format="reference"/>
+ <attr name="dummyAttr43" format="reference"/>
+ <attr name="dummyAttr44" format="reference"/>
+ <attr name="dummyAttr45" format="reference"/>
+ <attr name="dummyAttr46" format="reference"/>
+ <attr name="dummyAttr47" format="reference"/>
+ <attr name="dummyAttr48" format="reference"/>
+ <attr name="dummyAttr49" format="reference"/>
+ <attr name="dummyAttr4a" format="reference"/>
+ <attr name="dummyAttr4b" format="reference"/>
+ <attr name="dummyAttr4c" format="reference"/>
+ <attr name="dummyAttr4d" format="reference"/>
+ <attr name="dummyAttr4e" format="reference"/>
+ <attr name="dummyAttr4f" format="reference"/>
+ <attr name="dummyAttr50" format="reference"/>
+ <attr name="dummyAttr51" format="reference"/>
+ <attr name="dummyAttr52" format="reference"/>
+ <attr name="dummyAttr53" format="reference"/>
+ <attr name="dummyAttr54" format="reference"/>
+ <attr name="dummyAttr55" format="reference"/>
+</resources> \ No newline at end of file
diff --git a/libs/androidfw/tests/data/cm/system/res/values/themes.xml b/libs/androidfw/tests/data/cm/system/res/values/themes.xml
new file mode 100644
index 0000000..c870b1e
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/system/res/values/themes.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <public name="background" type="attr" id="0x01010000"/>
+ <public name="foreground" type="attr" id="0x01010001"/>
+ <public name="someDimen" type="attr" id="0x01010002" />
+ <public name="anotherDimen" type="attr" id="0x01010003" />
+ <!-- attributes 0x01010004 to 0x01010055 are in filler.xml -->
+ <public name="windowNoTitle" type="attr" id="0x01010056" />
+ <public name="Theme.One" type="style" id="0x01020000"/>
+
+ <attr name="background" format="color|reference"/>
+ <attr name="foreground" format="color|reference"/>
+ <attr name="someDimen" format="dimension|reference"/>
+ <attr name="anotherDimen" format="dimension|reference"/>
+ <attr name="windowNoTitle" format="boolean|reference"/>
+ <style name="Theme.One" parent="">
+ <item name="android:background">#ff0000</item>
+ <item name="android:foreground">#000000</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+</resources>
diff --git a/libs/androidfw/tests/data/cm/system/system_arsc.h b/libs/androidfw/tests/data/cm/system/system_arsc.h
new file mode 100644
index 0000000..e157a0e
--- /dev/null
+++ b/libs/androidfw/tests/data/cm/system/system_arsc.h
@@ -0,0 +1,538 @@
+unsigned char system_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x10, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xe8, 0x18, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
+ 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
+ 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0x68, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x46, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x96, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00,
+ 0xe4, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00,
+ 0x32, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00,
+ 0xce, 0x01, 0x00, 0x00, 0xe8, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+ 0x1c, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00,
+ 0x6a, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x9e, 0x02, 0x00, 0x00,
+ 0xb8, 0x02, 0x00, 0x00, 0xd2, 0x02, 0x00, 0x00, 0xec, 0x02, 0x00, 0x00,
+ 0x06, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x3a, 0x03, 0x00, 0x00,
+ 0x54, 0x03, 0x00, 0x00, 0x6e, 0x03, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00,
+ 0xa2, 0x03, 0x00, 0x00, 0xbc, 0x03, 0x00, 0x00, 0xd6, 0x03, 0x00, 0x00,
+ 0xf0, 0x03, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x24, 0x04, 0x00, 0x00,
+ 0x3e, 0x04, 0x00, 0x00, 0x58, 0x04, 0x00, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x8c, 0x04, 0x00, 0x00, 0xa6, 0x04, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x00,
+ 0xda, 0x04, 0x00, 0x00, 0xf4, 0x04, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00,
+ 0x28, 0x05, 0x00, 0x00, 0x42, 0x05, 0x00, 0x00, 0x5c, 0x05, 0x00, 0x00,
+ 0x76, 0x05, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0xaa, 0x05, 0x00, 0x00,
+ 0xc4, 0x05, 0x00, 0x00, 0xde, 0x05, 0x00, 0x00, 0xf8, 0x05, 0x00, 0x00,
+ 0x12, 0x06, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x46, 0x06, 0x00, 0x00,
+ 0x60, 0x06, 0x00, 0x00, 0x7a, 0x06, 0x00, 0x00, 0x94, 0x06, 0x00, 0x00,
+ 0xae, 0x06, 0x00, 0x00, 0xc8, 0x06, 0x00, 0x00, 0xe2, 0x06, 0x00, 0x00,
+ 0xfc, 0x06, 0x00, 0x00, 0x16, 0x07, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00,
+ 0x4a, 0x07, 0x00, 0x00, 0x64, 0x07, 0x00, 0x00, 0x7e, 0x07, 0x00, 0x00,
+ 0x98, 0x07, 0x00, 0x00, 0xb2, 0x07, 0x00, 0x00, 0xcc, 0x07, 0x00, 0x00,
+ 0xe6, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00,
+ 0x34, 0x08, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00,
+ 0x82, 0x08, 0x00, 0x00, 0x9c, 0x08, 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00,
+ 0xd4, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x63, 0x00,
+ 0x6b, 0x00, 0x67, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x67, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x09, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x44, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x44, 0x00, 0x69, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x30, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x36, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x30, 0x00, 0x39, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x30, 0x00, 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x63, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x64, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x30, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x31, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x33, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x31, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x31, 0x00, 0x36, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x39, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x31, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x31, 0x00, 0x63, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x66, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x32, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x32, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x35, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x36, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x32, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x32, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x39, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x61, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x62, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x63, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x32, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x32, 0x00, 0x65, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x33, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x33, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x36, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x33, 0x00, 0x39, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x33, 0x00, 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x63, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x64, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x33, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x34, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x33, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x34, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x34, 0x00, 0x36, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x39, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x34, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x34, 0x00, 0x63, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x66, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x35, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x35, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x35, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x35, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x35, 0x00, 0x35, 0x00,
+ 0x00, 0x00, 0x0d, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00,
+ 0x6f, 0x00, 0x77, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x54, 0x00, 0x69, 0x00,
+ 0x74, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x4f, 0x00,
+ 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x6c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x01, 0x02, 0x44, 0x00, 0x24, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x57, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0xc4, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
+ 0x18, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00,
+ 0x6c, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00,
+ 0xc0, 0x01, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
+ 0x14, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00,
+ 0x68, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00,
+ 0xbc, 0x02, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00,
+ 0x10, 0x03, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00,
+ 0x64, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x9c, 0x03, 0x00, 0x00,
+ 0xb8, 0x03, 0x00, 0x00, 0xd4, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00,
+ 0x0c, 0x04, 0x00, 0x00, 0x28, 0x04, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00,
+ 0x60, 0x04, 0x00, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x98, 0x04, 0x00, 0x00,
+ 0xb4, 0x04, 0x00, 0x00, 0xd0, 0x04, 0x00, 0x00, 0xec, 0x04, 0x00, 0x00,
+ 0x08, 0x05, 0x00, 0x00, 0x24, 0x05, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00,
+ 0x5c, 0x05, 0x00, 0x00, 0x78, 0x05, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00,
+ 0xb0, 0x05, 0x00, 0x00, 0xcc, 0x05, 0x00, 0x00, 0xe8, 0x05, 0x00, 0x00,
+ 0x04, 0x06, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x3c, 0x06, 0x00, 0x00,
+ 0x58, 0x06, 0x00, 0x00, 0x74, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00,
+ 0xac, 0x06, 0x00, 0x00, 0xc8, 0x06, 0x00, 0x00, 0xe4, 0x06, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x1c, 0x07, 0x00, 0x00, 0x38, 0x07, 0x00, 0x00,
+ 0x54, 0x07, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0x8c, 0x07, 0x00, 0x00,
+ 0xa8, 0x07, 0x00, 0x00, 0xc4, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00,
+ 0xfc, 0x07, 0x00, 0x00, 0x18, 0x08, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00,
+ 0x50, 0x08, 0x00, 0x00, 0x6c, 0x08, 0x00, 0x00, 0x88, 0x08, 0x00, 0x00,
+ 0xa4, 0x08, 0x00, 0x00, 0xc0, 0x08, 0x00, 0x00, 0xdc, 0x08, 0x00, 0x00,
+ 0xf8, 0x08, 0x00, 0x00, 0x14, 0x09, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00,
+ 0x4c, 0x09, 0x00, 0x00, 0x68, 0x09, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x41, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x41, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x23, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x2f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x3b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x47, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x4d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x53, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x44, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x57, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0x56, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x12, 0xff, 0xff, 0xff, 0xff
+};
+unsigned int system_arsc_len = 6416;
diff --git a/libs/androidfw/tests/data/overlay/overlay_arsc.h b/libs/androidfw/tests/data/overlay/overlay_arsc.h
index 5bd98b2..2d59417 100644
--- a/libs/androidfw/tests/data/overlay/overlay_arsc.h
+++ b/libs/androidfw/tests/data/overlay/overlay_arsc.h
@@ -1,17 +1,22 @@
unsigned char overlay_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x74, 0x00,
+ 0x02, 0x00, 0x0c, 0x00, 0xa8, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x1a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x64, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00, 0x77, 0x00,
+ 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x31, 0x00, 0x2e, 0x00,
+ 0x70, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x74, 0x00,
0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x6f, 0x00,
0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xc4, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x20, 0x04, 0x00, 0x00,
0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2e, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00,
+ 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -28,21 +33,30 @@ unsigned char overlay_arsc[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x41, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x3e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x08, 0x00, 0x64, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00,
+ 0x67, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x09, 0x00, 0x64, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
+ 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00,
+ 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00,
+ 0x6e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -55,15 +69,35 @@ unsigned char overlay_arsc[] = {
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x0b, 0x00, 0x00, 0x00
+ 0x0b, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x02, 0x38, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05,
+ 0x01, 0x0c, 0x00, 0x00
};
-unsigned int overlay_arsc_len = 784;
+unsigned int overlay_arsc_len = 1192;
diff --git a/libs/androidfw/tests/data/overlay/res/drawable/drawable1.png b/libs/androidfw/tests/data/overlay/res/drawable/drawable1.png
new file mode 100644
index 0000000..a7045ed
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/res/drawable/drawable1.png
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/res/values/values.xml b/libs/androidfw/tests/data/overlay/res/values/values.xml
index 3e1af98..3fd4ae9 100644
--- a/libs/androidfw/tests/data/overlay/res/values/values.xml
+++ b/libs/androidfw/tests/data/overlay/res/values/values.xml
@@ -20,4 +20,8 @@
<item>10</item>
<item>11</item>
</integer-array>
+
+ <dimen name="dimen1">56sp</dimen>
+ <dimen name="dimen2">12dp</dimen>
+
</resources>
diff --git a/libs/androidfw/tests/data/override/AndroidManifest.xml b/libs/androidfw/tests/data/override/AndroidManifest.xml
new file mode 100644
index 0000000..ed26054
--- /dev/null
+++ b/libs/androidfw/tests/data/override/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.override">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/override/R.h b/libs/androidfw/tests/data/override/R.h
new file mode 100644
index 0000000..a57c6b1
--- /dev/null
+++ b/libs/androidfw/tests/data/override/R.h
@@ -0,0 +1,16 @@
+#ifndef __BASE_R_H
+#define __BASE_R_H
+
+namespace override {
+namespace R {
+
+namespace string {
+ enum {
+ string1 = 0x7f020000, // default
+ };
+}
+
+} // namespace R
+} // namespace base
+
+#endif // __BASE_R_H
diff --git a/libs/androidfw/tests/data/override/build b/libs/androidfw/tests/data/override/build
new file mode 100755
index 0000000..f6ba33d
--- /dev/null
+++ b/libs/androidfw/tests/data/override/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc override.arsc && \
+xxd -i override.arsc > override_arsc.h
diff --git a/libs/androidfw/tests/data/override/override_arsc.h b/libs/androidfw/tests/data/override/override_arsc.h
new file mode 100644
index 0000000..2598635
--- /dev/null
+++ b/libs/androidfw/tests/data/override/override_arsc.h
@@ -0,0 +1,53 @@
+unsigned char override_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x50, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x73, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x10, 0x02, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00
+};
+unsigned int override_arsc_len = 592;
diff --git a/libs/androidfw/tests/data/override/res/values/values.xml b/libs/androidfw/tests/data/override/res/values/values.xml
new file mode 100644
index 0000000..7b607ef
--- /dev/null
+++ b/libs/androidfw/tests/data/override/res/values/values.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="string1">string1</string>
+</resources>
diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h
index 27f25fe..0f96bda 100644
--- a/libs/androidfw/tests/data/system/R.h
+++ b/libs/androidfw/tests/data/system/R.h
@@ -22,8 +22,11 @@ namespace R {
namespace attr {
enum {
- background = 0x01010000, // default
- foreground = 0x01010001, // default
+ background = 0x01010000, // default
+ foreground = 0x01010001, // default
+ some_dimen = 0x01010002, // default
+ another_dimen = 0x01010003, // default
+ windowNoTitle = 0x01010056, // default
};
}
diff --git a/libs/androidfw/tests/data/system/res/values/filler.xml b/libs/androidfw/tests/data/system/res/values/filler.xml
new file mode 100644
index 0000000..27af8dc
--- /dev/null
+++ b/libs/androidfw/tests/data/system/res/values/filler.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Filler so we can test the protected attribute "windowNoTitle" -->
+ <java-symbol name="dummyAttr04" type="attr" id="0x01010004" />
+ <java-symbol name="dummyAttr05" type="attr" id="0x01010005" />
+ <java-symbol name="dummyAttr06" type="attr" id="0x01010006" />
+ <java-symbol name="dummyAttr07" type="attr" id="0x01010007" />
+ <java-symbol name="dummyAttr08" type="attr" id="0x01010008" />
+ <java-symbol name="dummyAttr09" type="attr" id="0x01010009" />
+ <java-symbol name="dummyAttr0a" type="attr" id="0x0101000a" />
+ <java-symbol name="dummyAttr0b" type="attr" id="0x0101000b" />
+ <java-symbol name="dummyAttr0c" type="attr" id="0x0101000c" />
+ <java-symbol name="dummyAttr0d" type="attr" id="0x0101000d" />
+ <java-symbol name="dummyAttr0e" type="attr" id="0x0101000e" />
+ <java-symbol name="dummyAttr0f" type="attr" id="0x0101000f" />
+ <java-symbol name="dummyAttr10" type="attr" id="0x01010010" />
+ <java-symbol name="dummyAttr11" type="attr" id="0x01010011" />
+ <java-symbol name="dummyAttr12" type="attr" id="0x01010012" />
+ <java-symbol name="dummyAttr13" type="attr" id="0x01010013" />
+ <java-symbol name="dummyAttr14" type="attr" id="0x01010014" />
+ <java-symbol name="dummyAttr15" type="attr" id="0x01010015" />
+ <java-symbol name="dummyAttr16" type="attr" id="0x01010016" />
+ <java-symbol name="dummyAttr17" type="attr" id="0x01010017" />
+ <java-symbol name="dummyAttr18" type="attr" id="0x01010018" />
+ <java-symbol name="dummyAttr19" type="attr" id="0x01010019" />
+ <java-symbol name="dummyAttr1a" type="attr" id="0x0101001a" />
+ <java-symbol name="dummyAttr1b" type="attr" id="0x0101001b" />
+ <java-symbol name="dummyAttr1c" type="attr" id="0x0101001c" />
+ <java-symbol name="dummyAttr1d" type="attr" id="0x0101001d" />
+ <java-symbol name="dummyAttr1e" type="attr" id="0x0101001e" />
+ <java-symbol name="dummyAttr1f" type="attr" id="0x0101001f" />
+ <java-symbol name="dummyAttr20" type="attr" id="0x01010020" />
+ <java-symbol name="dummyAttr21" type="attr" id="0x01010021" />
+ <java-symbol name="dummyAttr22" type="attr" id="0x01010022" />
+ <java-symbol name="dummyAttr23" type="attr" id="0x01010023" />
+ <java-symbol name="dummyAttr24" type="attr" id="0x01010024" />
+ <java-symbol name="dummyAttr25" type="attr" id="0x01010025" />
+ <java-symbol name="dummyAttr26" type="attr" id="0x01010026" />
+ <java-symbol name="dummyAttr27" type="attr" id="0x01010027" />
+ <java-symbol name="dummyAttr28" type="attr" id="0x01010028" />
+ <java-symbol name="dummyAttr29" type="attr" id="0x01010029" />
+ <java-symbol name="dummyAttr2a" type="attr" id="0x0101002a" />
+ <java-symbol name="dummyAttr2b" type="attr" id="0x0101002b" />
+ <java-symbol name="dummyAttr2c" type="attr" id="0x0101002c" />
+ <java-symbol name="dummyAttr2d" type="attr" id="0x0101002d" />
+ <java-symbol name="dummyAttr2e" type="attr" id="0x0101002e" />
+ <java-symbol name="dummyAttr2f" type="attr" id="0x0101002f" />
+ <java-symbol name="dummyAttr30" type="attr" id="0x01010030" />
+ <java-symbol name="dummyAttr31" type="attr" id="0x01010031" />
+ <java-symbol name="dummyAttr32" type="attr" id="0x01010032" />
+ <java-symbol name="dummyAttr33" type="attr" id="0x01010033" />
+ <java-symbol name="dummyAttr34" type="attr" id="0x01010034" />
+ <java-symbol name="dummyAttr35" type="attr" id="0x01010035" />
+ <java-symbol name="dummyAttr36" type="attr" id="0x01010036" />
+ <java-symbol name="dummyAttr37" type="attr" id="0x01010037" />
+ <java-symbol name="dummyAttr38" type="attr" id="0x01010038" />
+ <java-symbol name="dummyAttr39" type="attr" id="0x01010039" />
+ <java-symbol name="dummyAttr3a" type="attr" id="0x0101003a" />
+ <java-symbol name="dummyAttr3b" type="attr" id="0x0101003b" />
+ <java-symbol name="dummyAttr3c" type="attr" id="0x0101003c" />
+ <java-symbol name="dummyAttr3d" type="attr" id="0x0101003d" />
+ <java-symbol name="dummyAttr3e" type="attr" id="0x0101003e" />
+ <java-symbol name="dummyAttr3f" type="attr" id="0x0101003f" />
+ <java-symbol name="dummyAttr40" type="attr" id="0x01010040" />
+ <java-symbol name="dummyAttr41" type="attr" id="0x01010041" />
+ <java-symbol name="dummyAttr42" type="attr" id="0x01010042" />
+ <java-symbol name="dummyAttr43" type="attr" id="0x01010043" />
+ <java-symbol name="dummyAttr44" type="attr" id="0x01010044" />
+ <java-symbol name="dummyAttr45" type="attr" id="0x01010045" />
+ <java-symbol name="dummyAttr46" type="attr" id="0x01010046" />
+ <java-symbol name="dummyAttr47" type="attr" id="0x01010047" />
+ <java-symbol name="dummyAttr48" type="attr" id="0x01010048" />
+ <java-symbol name="dummyAttr49" type="attr" id="0x01010049" />
+ <java-symbol name="dummyAttr4a" type="attr" id="0x0101004a" />
+ <java-symbol name="dummyAttr4b" type="attr" id="0x0101004b" />
+ <java-symbol name="dummyAttr4c" type="attr" id="0x0101004c" />
+ <java-symbol name="dummyAttr4d" type="attr" id="0x0101004d" />
+ <java-symbol name="dummyAttr4e" type="attr" id="0x0101004e" />
+ <java-symbol name="dummyAttr4f" type="attr" id="0x0101004f" />
+ <java-symbol name="dummyAttr50" type="attr" id="0x01010050" />
+ <java-symbol name="dummyAttr51" type="attr" id="0x01010051" />
+ <java-symbol name="dummyAttr52" type="attr" id="0x01010052" />
+ <java-symbol name="dummyAttr53" type="attr" id="0x01010053" />
+ <java-symbol name="dummyAttr54" type="attr" id="0x01010054" />
+ <java-symbol name="dummyAttr55" type="attr" id="0x01010055" />
+ <attr name="dummyAttr04" format="reference"/>
+ <attr name="dummyAttr05" format="reference"/>
+ <attr name="dummyAttr06" format="reference"/>
+ <attr name="dummyAttr07" format="reference"/>
+ <attr name="dummyAttr08" format="reference"/>
+ <attr name="dummyAttr09" format="reference"/>
+ <attr name="dummyAttr0a" format="reference"/>
+ <attr name="dummyAttr0b" format="reference"/>
+ <attr name="dummyAttr0c" format="reference"/>
+ <attr name="dummyAttr0d" format="reference"/>
+ <attr name="dummyAttr0e" format="reference"/>
+ <attr name="dummyAttr0f" format="reference"/>
+ <attr name="dummyAttr10" format="reference"/>
+ <attr name="dummyAttr11" format="reference"/>
+ <attr name="dummyAttr12" format="reference"/>
+ <attr name="dummyAttr13" format="reference"/>
+ <attr name="dummyAttr14" format="reference"/>
+ <attr name="dummyAttr15" format="reference"/>
+ <attr name="dummyAttr16" format="reference"/>
+ <attr name="dummyAttr17" format="reference"/>
+ <attr name="dummyAttr18" format="reference"/>
+ <attr name="dummyAttr19" format="reference"/>
+ <attr name="dummyAttr1a" format="reference"/>
+ <attr name="dummyAttr1b" format="reference"/>
+ <attr name="dummyAttr1c" format="reference"/>
+ <attr name="dummyAttr1d" format="reference"/>
+ <attr name="dummyAttr1e" format="reference"/>
+ <attr name="dummyAttr1f" format="reference"/>
+ <attr name="dummyAttr20" format="reference"/>
+ <attr name="dummyAttr21" format="reference"/>
+ <attr name="dummyAttr22" format="reference"/>
+ <attr name="dummyAttr23" format="reference"/>
+ <attr name="dummyAttr24" format="reference"/>
+ <attr name="dummyAttr25" format="reference"/>
+ <attr name="dummyAttr26" format="reference"/>
+ <attr name="dummyAttr27" format="reference"/>
+ <attr name="dummyAttr28" format="reference"/>
+ <attr name="dummyAttr29" format="reference"/>
+ <attr name="dummyAttr2a" format="reference"/>
+ <attr name="dummyAttr2b" format="reference"/>
+ <attr name="dummyAttr2c" format="reference"/>
+ <attr name="dummyAttr2d" format="reference"/>
+ <attr name="dummyAttr2e" format="reference"/>
+ <attr name="dummyAttr2f" format="reference"/>
+ <attr name="dummyAttr30" format="reference"/>
+ <attr name="dummyAttr31" format="reference"/>
+ <attr name="dummyAttr32" format="reference"/>
+ <attr name="dummyAttr33" format="reference"/>
+ <attr name="dummyAttr34" format="reference"/>
+ <attr name="dummyAttr35" format="reference"/>
+ <attr name="dummyAttr36" format="reference"/>
+ <attr name="dummyAttr37" format="reference"/>
+ <attr name="dummyAttr38" format="reference"/>
+ <attr name="dummyAttr39" format="reference"/>
+ <attr name="dummyAttr3a" format="reference"/>
+ <attr name="dummyAttr3b" format="reference"/>
+ <attr name="dummyAttr3c" format="reference"/>
+ <attr name="dummyAttr3d" format="reference"/>
+ <attr name="dummyAttr3e" format="reference"/>
+ <attr name="dummyAttr3f" format="reference"/>
+ <attr name="dummyAttr40" format="reference"/>
+ <attr name="dummyAttr41" format="reference"/>
+ <attr name="dummyAttr42" format="reference"/>
+ <attr name="dummyAttr43" format="reference"/>
+ <attr name="dummyAttr44" format="reference"/>
+ <attr name="dummyAttr45" format="reference"/>
+ <attr name="dummyAttr46" format="reference"/>
+ <attr name="dummyAttr47" format="reference"/>
+ <attr name="dummyAttr48" format="reference"/>
+ <attr name="dummyAttr49" format="reference"/>
+ <attr name="dummyAttr4a" format="reference"/>
+ <attr name="dummyAttr4b" format="reference"/>
+ <attr name="dummyAttr4c" format="reference"/>
+ <attr name="dummyAttr4d" format="reference"/>
+ <attr name="dummyAttr4e" format="reference"/>
+ <attr name="dummyAttr4f" format="reference"/>
+ <attr name="dummyAttr50" format="reference"/>
+ <attr name="dummyAttr51" format="reference"/>
+ <attr name="dummyAttr52" format="reference"/>
+ <attr name="dummyAttr53" format="reference"/>
+ <attr name="dummyAttr54" format="reference"/>
+ <attr name="dummyAttr55" format="reference"/>
+</resources> \ No newline at end of file
diff --git a/libs/androidfw/tests/data/system/res/values/themes.xml b/libs/androidfw/tests/data/system/res/values/themes.xml
index 35d43c7..a426bd3 100644
--- a/libs/androidfw/tests/data/system/res/values/themes.xml
+++ b/libs/androidfw/tests/data/system/res/values/themes.xml
@@ -17,12 +17,20 @@
<resources>
<public name="background" type="attr" id="0x01010000"/>
<public name="foreground" type="attr" id="0x01010001"/>
+ <public name="someDimen" type="attr" id="0x01010002" />
+ <public name="anotherDimen" type="attr" id="0x01010003" />
+ <!-- attributes 0x01010004 to 0x01010055 are in filler.xml -->
+ <public name="windowNoTitle" type="attr" id="0x01010056" />
<public name="Theme.One" type="style" id="0x01020000"/>
<attr name="background" format="color|reference"/>
<attr name="foreground" format="color|reference"/>
+ <attr name="someDimen" format="dimension|reference"/>
+ <attr name="anotherDimen" format="dimension|reference"/>
+ <attr name="windowNoTitle" format="boolean|reference"/>
<style name="Theme.One" parent="">
<item name="android:background">#ff0000</item>
<item name="android:foreground">#000000</item>
+ <item name="android:windowNoTitle">true</item>
</style>
</resources>
diff --git a/libs/androidfw/tests/data/system/system_arsc.h b/libs/androidfw/tests/data/system/system_arsc.h
index 215ecae..e157a0e 100644
--- a/libs/androidfw/tests/data/system/system_arsc.h
+++ b/libs/androidfw/tests/data/system/system_arsc.h
@@ -1,8 +1,8 @@
unsigned char system_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x18, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x0c, 0x00, 0x10, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf0, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xe8, 0x18, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -25,45 +25,514 @@ unsigned char system_arsc[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x68, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x67, 0x00,
- 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40,
- 0x01, 0x02, 0x44, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x46, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x96, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00,
+ 0xe4, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00,
+ 0x32, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00,
+ 0xce, 0x01, 0x00, 0x00, 0xe8, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+ 0x1c, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00,
+ 0x6a, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x9e, 0x02, 0x00, 0x00,
+ 0xb8, 0x02, 0x00, 0x00, 0xd2, 0x02, 0x00, 0x00, 0xec, 0x02, 0x00, 0x00,
+ 0x06, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x3a, 0x03, 0x00, 0x00,
+ 0x54, 0x03, 0x00, 0x00, 0x6e, 0x03, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00,
+ 0xa2, 0x03, 0x00, 0x00, 0xbc, 0x03, 0x00, 0x00, 0xd6, 0x03, 0x00, 0x00,
+ 0xf0, 0x03, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x24, 0x04, 0x00, 0x00,
+ 0x3e, 0x04, 0x00, 0x00, 0x58, 0x04, 0x00, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x8c, 0x04, 0x00, 0x00, 0xa6, 0x04, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x00,
+ 0xda, 0x04, 0x00, 0x00, 0xf4, 0x04, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00,
+ 0x28, 0x05, 0x00, 0x00, 0x42, 0x05, 0x00, 0x00, 0x5c, 0x05, 0x00, 0x00,
+ 0x76, 0x05, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0xaa, 0x05, 0x00, 0x00,
+ 0xc4, 0x05, 0x00, 0x00, 0xde, 0x05, 0x00, 0x00, 0xf8, 0x05, 0x00, 0x00,
+ 0x12, 0x06, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x46, 0x06, 0x00, 0x00,
+ 0x60, 0x06, 0x00, 0x00, 0x7a, 0x06, 0x00, 0x00, 0x94, 0x06, 0x00, 0x00,
+ 0xae, 0x06, 0x00, 0x00, 0xc8, 0x06, 0x00, 0x00, 0xe2, 0x06, 0x00, 0x00,
+ 0xfc, 0x06, 0x00, 0x00, 0x16, 0x07, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00,
+ 0x4a, 0x07, 0x00, 0x00, 0x64, 0x07, 0x00, 0x00, 0x7e, 0x07, 0x00, 0x00,
+ 0x98, 0x07, 0x00, 0x00, 0xb2, 0x07, 0x00, 0x00, 0xcc, 0x07, 0x00, 0x00,
+ 0xe6, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00,
+ 0x34, 0x08, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00,
+ 0x82, 0x08, 0x00, 0x00, 0x9c, 0x08, 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00,
+ 0xd4, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x63, 0x00,
+ 0x6b, 0x00, 0x67, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x67, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x09, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x44, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x44, 0x00, 0x69, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x30, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x36, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x30, 0x00, 0x39, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x30, 0x00, 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x63, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00, 0x64, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x30, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x30, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x31, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x33, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x31, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x31, 0x00, 0x36, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x39, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x31, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x31, 0x00, 0x63, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x66, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x32, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x32, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x35, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x36, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x32, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x32, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x39, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x61, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x62, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x32, 0x00,
+ 0x63, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x32, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x32, 0x00, 0x65, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x33, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x33, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x36, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x33, 0x00, 0x39, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x33, 0x00, 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x63, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00, 0x64, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x33, 0x00,
+ 0x65, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x33, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x34, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x33, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x34, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x34, 0x00, 0x36, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x39, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00,
+ 0x61, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x34, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x34, 0x00, 0x63, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x34, 0x00, 0x66, 0x00,
+ 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00,
+ 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x35, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x35, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00,
+ 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x35, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x64, 0x00,
+ 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00, 0x74, 0x00,
+ 0x74, 0x00, 0x72, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x41, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x35, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00,
+ 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x35, 0x00, 0x35, 0x00,
+ 0x00, 0x00, 0x0d, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00,
+ 0x6f, 0x00, 0x77, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x54, 0x00, 0x69, 0x00,
+ 0x74, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x09, 0x00, 0x54, 0x00,
+ 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x4f, 0x00,
+ 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x6c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x01, 0x02, 0x44, 0x00, 0x24, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x57, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0xc4, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
+ 0x18, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00,
+ 0x6c, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00,
+ 0xc0, 0x01, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
+ 0x14, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00,
+ 0x68, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00,
+ 0xbc, 0x02, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00,
+ 0x10, 0x03, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00,
+ 0x64, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x9c, 0x03, 0x00, 0x00,
+ 0xb8, 0x03, 0x00, 0x00, 0xd4, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00,
+ 0x0c, 0x04, 0x00, 0x00, 0x28, 0x04, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00,
+ 0x60, 0x04, 0x00, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x98, 0x04, 0x00, 0x00,
+ 0xb4, 0x04, 0x00, 0x00, 0xd0, 0x04, 0x00, 0x00, 0xec, 0x04, 0x00, 0x00,
+ 0x08, 0x05, 0x00, 0x00, 0x24, 0x05, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00,
+ 0x5c, 0x05, 0x00, 0x00, 0x78, 0x05, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00,
+ 0xb0, 0x05, 0x00, 0x00, 0xcc, 0x05, 0x00, 0x00, 0xe8, 0x05, 0x00, 0x00,
+ 0x04, 0x06, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x3c, 0x06, 0x00, 0x00,
+ 0x58, 0x06, 0x00, 0x00, 0x74, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00,
+ 0xac, 0x06, 0x00, 0x00, 0xc8, 0x06, 0x00, 0x00, 0xe4, 0x06, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x1c, 0x07, 0x00, 0x00, 0x38, 0x07, 0x00, 0x00,
+ 0x54, 0x07, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0x8c, 0x07, 0x00, 0x00,
+ 0xa8, 0x07, 0x00, 0x00, 0xc4, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00,
+ 0xfc, 0x07, 0x00, 0x00, 0x18, 0x08, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00,
+ 0x50, 0x08, 0x00, 0x00, 0x6c, 0x08, 0x00, 0x00, 0x88, 0x08, 0x00, 0x00,
+ 0xa4, 0x08, 0x00, 0x00, 0xc0, 0x08, 0x00, 0x00, 0xdc, 0x08, 0x00, 0x00,
+ 0xf8, 0x08, 0x00, 0x00, 0x14, 0x09, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00,
+ 0x4c, 0x09, 0x00, 0x00, 0x68, 0x09, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x44, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x41, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x41, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x17, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x23, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x2f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x3b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x3e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x47, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x4d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x53, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x44, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff,
- 0x01, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x57, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0x56, 0x00, 0x01, 0x01,
+ 0x08, 0x00, 0x00, 0x12, 0xff, 0xff, 0xff, 0xff
};
-unsigned int system_arsc_len = 792;
+unsigned int system_arsc_len = 6416;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 91e289c..fb9ac1e 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,6 +2,10 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+ifeq ($(TARGET_REQUIRES_SYNCHRONOUS_SETSURFACE),true)
+ LOCAL_CFLAGS += -DREQUIRES_SYNCHRONOUS_SETSURFACE
+endif
+
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE := libhwui
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 35051b7..54cfaea 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -683,14 +683,6 @@ bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, cons
return mDrawn;
}
-void FontRenderer::removeFont(const Font* font) {
- mActiveFonts.remove(font->getDescription());
-
- if (mCurrentFont == font) {
- mCurrentFont = nullptr;
- }
-}
-
void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) {
uint32_t intRadius = Blur::convertRadiusToInt(radius);
#ifdef ANDROID_ENABLE_RENDERSCRIPT
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index dfb107c..3da20ee 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -151,8 +151,6 @@ private:
float x3, float y3, float u3, float v3,
float x4, float y4, float u4, float v4, CacheTexture* texture);
- void removeFont(const Font* font);
-
void checkTextureUpdate();
void setTextureDirty() {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2292ef4..88a6979 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -181,6 +181,16 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa
}
void OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
+#ifdef QCOM_HARDWARE
+ mRenderState.scissor().setEnabled(true);
+ mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
+ glClear(GL_COLOR_BUFFER_BIT);
+ mDirty = true;
+ if (opaque) {
+ mRenderState.scissor().reset();
+ return;
+ }
+#else
if (!opaque) {
mRenderState.scissor().setEnabled(true);
mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
@@ -190,6 +200,7 @@ void OpenGLRenderer::clear(float left, float top, float right, float bottom, boo
}
mRenderState.scissor().reset();
+#endif
}
void OpenGLRenderer::startTilingCurrentClip(bool opaque, bool expand) {
@@ -1699,6 +1710,7 @@ void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
if (!texture) return;
+ const AutoTexture autoCleanup(texture);
// 9 patches are built for stretching - always filter
int textureFillFlags = TextureFillFlags::ForceFilter;
@@ -2325,12 +2337,15 @@ void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
PathTexture* texture = mCaches.pathCache.get(path, paint);
if (!texture) return;
- const AutoTexture autoCleanup(texture);
const float x = texture->left - texture->offset;
const float y = texture->top - texture->offset;
drawPathTexture(texture, x, y, paint);
+
+ if (texture->cleanup) {
+ mCaches.pathCache.remove(path, paint);
+ }
mDirty = true;
}
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 3af640f..3236f6f 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -400,6 +400,13 @@ PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
return texture;
}
+void PathCache::remove(const SkPath* path, const SkPaint* paint)
+{
+ PathDescription entry(kShapePath, paint);
+ entry.shape.path.mGenerationID = path->getGenerationID();
+ mCache.remove(entry);
+}
+
void PathCache::precache(const SkPath* path, const SkPaint* paint) {
if (!Caches::getInstance().tasks.canRunTasks()) {
return;
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 7014863..c529915 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -201,6 +201,7 @@ public:
PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
bool useCenter, const SkPaint* paint);
PathTexture* get(const SkPath* path, const SkPaint* paint);
+ void remove(const SkPath* path, const SkPaint* paint);
/**
* Removes the specified path. This is meant to be called from threads
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 7a2b9af..5d36a03 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -742,7 +742,7 @@ inline void genNewPenumbraAndPairWithUmbra(const Vector2* penumbra, int penumbra
// vertex's location.
int newPenumbraNumber = indexDelta - 1;
- float accumulatedDeltaLength[newPenumbraNumber];
+ float accumulatedDeltaLength[indexDelta];
float totalDeltaLength = 0;
// To save time, cache the previous umbra vertex info outside the loop
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index d2685da..a767a4e 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -204,15 +204,21 @@ void CacheTexture::allocatePixelBuffer() {
bool CacheTexture::upload() {
const Rect& dirtyRect = mDirtyRect;
- uint32_t x = mHasUnpackRowLength ? dirtyRect.left : 0;
- uint32_t y = dirtyRect.top;
- uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : getWidth();
- uint32_t height = dirtyRect.getHeight();
+ // align the x direction to 32 and y direction to 4 for better performance
+ uint32_t x = (((uint32_t)dirtyRect.left) & (~0x1F));
+ uint32_t y = (((uint32_t)dirtyRect.top) & (~0x3));
+ uint32_t r = ((((uint32_t)dirtyRect.right) + 0x1F) & (~0x1F));
+ uint32_t b = ((((uint32_t)dirtyRect.bottom) + 0x3) & (~0x3));
+ uint32_t width = (r > getWidth() ? getWidth() : r) - x;
+ uint32_t height = (b > getHeight() ? getHeight() : b) - y;
// The unpack row length only needs to be specified when a new
// texture is bound
if (mHasUnpackRowLength) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, getWidth());
+ } else {
+ x = 0;
+ width = getWidth();
}
mPixelBuffer->upload(x, y, width, height);
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 5de64a4..762f2bb 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -64,8 +64,6 @@ Font::FontDescription::FontDescription(const SkPaint* paint, const SkMatrix& ras
}
Font::~Font() {
- mState->removeFont(this);
-
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
delete mCachedGlyphs.valueAt(i);
}
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 1e39bfa..84b6965 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -306,6 +306,10 @@ void RenderState::render(const Glop& glop) {
// Shader uniforms
SkiaShader::apply(*mCaches, fill.skiaShaderData);
+ Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType) ?
+ fill.skiaShaderData.bitmapData.bitmapTexture : nullptr;
+ const AutoTexture autoCleanup(texture);
+
// ------------------------------------
// ---------- GL state setup ----------
// ------------------------------------
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4cf8b15..57e5832 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -110,12 +110,11 @@ void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
mSwapBehavior = swapBehavior;
}
-bool CanvasContext::initialize(ANativeWindow* window) {
+void CanvasContext::initialize(ANativeWindow* window) {
setSurface(window);
- if (mCanvas) return false;
+ if (mCanvas) return;
mCanvas = new OpenGLRenderer(mRenderThread.renderState());
mCanvas->initProperties();
- return true;
}
void CanvasContext::updateSurface(ANativeWindow* window) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index f2fa9cd..1e6f830 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -67,7 +67,7 @@ public:
// Won't take effect until next EGLSurface creation
void setSwapBehavior(SwapBehavior swapBehavior);
- bool initialize(ANativeWindow* window);
+ void initialize(ANativeWindow* window);
void updateSurface(ANativeWindow* window);
bool pauseSurface(ANativeWindow* window);
bool hasSurface() { return mNativeWindow.get(); }
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6d9acd4..2214091 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -140,14 +140,19 @@ void RenderProxy::setName(const char* name) {
}
CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
- return (void*) args->context->initialize(args->window);
+ args->context->initialize(args->window);
+ return nullptr;
}
-bool RenderProxy::initialize(const sp<ANativeWindow>& window) {
+void RenderProxy::initialize(const sp<ANativeWindow>& window) {
SETUP_TASK(initialize);
args->context = mContext;
args->window = window.get();
- return (bool) postAndWait(task);
+#ifdef REQUIRES_SYNCHRONOUS_SETSURFACE
+ postAndWait(task);
+#else
+ post(task);
+#endif
}
CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
@@ -384,6 +389,12 @@ void RenderProxy::fence() {
postAndWait(task);
}
+void RenderProxy::staticFence() {
+ SETUP_TASK(fence);
+ UNUSED(args);
+ staticPostAndWait(task);
+}
+
CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
args->context->stopDrawing();
return nullptr;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 5febbe0..8a1f5bf 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -67,7 +67,7 @@ public:
ANDROID_API bool loadSystemProperties();
ANDROID_API void setName(const char* name);
- ANDROID_API bool initialize(const sp<ANativeWindow>& window);
+ ANDROID_API void initialize(const sp<ANativeWindow>& window);
ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
ANDROID_API void setup(int width, int height, float lightRadius,
@@ -94,6 +94,7 @@ public:
ANDROID_API static void overrideProperty(const char* name, const char* value);
ANDROID_API void fence();
+ ANDROID_API static void staticFence();
ANDROID_API void stopDrawing();
ANDROID_API void notifyFramePending();
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index c643ed0..f7379b6 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -50,6 +50,7 @@ enum {
TRANSACTION_isExternalStorageEmulated,
TRANSACTION_decryptStorage,
TRANSACTION_encryptStorage,
+ TRANSACTION_encryptWipeStorage = IBinder::FIRST_CALL_TRANSACTION + 61,
};
class BpMountService: public BpInterface<IMountService>
@@ -551,6 +552,23 @@ public:
}
return reply.readInt32();
}
+
+ int32_t encryptWipeStorage(const String16& password)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(password);
+ if (remote()->transact(TRANSACTION_encryptWipeStorage, data, &reply) != NO_ERROR) {
+ ALOGD("encryptWipeStorage could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ ALOGD("encryptWipeStorage caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(MountService, "IMountService")
diff --git a/location/java/android/location/GeoFenceParams.aidl b/location/java/android/location/GeoFenceParams.aidl
new file mode 100644
index 0000000..3e9be4c
--- /dev/null
+++ b/location/java/android/location/GeoFenceParams.aidl
@@ -0,0 +1,23 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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.location;
+
+parcelable GeoFenceParams;
diff --git a/location/java/android/location/GeoFenceParams.java b/location/java/android/location/GeoFenceParams.java
new file mode 100644
index 0000000..aa6e245
--- /dev/null
+++ b/location/java/android/location/GeoFenceParams.java
@@ -0,0 +1,132 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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.location;
+
+import android.app.PendingIntent;
+import android.os.Binder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.io.PrintWriter;
+
+/**
+ * GeoFenceParams for internal use
+ * {@hide}
+ */
+public class GeoFenceParams implements Parcelable {
+ public static final int ENTERING = 1;
+ public static final int LEAVING = 2;
+ public final int mUid;
+ public final double mLatitude;
+ public final double mLongitude;
+ public final float mRadius;
+ public final long mExpiration;
+ public final PendingIntent mIntent;
+ public final String mPackageName;
+
+ public static final Parcelable.Creator<GeoFenceParams> CREATOR = new Parcelable.Creator<GeoFenceParams>() {
+ public GeoFenceParams createFromParcel(Parcel in) {
+ return new GeoFenceParams(in);
+ }
+
+ @Override
+ public GeoFenceParams[] newArray(int size) {
+ return new GeoFenceParams[size];
+ }
+ };
+
+ public GeoFenceParams(double lat, double lon, float r,
+ long expire, PendingIntent intent, String packageName) {
+ this(Binder.getCallingUid(), lat, lon, r, expire, intent, packageName);
+ }
+
+ public GeoFenceParams(int uid, double lat, double lon, float r,
+ long expire, PendingIntent intent, String packageName) {
+ mUid = uid;
+ mLatitude = lat;
+ mLongitude = lon;
+ mRadius = r;
+ mExpiration = expire;
+ mIntent = intent;
+ mPackageName = packageName;
+ }
+
+ private GeoFenceParams(Parcel in) {
+ mUid = in.readInt();
+ mLatitude = in.readDouble();
+ mLongitude = in.readDouble();
+ mRadius = in.readFloat();
+ mExpiration = in.readLong();
+ mIntent = in.readParcelable(null);
+ mPackageName = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mUid);
+ dest.writeDouble(mLatitude);
+ dest.writeDouble(mLongitude);
+ dest.writeFloat(mRadius);
+ dest.writeLong(mExpiration);
+ dest.writeParcelable(mIntent, 0);
+ dest.writeString(mPackageName);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("GeoFenceParams:\n\tmUid - ");
+ sb.append(mUid);
+ sb.append("\n\tmLatitide - ");
+ sb.append(mLatitude);
+ sb.append("\n\tmLongitude - ");
+ sb.append(mLongitude);
+ sb.append("\n\tmRadius - ");
+ sb.append(mRadius);
+ sb.append("\n\tmExpiration - ");
+ sb.append(mExpiration);
+ sb.append("\n\tmIntent - ");
+ sb.append(mIntent);
+ return sb.toString();
+ }
+
+ public long getExpiration() {
+ return mExpiration;
+ }
+
+ public PendingIntent getIntent() {
+ return mIntent;
+ }
+
+ public int getCallerUid() {
+ return mUid;
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + this);
+ pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
+ pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
+ }
+}
diff --git a/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl b/location/java/android/location/IGeoFenceListener.aidl
index 96c59e2..ccec143 100755..100644
--- a/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl
+++ b/location/java/android/location/IGeoFenceListener.aidl
@@ -1,5 +1,9 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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.
@@ -14,17 +18,13 @@
* limitations under the License.
*/
-package android.bluetooth;
+package android.location;
-import android.content.ComponentName;
-import android.os.IBinder;
+import android.app.PendingIntent;
/**
- * Callback for bluetooth profile connections.
- *
* {@hide}
*/
-interface IBluetoothProfileServiceConnection {
- void onServiceConnected(in ComponentName comp, in IBinder service);
- void onServiceDisconnected(in ComponentName comp);
+oneway interface IGeoFenceListener {
+ void geoFenceExpired(in PendingIntent intent);
}
diff --git a/location/java/android/location/IGeoFencer.aidl b/location/java/android/location/IGeoFencer.aidl
new file mode 100644
index 0000000..d576c6e
--- /dev/null
+++ b/location/java/android/location/IGeoFencer.aidl
@@ -0,0 +1,33 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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.location;
+
+import android.location.GeoFenceParams;
+import android.app.PendingIntent;
+
+/**
+ * {@hide}
+ */
+interface IGeoFencer {
+ boolean setGeoFence(in IBinder who, in GeoFenceParams params);
+ void clearGeoFence(in IBinder who, in PendingIntent fence);
+ void clearGeoFenceUser(int uid);
+}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 2c19324..4544814 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -456,6 +456,7 @@ public class LocationManager {
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(String provider, long minTime, float minDistance,
LocationListener listener) {
+ android.util.SeempLog.record(47);
checkProvider(provider);
checkListener(listener);
@@ -488,6 +489,7 @@ public class LocationManager {
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(String provider, long minTime, float minDistance,
LocationListener listener, Looper looper) {
+ android.util.SeempLog.record(47);
checkProvider(provider);
checkListener(listener);
@@ -521,6 +523,7 @@ public class LocationManager {
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
LocationListener listener, Looper looper) {
+ android.util.SeempLog.record(47);
checkCriteria(criteria);
checkListener(listener);
@@ -549,6 +552,7 @@ public class LocationManager {
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(String provider, long minTime, float minDistance,
PendingIntent intent) {
+ android.util.SeempLog.record(47);
checkProvider(provider);
checkPendingIntent(intent);
@@ -651,6 +655,7 @@ public class LocationManager {
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
PendingIntent intent) {
+ android.util.SeempLog.record(47);
checkCriteria(criteria);
checkPendingIntent(intent);
@@ -680,6 +685,7 @@ public class LocationManager {
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) {
+ android.util.SeempLog.record(64);
checkProvider(provider);
checkListener(listener);
@@ -710,6 +716,7 @@ public class LocationManager {
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) {
+ android.util.SeempLog.record(64);
checkCriteria(criteria);
checkListener(listener);
@@ -733,6 +740,7 @@ public class LocationManager {
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(String provider, PendingIntent intent) {
+ android.util.SeempLog.record(64);
checkProvider(provider);
checkPendingIntent(intent);
@@ -757,6 +765,7 @@ public class LocationManager {
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(Criteria criteria, PendingIntent intent) {
+ android.util.SeempLog.record(64);
checkCriteria(criteria);
checkPendingIntent(intent);
@@ -825,6 +834,7 @@ public class LocationManager {
@SystemApi
public void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper) {
+ android.util.SeempLog.record(47);
checkListener(listener);
requestLocationUpdates(request, listener, looper, null);
}
@@ -852,6 +862,7 @@ public class LocationManager {
*/
@SystemApi
public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
+ android.util.SeempLog.record(47);
checkPendingIntent(intent);
requestLocationUpdates(request, null, null, intent);
}
@@ -870,6 +881,7 @@ public class LocationManager {
private void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper, PendingIntent intent) {
+ android.util.SeempLog.record(47);
String packageName = mContext.getPackageName();
@@ -978,6 +990,7 @@ public class LocationManager {
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
PendingIntent intent) {
+ android.util.SeempLog.record(45);
checkPendingIntent(intent);
if (expiration < 0) expiration = Long.MAX_VALUE;
@@ -1191,6 +1204,7 @@ public class LocationManager {
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public Location getLastKnownLocation(String provider) {
+ android.util.SeempLog.record(46);
checkProvider(provider);
String packageName = mContext.getPackageName();
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
@@ -1511,6 +1525,7 @@ public class LocationManager {
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addGpsStatusListener(GpsStatus.Listener listener) {
+ android.util.SeempLog.record(43);
boolean result;
if (mGpsStatusListeners.get(listener) != null) {
@@ -1558,6 +1573,7 @@ public class LocationManager {
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
+ android.util.SeempLog.record(44);
boolean result;
if (mNmeaListeners.get(listener) != null) {
@@ -1676,6 +1692,7 @@ public class LocationManager {
* @return true if the command succeeds.
*/
public boolean sendExtraCommand(String provider, String command, Bundle extras) {
+ android.util.SeempLog.record(48);
try {
return mService.sendExtraCommand(provider, command, extras);
} catch (RemoteException e) {
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index bde3d19..962316b 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -252,6 +252,30 @@ public class AudioFormat {
* */
public static final int ENCODING_AAC_HE_V2 = 12;
+ /** Audio data format: AMRNB
+ * @hide
+ * */
+ public static final int ENCODING_AMRNB = 100;
+ /** Audio data format: AMRWB
+ * @hide
+ * */
+ public static final int ENCODING_AMRWB = 101;
+ /** Audio data format: EVRC
+ * @hide
+ * */
+ public static final int ENCODING_EVRC = 102;
+ /** Audio data format: EVRCB
+ * @hide
+ * */
+ public static final int ENCODING_EVRCB = 103;
+ /** Audio data format: EVRCWB
+ * @hide
+ * */
+ public static final int ENCODING_EVRCWB = 104;
+ /** Audio data format: EVRCNW
+ * @hide
+ * */
+ public static final int ENCODING_EVRCNW = 105;
/** Invalid audio channel configuration */
/** @deprecated Use {@link #CHANNEL_INVALID} instead. */
@Deprecated public static final int CHANNEL_CONFIGURATION_INVALID = 0;
@@ -409,6 +433,11 @@ public class AudioFormat {
public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);
/** @hide */
public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK;
+ /** @hide */
+ public static final int CHANNEL_IN_5POINT1 = (CHANNEL_IN_LEFT |
+ CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK |
+ CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED);
+
// CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL
/** @hide */
@@ -422,6 +451,15 @@ public class AudioFormat {
return 2;
case ENCODING_PCM_FLOAT:
return 4;
+ case ENCODING_AMRNB:
+ return 32;
+ case ENCODING_AMRWB:
+ return 61;
+ case ENCODING_EVRC:
+ case ENCODING_EVRCB:
+ case ENCODING_EVRCWB:
+ case ENCODING_EVRCNW:
+ return 23;
case ENCODING_INVALID:
default:
throw new IllegalArgumentException("Bad audio format " + audioFormat);
@@ -443,6 +481,12 @@ public class AudioFormat {
case ENCODING_AAC_LC:
case ENCODING_AAC_HE_V1:
case ENCODING_AAC_HE_V2:
+ case ENCODING_AMRNB:
+ case ENCODING_AMRWB:
+ case ENCODING_EVRC:
+ case ENCODING_EVRCB:
+ case ENCODING_EVRCWB:
+ case ENCODING_EVRCNW:
return true;
default:
return false;
@@ -483,6 +527,12 @@ public class AudioFormat {
case ENCODING_AAC_LC:
case ENCODING_AAC_HE_V1:
case ENCODING_AAC_HE_V2:
+ case ENCODING_AMRNB:
+ case ENCODING_AMRWB:
+ case ENCODING_EVRC:
+ case ENCODING_EVRCB:
+ case ENCODING_EVRCWB:
+ case ENCODING_EVRCNW:
return false;
case ENCODING_INVALID:
default:
@@ -715,6 +765,12 @@ public class AudioFormat {
case ENCODING_E_AC3:
case ENCODING_DTS:
case ENCODING_DTS_HD:
+ case ENCODING_AMRNB:
+ case ENCODING_AMRWB:
+ case ENCODING_EVRC:
+ case ENCODING_EVRCB:
+ case ENCODING_EVRCWB:
+ case ENCODING_EVRCNW:
mEncoding = encoding;
break;
case ENCODING_INVALID:
@@ -859,7 +915,13 @@ public class AudioFormat {
ENCODING_AC3,
ENCODING_E_AC3,
ENCODING_DTS,
- ENCODING_DTS_HD
+ ENCODING_DTS_HD,
+ ENCODING_AMRNB,
+ ENCODING_AMRWB,
+ ENCODING_EVRC,
+ ENCODING_EVRCB,
+ ENCODING_EVRCWB,
+ ENCODING_EVRCNW
})
@Retention(RetentionPolicy.SOURCE)
public @interface Encoding {}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 875e716..fc917f6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -67,7 +67,6 @@ public class AudioManager {
private final boolean mUseFixedVolume;
private static String TAG = "AudioManager";
private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
-
/**
* Broadcast intent, a hint for applications that audio is about to become
* 'noisy' due to a change in audio outputs. For example, this intent may
@@ -310,6 +309,32 @@ public class AudioManager {
*/
public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
+ /**
+ * @hide Broadcast intent when RemoteControlClient list is updated.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String RCC_CHANGED_ACTION =
+ "org.codeaurora.bluetooth.RCC_CHANGED_ACTION";
+
+ /**
+ * @hide Used for sharing the calling package name
+ */
+ public static final String EXTRA_CALLING_PACKAGE_NAME =
+ "org.codeaurora.bluetooth.EXTRA_CALLING_PACKAGE_NAME";
+
+ /**
+ * @hide Used for sharing the focus changed value
+ */
+ public static final String EXTRA_FOCUS_CHANGED_VALUE =
+ "org.codeaurora.bluetooth.EXTRA_FOCUS_CHANGED_VALUE";
+
+ /**
+ * @hide Used for sharing the availability changed value
+ */
+ public static final String EXTRA_AVAILABLITY_CHANGED_VALUE =
+ "org.codeaurora.bluetooth.EXTRA_AVAILABLITY_CHANGED_VALUE";
+
+
/** The audio stream for phone calls */
public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
/** The audio stream for system sounds */
@@ -2481,6 +2506,7 @@ public class AudioManager {
//====================================================================
// Remote Control
+
/**
* Register a component to be the sole receiver of MEDIA_BUTTON intents.
* @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
@@ -2499,6 +2525,7 @@ public class AudioManager {
"receiver and context package names don't match");
return;
}
+
// construct a PendingIntent for the media button and register it
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
// the associated intent will be handled by the component being registered
@@ -2508,6 +2535,7 @@ public class AudioManager {
registerMediaButtonIntent(pi, eventReceiver);
}
+
/**
* Register a component to be the sole receiver of MEDIA_BUTTON intents. This is like
* {@link #registerMediaButtonEventReceiver(android.content.ComponentName)}, but allows
@@ -2637,6 +2665,13 @@ public class AudioManager {
return false;
}
rctlr.startListeningToSessions();
+ IAudioService service = getService();
+ try {
+ service.updateRemoteControllerOnExistingMediaPlayers();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in calling Audio service interface" +
+ "updateRemoteControllerOnExistingMediaPlayers() due to " + e);
+ }
return true;
}
@@ -2660,6 +2695,24 @@ public class AudioManager {
/**
* @hide
+ */
+ public void updateMediaPlayerList(String packageName, boolean toAdd) {
+ IAudioService service = getService();
+ try {
+ if (toAdd) {
+ Log.d(TAG, "updateMediaPlayerList: Add RCC " + packageName + " to List");
+ service.addMediaPlayerAndUpdateRemoteController(packageName);
+ } else {
+ Log.d(TAG, "updateMediaPlayerList: Remove RCC " + packageName + " from List");
+ service.removeMediaPlayerAndUpdateRemoteController(packageName);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while executing updateMediaPlayerList: " + e);
+ }
+ }
+
+ /**
+ * @hide
* Registers a remote control display that will be sent information by remote control clients.
* Use this method if your IRemoteControlDisplay is not going to display artwork, otherwise
* use {@link #registerRemoteControlDisplay(IRemoteControlDisplay, int, int)} to pass the
@@ -2811,6 +2864,52 @@ public class AudioManager {
}
}
+ /**
+ * @hide
+ * Request the user of a RemoteControlClient to play the requested item.
+ * @param generationId the RemoteControlClient generation counter for which this request is
+ * issued.
+ * @param uid uid of the song to be played.
+ * @scope scope of the file system to use
+ */
+ public void setRemoteControlClientPlayItem(long uid, int scope) {
+ IAudioService service = getService();
+ try {
+ service.setRemoteControlClientPlayItem(uid, scope);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setRemoteControlClientPlayItem(" +
+ uid + ", " + scope + ")", e);
+ }
+ }
+
+ /**
+ * @hide
+ * Request the user of a RemoteControlClient to provide with the now playing list entries.
+ * @param generationId the RemoteControlClient generation counter for which this request is
+ * issued.
+ */
+ public void getRemoteControlClientNowPlayingEntries() {
+ IAudioService service = getService();
+ try {
+ service.getRemoteControlClientNowPlayingEntries();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in getRemoteControlClientNowPlayingEntries(" + ")", e);
+ }
+ }
+
+ /**
+ * @hide
+ * Request the user of a RemoteControlClient to set the music player as current browsed player.
+ */
+ public void setRemoteControlClientBrowsedPlayer() {
+ Log.d(TAG, "setRemoteControlClientBrowsedPlayer: ");
+ IAudioService service = getService();
+ try {
+ service.setRemoteControlClientBrowsedPlayer();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setRemoteControlClientBrowsedPlayer(" + ")", e);
+ }
+ }
/**
* @hide
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 974b62e..e819b8a 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -643,6 +643,12 @@ public class AudioRecord
case AudioFormat.ENCODING_PCM_FLOAT:
case AudioFormat.ENCODING_PCM_16BIT:
case AudioFormat.ENCODING_PCM_8BIT:
+ case AudioFormat.ENCODING_AMRNB:
+ case AudioFormat.ENCODING_AMRWB:
+ case AudioFormat.ENCODING_EVRC:
+ case AudioFormat.ENCODING_EVRCB:
+ case AudioFormat.ENCODING_EVRCWB:
+ case AudioFormat.ENCODING_EVRCNW:
mAudioFormat = audioFormat;
break;
default:
@@ -845,6 +851,9 @@ public class AudioRecord
case (AudioFormat.CHANNEL_IN_FRONT | AudioFormat.CHANNEL_IN_BACK):
channelCount = 2;
break;
+ case AudioFormat.CHANNEL_IN_5POINT1:
+ channelCount = 6;
+ break;
case AudioFormat.CHANNEL_INVALID:
default:
loge("getMinBufferSize(): Invalid channel configuration.");
@@ -881,6 +890,7 @@ public class AudioRecord
*/
public void startRecording()
throws IllegalStateException {
+ android.util.SeempLog.record(70);
if (mState != STATE_INITIALIZED) {
throw new IllegalStateException("startRecording() called on an "
+ "uninitialized AudioRecord.");
@@ -893,6 +903,11 @@ public class AudioRecord
mRecordingState = RECORDSTATE_RECORDING;
}
}
+
+ if (getRecordingState() == RECORDSTATE_RECORDING &&
+ getAudioSource() == MediaRecorder.AudioSource.HOTWORD) {
+ handleHotwordInput(true);
+ }
}
/**
@@ -904,6 +919,7 @@ public class AudioRecord
*/
public void startRecording(MediaSyncEvent syncEvent)
throws IllegalStateException {
+ android.util.SeempLog.record(70);
if (mState != STATE_INITIALIZED) {
throw new IllegalStateException("startRecording() called on an "
+ "uninitialized AudioRecord.");
@@ -934,6 +950,10 @@ public class AudioRecord
native_stop();
mRecordingState = RECORDSTATE_STOPPED;
}
+
+ if (getAudioSource() == MediaRecorder.AudioSource.HOTWORD) {
+ handleHotwordInput(false);
+ }
}
private final IBinder mICallBack = new Binder();
@@ -950,6 +970,16 @@ public class AudioRecord
}
}
+ private void handleHotwordInput(boolean listening) {
+ final IBinder b = ServiceManager.getService(android.content.Context.AUDIO_SERVICE);
+ final IAudioService ias = IAudioService.Stub.asInterface(b);
+ try {
+ ias.handleHotwordInput(listening);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to AudioService when handling hotword input.", e);
+ }
+ }
+
//---------------------------------------------------------
// Audio data supply
//--------------------
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index c59d1c7..8bf1604 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -268,6 +268,54 @@ public class AudioSystem
}
+ /**
+ * Handles events for the audio policy manager about effect sessions
+ * @see android.media.audiopolicy.AudioPolicy
+ */
+ public interface EffectSessionCallback
+ {
+ void onSessionAdded(int stream, int sessionId);
+
+ void onSessionRemoved(int stream, int sessionId);
+ }
+
+ //keep in sync with include/media/AudioPolicy.h
+ private final static int AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE = 10;
+
+ private static EffectSessionCallback sEffectSessionCallback;
+
+ public static void setEffectSessionCallback(EffectSessionCallback cb)
+ {
+ synchronized (AudioSystem.class) {
+ sEffectSessionCallback = cb;
+ native_register_effect_session_callback();
+ }
+ }
+
+ private static void effectSessionCallbackFromNative(int event, int stream, int sessionId, boolean added)
+ {
+ EffectSessionCallback cb = null;
+ synchronized (AudioSystem.class) {
+ if (sEffectSessionCallback != null) {
+ cb = sEffectSessionCallback;
+ }
+ }
+ if (cb != null) {
+ switch(event) {
+ case AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE:
+ if (added) {
+ cb.onSessionAdded(stream, sessionId);
+ } else {
+ cb.onSessionRemoved(stream, sessionId);
+ }
+ break;
+ default:
+ Log.e(TAG, "effectSessionCallbackFromNative: unknown event " + event);
+ }
+ }
+ }
+
+
/*
* Error codes used by public APIs (AudioTrack, AudioRecord, AudioManager ...)
* Must be kept in sync with frameworks/base/core/jni/android_media_AudioErrors.h
@@ -319,7 +367,7 @@ public class AudioSystem
public static final int DEVICE_OUT_AUX_LINE = 0x200000;
public static final int DEVICE_OUT_SPEAKER_SAFE = 0x400000;
public static final int DEVICE_OUT_IP = 0x800000;
-
+ public static final int DEVICE_OUT_PROXY = 0x1000000;
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
@@ -346,6 +394,7 @@ public class AudioSystem
DEVICE_OUT_AUX_LINE |
DEVICE_OUT_SPEAKER_SAFE |
DEVICE_OUT_IP |
+ DEVICE_OUT_PROXY |
DEVICE_OUT_DEFAULT);
public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -385,6 +434,7 @@ public class AudioSystem
public static final int DEVICE_IN_BLUETOOTH_A2DP = DEVICE_BIT_IN | 0x20000;
public static final int DEVICE_IN_LOOPBACK = DEVICE_BIT_IN | 0x40000;
public static final int DEVICE_IN_IP = DEVICE_BIT_IN | 0x80000;
+ public static final int DEVICE_IN_PROXY = DEVICE_BIT_IN | 0x1000000;
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
@@ -407,6 +457,7 @@ public class AudioSystem
DEVICE_IN_BLUETOOTH_A2DP |
DEVICE_IN_LOOPBACK |
DEVICE_IN_IP |
+ DEVICE_IN_PROXY |
DEVICE_IN_DEFAULT);
public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
@@ -442,6 +493,7 @@ public class AudioSystem
public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line";
public static final String DEVICE_OUT_SPEAKER_SAFE_NAME = "speaker_safe";
public static final String DEVICE_OUT_IP_NAME = "ip";
+ public static final String DEVICE_OUT_PROXY_NAME = "proxy";
public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
@@ -515,6 +567,8 @@ public class AudioSystem
return DEVICE_OUT_SPEAKER_SAFE_NAME;
case DEVICE_OUT_IP:
return DEVICE_OUT_IP_NAME;
+ case DEVICE_OUT_PROXY:
+ return DEVICE_OUT_PROXY_NAME;
case DEVICE_OUT_DEFAULT:
default:
return Integer.toString(device);
@@ -642,6 +696,8 @@ public class AudioSystem
// declare this instance as having a dynamic policy callback handler
private static native final void native_register_dynamic_policy_callback();
+ private static native final void native_register_effect_session_callback();
+
// must be kept in sync with value in include/system/audio.h
public static final int AUDIO_HW_SYNC_INVALID = 0;
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index d303a2e..6785670 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -206,6 +206,77 @@ public class CamcorderProfile
private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW;
private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_2160P;
+ // Vendor-specific quality profiles
+ /**
+ * Quality level corresponding to the VGA (640 x 480) resolution.
+ * @hide
+ */
+ public static final int QUALITY_VGA = 10000;
+
+ /**
+ * Quality level corresponding to the 4k-DCI (4096 x 2160) resolution.
+ * @hide
+ */
+ public static final int QUALITY_4KDCI = 10001;
+
+ /**
+ * Time lapse quality level corresponding to the VGA (640 x 480) resolution.
+ * @hide
+ */
+ public static final int QUALITY_TIME_LAPSE_VGA = 10002;
+
+ /**
+ * Time lapse quality level corresponding to the 4k-DCI (4096 x 2160) resolution.
+ * @hide
+ */
+ public static final int QUALITY_TIME_LAPSE_4KDCI = 10003;
+
+ /**
+ * High speed ( >= 100fps) quality level corresponding to the CIF (352 x 288)
+ * @hide
+ */
+ public static final int QUALITY_HIGH_SPEED_CIF = 10004;
+
+ /**
+ * High speed ( >= 100fps) quality level corresponding to the VGA (640 x 480)
+ * @hide
+ */
+ public static final int QUALITY_HIGH_SPEED_VGA = 10005;
+
+ /**
+ * High speed ( >= 100fps) quality level corresponding to the 4K-DCI (4096 x 2160)
+ * @hide
+ */
+ public static final int QUALITY_HIGH_SPEED_4KDCI = 10006;
+
+ /**
+ * Quality level corresponding to QHD resolution
+ * @hide
+ */
+ public static final int QUALITY_QHD = 10007;
+
+ /**
+ * Quality level corresponding to 2K resolution
+ * @hide
+ */
+ public static final int QUALITY_2k = 10008;
+
+ /**
+ * Time lapse quality level corresponding to the QHD resolution.
+ * @hide
+ */
+ public static final int QUALITY_TIME_LAPSE_QHD = 10009;
+
+ /**
+ * Time lapse quality level corresponding to the 2K resolution.
+ * @hide
+ */
+ public static final int QUALITY_TIME_LAPSE_2k = 10010;
+
+ // Start and end of vendor quality list
+ private static final int QUALITY_VENDOR_LIST_START = QUALITY_VGA;
+ private static final int QUALITY_VENDOR_LIST_END = QUALITY_TIME_LAPSE_2k;
+
/**
* Default recording duration in seconds before the session is terminated.
* This is useful for applications like MMS has limited file size requirement.
@@ -391,7 +462,9 @@ public class CamcorderProfile
(quality >= QUALITY_TIME_LAPSE_LIST_START &&
quality <= QUALITY_TIME_LAPSE_LIST_END) ||
(quality >= QUALITY_HIGH_SPEED_LIST_START &&
- quality <= QUALITY_HIGH_SPEED_LIST_END))) {
+ quality <= QUALITY_HIGH_SPEED_LIST_END) ||
+ (quality >= QUALITY_VENDOR_LIST_START &&
+ quality <= QUALITY_VENDOR_LIST_END))) {
String errMessage = "Unsupported quality level: " + quality;
throw new IllegalArgumentException(errMessage);
}
diff --git a/media/java/android/media/ClosedCaptionRenderer.java b/media/java/android/media/ClosedCaptionRenderer.java
index 8403c1c..2cf754e 100644
--- a/media/java/android/media/ClosedCaptionRenderer.java
+++ b/media/java/android/media/ClosedCaptionRenderer.java
@@ -609,8 +609,10 @@ class CCParser {
if (mLines[mRow] != null) {
for (int i = 0; i < mCol; i++) {
if (mLines[mRow].charAt(i) != TS) {
- for (int j = mCol; j < mLines[mRow].length(); j++) {
- mLines[j].setCharAt(j, TS);
+ for (int j = mCol; j < mLines[mRow].length() && j < mLines.length; j++) {
+ if (mLines[j] != null){
+ mLines[j].setCharAt(j, TS);
+ }
}
return;
}
diff --git a/media/java/android/media/EncoderCapabilities.java b/media/java/android/media/EncoderCapabilities.java
index 332e360..d612c20 100644
--- a/media/java/android/media/EncoderCapabilities.java
+++ b/media/java/android/media/EncoderCapabilities.java
@@ -47,13 +47,17 @@ public class EncoderCapabilities
public final int mMinFrameRate, mMaxFrameRate; // min and max frame rate (fps)
public final int mMinFrameWidth, mMaxFrameWidth; // min and max frame width (pixel)
public final int mMinFrameHeight, mMaxFrameHeight; // minn and max frame height (pixel)
+ public final int mMaxHFRFrameWidth, mMaxHFRFrameHeight; // max HFR size (pixel)
+ public final int mMaxHFRMode; // max HFR mode
// Private constructor called by JNI
private VideoEncoderCap(int codec,
int minBitRate, int maxBitRate,
int minFrameRate, int maxFrameRate,
int minFrameWidth, int maxFrameWidth,
- int minFrameHeight, int maxFrameHeight) {
+ int minFrameHeight, int maxFrameHeight,
+ int maxHFRFrameWidth, int maxHFRFrameHeight,
+ int maxHFRMode) {
mCodec = codec;
mMinBitRate = minBitRate;
mMaxBitRate = maxBitRate;
@@ -63,6 +67,9 @@ public class EncoderCapabilities
mMaxFrameWidth = maxFrameWidth;
mMinFrameHeight = minFrameHeight;
mMaxFrameHeight = maxFrameHeight;
+ mMaxHFRFrameWidth = maxHFRFrameWidth;
+ mMaxHFRFrameHeight = maxHFRFrameHeight;
+ mMaxHFRMode = maxHFRMode;
}
};
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 8aebe11..cdcd83c 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -215,4 +215,21 @@ interface IAudioService {
int setFocusPropertiesForPolicy(int duckingBehavior, in IAudioPolicyCallback pcb);
void setVolumePolicy(in VolumePolicy policy);
+
+ void setRemoteControlClientBrowsedPlayer();
+
+ void getRemoteControlClientNowPlayingEntries();
+
+ void setRemoteControlClientPlayItem(long uid, int scope);
+
+ void updateRemoteControllerOnExistingMediaPlayers();
+
+ void addMediaPlayerAndUpdateRemoteController(String packageName);
+
+ void removeMediaPlayerAndUpdateRemoteController(String packageName);
+
+ void handleHotwordInput(boolean listening);
+
+ String getCurrentHotwordInputPackageName();
+
}
diff --git a/media/java/android/media/IRemoteControlClient.aidl b/media/java/android/media/IRemoteControlClient.aidl
index aa142d6..d8e73c8 100644
--- a/media/java/android/media/IRemoteControlClient.aidl
+++ b/media/java/android/media/IRemoteControlClient.aidl
@@ -52,11 +52,14 @@ oneway interface IRemoteControlClient
*/
void setCurrentClientGenerationId(int clientGeneration);
- void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h);
+ void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h);
void unplugRemoteControlDisplay(IRemoteControlDisplay rcd);
void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h);
void setWantsSyncForDisplay(IRemoteControlDisplay rcd, boolean wantsSync);
void enableRemoteControlDisplay(IRemoteControlDisplay rcd, boolean enabled);
void seekTo(int clientGeneration, long timeMs);
void updateMetadata(int clientGeneration, int key, in Rating value);
+ void setPlayItem(int scope, long uid);
+ void setBrowsedPlayer();
+ void getNowPlayingEntries();
} \ No newline at end of file
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 4101935..957ba16 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -589,6 +589,13 @@ public final class MediaCodecInfo {
return mDefaultFormat;
}
+ /* Return the capabilities info, so the app can query custom settings
+ * like for VT. */
+ /** @hide */
+ public MediaFormat getCapabilitiesInfoFormat() {
+ return mCapabilitiesInfo;
+ }
+
/**
* Returns the mime type for which this codec-capability object was created.
*/
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 526656a..c6de463 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -46,6 +46,18 @@ public class MediaFile {
private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_FLAC;
+ // More audio file types
+ public static final int FILE_TYPE_DTS = 300;
+ public static final int FILE_TYPE_3GPA = 301;
+ public static final int FILE_TYPE_AC3 = 302;
+ public static final int FILE_TYPE_QCP = 303;
+ public static final int FILE_TYPE_PCM = 304;
+ public static final int FILE_TYPE_EC3 = 305;
+ public static final int FILE_TYPE_AIFF = 306;
+ public static final int FILE_TYPE_APE = 307;
+ private static final int FIRST_AUDIO_FILE_TYPE_EXT = FILE_TYPE_DTS;
+ private static final int LAST_AUDIO_FILE_TYPE_EXT = FILE_TYPE_APE;
+
// MIDI file types
public static final int FILE_TYPE_MID = 11;
public static final int FILE_TYPE_SMF = 12;
@@ -69,8 +81,10 @@ public class MediaFile {
// More video file types
public static final int FILE_TYPE_MP2PS = 200;
+ public static final int FILE_TYPE_DIVX = 201;
+ public static final int FILE_TYPE_FLV = 202;
private static final int FIRST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS;
- private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS;
+ private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_FLV;
// Image file types
public static final int FILE_TYPE_JPEG = 31;
@@ -87,14 +101,16 @@ public class MediaFile {
public static final int FILE_TYPE_PLS = 42;
public static final int FILE_TYPE_WPL = 43;
public static final int FILE_TYPE_HTTPLIVE = 44;
+ public static final int FILE_TYPE_DASH = 45;
private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;
- private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_HTTPLIVE;
+ private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_DASH;
// Drm file types
public static final int FILE_TYPE_FL = 51;
+ public static final int FILE_TYPE_SD = 52;
private static final int FIRST_DRM_FILE_TYPE = FILE_TYPE_FL;
- private static final int LAST_DRM_FILE_TYPE = FILE_TYPE_FL;
+ private static final int LAST_DRM_FILE_TYPE = FILE_TYPE_SD;
// Other popular file types
public static final int FILE_TYPE_TEXT = 100;
@@ -228,6 +244,7 @@ public class MediaFile {
addFileType("M3U8", FILE_TYPE_HTTPLIVE, "audio/x-mpegurl");
addFileType("FL", FILE_TYPE_FL, "application/x-android-drm-fl");
+ addFileType("DCF", FILE_TYPE_SD, "application/vnd.oma.drm.content");
addFileType("TXT", FILE_TYPE_TEXT, "text/plain", MtpConstants.FORMAT_TEXT);
addFileType("HTM", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML);
@@ -240,13 +257,24 @@ public class MediaFile {
addFileType("ZIP", FILE_TYPE_ZIP, "application/zip");
addFileType("MPG", FILE_TYPE_MP2PS, "video/mp2p");
addFileType("MPEG", FILE_TYPE_MP2PS, "video/mp2p");
+ addFileType("DIVX", FILE_TYPE_DIVX, "video/divx");
+ addFileType("FLV", FILE_TYPE_FLV, "video/flv");
+ addFileType("MPD", FILE_TYPE_DASH, "application/dash+xml");
+ addFileType("QCP", FILE_TYPE_QCP, "audio/qcelp");
+ addFileType("AC3", FILE_TYPE_AC3, "audio/ac3");
+ addFileType("EC3", FILE_TYPE_EC3, "audio/eac3");
+ addFileType("AIF", FILE_TYPE_AIFF, "audio/x-aiff");
+ addFileType("AIFF", FILE_TYPE_AIFF, "audio/x-aiff");
+ addFileType("APE", FILE_TYPE_APE, "audio/x-ape");
}
public static boolean isAudioFileType(int fileType) {
return ((fileType >= FIRST_AUDIO_FILE_TYPE &&
fileType <= LAST_AUDIO_FILE_TYPE) ||
(fileType >= FIRST_MIDI_FILE_TYPE &&
- fileType <= LAST_MIDI_FILE_TYPE));
+ fileType <= LAST_MIDI_FILE_TYPE) ||
+ (fileType >= FIRST_AUDIO_FILE_TYPE_EXT &&
+ fileType <= LAST_AUDIO_FILE_TYPE_EXT));
}
public static boolean isVideoFileType(int fileType) {
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index d6bf421..59eaeef 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -19,6 +19,7 @@ package android.media;
import android.net.NetworkUtils;
import android.os.IBinder;
import android.os.StrictMode;
+import android.os.SystemProperties;
import android.util.Log;
import java.io.BufferedInputStream;
@@ -34,8 +35,14 @@ import java.net.NoRouteToHostException;
import java.net.ProtocolException;
import java.net.UnknownServiceException;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.Socket;
+import java.net.SocketAddress;
+
import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
/** @hide */
@@ -48,10 +55,14 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
private long mCurrentOffset = -1;
private URL mURL = null;
+ private int mProxyPort = 0;
+ private String mProxyIP;
private Map<String, String> mHeaders = null;
private HttpURLConnection mConnection = null;
private long mTotalSize = -1;
private InputStream mInputStream = null;
+ private List<String> mCookies = null;
+ private boolean mIsCookieUpdated = false;
private boolean mAllowCrossDomainRedirect = true;
private boolean mAllowCrossProtocolRedirect = true;
@@ -97,10 +108,21 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
/* returns true iff header is internal */
private boolean filterOutInternalHeaders(String key, String val) {
+ Log.d(TAG, "filterOutInternalHeaders: key=" + key + ", val=" + val);
if ("android-allow-cross-domain-redirect".equalsIgnoreCase(key)) {
mAllowCrossDomainRedirect = parseBoolean(val);
// cross-protocol redirects are also controlled by this flag
mAllowCrossProtocolRedirect = mAllowCrossDomainRedirect;
+ } else if ("use-proxy".equalsIgnoreCase(key)) {
+ Log.d(TAG, "filterOutInternalHeaders use-proxy " + val);
+ int colonPos = val.indexOf(":");
+ if (colonPos > 0) {
+ mProxyIP = new String((val.substring(0, colonPos)).trim());
+ mProxyPort = Integer.parseInt(val.substring(colonPos + 1));
+ Log.d(TAG, "sta-proxy-ip " + mProxyIP + " port " + mProxyPort);
+ }
+ } else if ("Cookie".equalsIgnoreCase(key) && mIsCookieUpdated) {
+ Log.d(TAG, "filterOutInternalHeaders: Cookie");
} else {
return false;
}
@@ -180,10 +202,19 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
boolean noProxy = isLocalHost(url);
while (true) {
- if (noProxy) {
- mConnection = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
+
+ Log.d(TAG, "proxy " + mProxyIP +" port "+ mProxyPort);
+ if (mProxyPort > 0) {
+ SocketAddress socketAddr = new InetSocketAddress(mProxyIP, mProxyPort);
+ java.net.Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, socketAddr);
+ mConnection = (HttpURLConnection) url.openConnection(proxy);
+ Log.d(TAG, "connection initialized with proxy");
} else {
- mConnection = (HttpURLConnection)url.openConnection();
+ if (noProxy) {
+ mConnection = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
+ } else {
+ mConnection = (HttpURLConnection)url.openConnection();
+ }
}
mConnection.setConnectTimeout(CONNECT_TIMEOUT_MS);
@@ -197,6 +228,14 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
}
}
+ if (mIsCookieUpdated) {
+ if (VERBOSE)
+ Log.d(TAG, "add Cookie in the request");
+ for (String cookie : mCookies) {
+ mConnection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
+ }
+ }
+
if (offset > 0) {
mConnection.setRequestProperty(
"Range", "bytes=" + offset + "-");
@@ -283,6 +322,16 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
throw new IOException();
} else {
mTotalSize = mConnection.getContentLength();
+ if (mConnection.getHeaderFields().containsKey("Set-Cookie")) {
+ mIsCookieUpdated = SystemProperties.getBoolean(
+ "persist.media.cookie.cust", false);
+ mCookies = mConnection.getHeaderFields().get("Set-Cookie");
+ if (VERBOSE) {
+ for (String cookie : mCookies) {
+ Log.d(TAG, "get Cookie" + cookie);
+ }
+ }
+ }
}
if (offset > 0 && response != HttpURLConnection.HTTP_PARTIAL) {
diff --git a/media/java/android/media/MediaMetadataEditor.java b/media/java/android/media/MediaMetadataEditor.java
index 566b93f..eeb8fe2 100644
--- a/media/java/android/media/MediaMetadataEditor.java
+++ b/media/java/android/media/MediaMetadataEditor.java
@@ -439,7 +439,7 @@ import android.util.SparseIntArray;
protected static final SparseIntArray METADATA_KEYS_TYPE;
static {
- METADATA_KEYS_TYPE = new SparseIntArray(17);
+ METADATA_KEYS_TYPE = new SparseIntArray(18);
// NOTE: if adding to the list below, make sure you increment the array initialization size
// keys with long values
METADATA_KEYS_TYPE.put(
@@ -465,5 +465,7 @@ import android.util.SparseIntArray;
// keys with Rating values
METADATA_KEYS_TYPE.put(RATING_KEY_BY_OTHERS, METADATA_TYPE_RATING);
METADATA_KEYS_TYPE.put(RATING_KEY_BY_USER, METADATA_TYPE_RATING);
+ // Meta data for total number of tracks in Album
+ METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
}
}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index a3ff080..7dd70d4 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -64,9 +64,7 @@ public class MediaMetadataRetriever
throw new IllegalArgumentException();
}
- FileInputStream is = null;
- try {
- is = new FileInputStream(path);
+ try (FileInputStream is = new FileInputStream(path)) {
FileDescriptor fd = is.getFD();
setDataSource(fd, 0, 0x7ffffffffffffffL);
} catch (FileNotFoundException fileEx) {
@@ -74,12 +72,6 @@ public class MediaMetadataRetriever
} catch (IOException ioEx) {
throw new IllegalArgumentException();
}
-
- try {
- if (is != null) {
- is.close();
- }
- } catch (Exception e) {}
}
/**
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 587d494..b3f25ee 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -3453,6 +3453,23 @@ public class MediaPlayer implements SubtitleController.Listener
mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
}
+ /** @hide
+ */
+ public boolean suspend() {
+ stayAwake(false);
+ return _suspend();
+ }
+
+ private native boolean _suspend();
+
+ /** @hide
+ */
+ public boolean resume() {
+ return _resume();
+ }
+
+ private native boolean _resume();
+
/** @hide */
static class TimeProvider implements MediaPlayer.OnSeekCompleteListener,
MediaTimeProvider {
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index ed2c4cbd..7112c1a 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -345,6 +345,13 @@ public class MediaRecorder
/** VP8/VORBIS data in a WEBM container */
public static final int WEBM = 9;
+
+ /** @hide QCP file format */
+ public static final int QCP = 20;
+
+ /** @hide WAVE media file format*/
+ public static final int WAVE = 21;
+
};
/**
@@ -369,6 +376,12 @@ public class MediaRecorder
public static final int AAC_ELD = 5;
/** Ogg Vorbis audio codec */
public static final int VORBIS = 6;
+ /** @hide EVRC audio codec */
+ public static final int EVRC = 10;
+ /** @hide QCELP audio codec */
+ public static final int QCELP = 11;
+ /** @hide Linear PCM audio codec */
+ public static final int LPCM = 12;
}
/**
@@ -385,6 +398,8 @@ public class MediaRecorder
public static final int H264 = 2;
public static final int MPEG_4_SP = 3;
public static final int VP8 = 4;
+ /** @hide **/
+ public static final int H265 = 1001;
}
/**
@@ -436,11 +451,12 @@ public class MediaRecorder
setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
setVideoEncodingBitRate(profile.videoBitRate);
setVideoEncoder(profile.videoCodec);
- if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
- profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
+ if ((profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
+ profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_2160P) ||
+ profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_VGA) {
// Nothing needs to be done. Call to setCaptureRate() enables
// time lapse video recording.
- } else {
+ } else if (profile.audioCodec >= 0) {
setAudioEncodingBitRate(profile.audioBitRate);
setAudioChannels(profile.audioChannels);
setAudioSamplingRate(profile.audioSampleRate);
@@ -792,6 +808,10 @@ public class MediaRecorder
*/
public native void start() throws IllegalStateException;
+ /** @hide
+ */
+ public native void pause() throws IllegalStateException;
+
/**
* Stops recording. Call this after start(). Once recording is stopped,
* you will have to configure it again as if it has just been constructed.
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 4c8085f..da1484c 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -63,6 +63,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Internal service helper that no-one should use directly.
@@ -351,6 +353,11 @@ public class MediaScanner
private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+ // For basic VorbisComment DATE tag support. It can take two forms, YYYY
+ // or YYYY-MM. This pattern is used to extract the year for compatibility
+ // with the ID3 YEAR tag.
+ private static final Pattern DATE_YEAR_DETECT_PATTERN = Pattern.compile("^(\\d{4})(-\\d{2})?$");
+
private static class FileEntry {
long mRowId;
String mPath;
@@ -632,6 +639,13 @@ public class MediaScanner
mGenre = getGenreName(value);
} else if (name.equalsIgnoreCase("year") || name.startsWith("year;")) {
mYear = parseSubstring(value, 0, 0);
+ } else if (mYear == 0 && name.equalsIgnoreCase("date") || name.startsWith("date;")) {
+ // Since Android doesn't support DATE tag itself, just use it to extract
+ // the year, if the YEAR tag isn't present.
+ Matcher m = DATE_YEAR_DETECT_PATTERN.matcher(value);
+ if (m.find()) {
+ mYear = parseSubstring(m.group(1), 0, 0);
+ }
} else if (name.equalsIgnoreCase("tracknumber") || name.startsWith("tracknumber;")) {
// track number might be of the form "2/12"
// we just read the number before the slash
@@ -1399,7 +1413,7 @@ public class MediaScanner
// always scan the file, so we can return the content://media Uri for existing files
return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(),
- false, true, MediaScanner.isNoMediaPath(path));
+ file.isDirectory(), true, MediaScanner.isNoMediaPath(path));
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
return null;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index c9a86d8..07b8c23 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -707,6 +707,79 @@ import java.lang.IllegalArgumentException;
}
}
+ /**
+ * @hide
+ */
+ public void playItemResponse(boolean success) {
+ Log.e(TAG, "playItemResponse");
+ playItemResponseInt(success);
+ }
+
+ private void playItemResponseInt(boolean success) {
+ Log.d(TAG, "playItemResponseInt");
+ Log.v(TAG, "success: " + success);
+
+ // USE_SESSIONS
+ if (mSession != null) {
+ mSession.playItemResponse(success);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void updateNowPlayingEntries(long[] playList) {
+ Log.e(TAG, "updateNowPlayingEntries: Item numbers: " + playList.length);
+ updateNowPlayingEntriesInt(playList);
+ }
+
+ private void updateNowPlayingEntriesInt(long[] playList) {
+ Log.d(TAG, "updateNowPlayingEntriesInt");
+
+ // USE_SESSIONS
+ if (mSession != null) {
+ mSession.updateNowPlayingEntries(playList);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void updateFolderInfoBrowsedPlayer(String stringUri) {
+ Log.e(TAG, "updateFolderInfoBrowsedPlayer");
+ synchronized(mCacheLock) {
+ updateFolderInfoBrowsedPlayerInt(stringUri);
+ }
+ }
+
+ private void updateFolderInfoBrowsedPlayerInt(String stringUri) {
+ Log.d(TAG, "updateFolderInfoBrowsedPlayerInt");
+
+ // USE_SESSIONS
+ if (mSession != null) {
+ mSession.updateFolderInfoBrowsedPlayer(stringUri);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void updateNowPlayingContentChange() {
+ Log.e(TAG, "updateNowPlayingContentChange");
+ synchronized(mCacheLock) {
+ updateNowPlayingContentChangeInt();
+ }
+ }
+
+ private void updateNowPlayingContentChangeInt() {
+ Log.d(TAG, "updateNowPlayingContentChangeInt");
+
+ // USE_SESSIONS
+ if (mSession != null) {
+ mSession.updateNowPlayingContentChange();
+ }
+ }
+
// TODO investigate if we still need position drift checking
private void onPositionDriftCheck() {
if (DEBUG) { Log.d(TAG, "onPositionDriftCheck()"); }
@@ -798,6 +871,56 @@ import java.lang.IllegalArgumentException;
}
}
+ /**
+ * @hide
+ */
+ public interface OnGetNowPlayingEntriesListener {
+ public abstract void onGetNowPlayingEntries();
+ }
+
+ /**
+ * @hide
+ */
+ public void setNowPlayingEntriesUpdateListener(OnGetNowPlayingEntriesListener l) {
+ Log.d(TAG, "setNowPlayingEntriesUpdateListener");
+ synchronized(mCacheLock) {
+ mGetNowPlayingEntriesListener = l;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public interface OnSetBrowsedPlayerListener {
+ public abstract void onSetBrowsedPlayer();
+ }
+
+ /**
+ * @hide
+ */
+ public void setBrowsedPlayerUpdateListener(OnSetBrowsedPlayerListener l) {
+ Log.d(TAG, "setBrowsedPlayerUpdateListener");
+ synchronized(mCacheLock) {
+ mSetBrowsedPlayerListener = l;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public interface OnSetPlayItemListener {
+ public abstract void onSetPlayItem(int scope, long uid);
+ }
+
+ /**
+ * @hide
+ */
+ public void setPlayItemListener(OnSetPlayItemListener l) {
+ Log.d(TAG, "setPlayItemListener");
+ synchronized(mCacheLock) {
+ mSetPlayItemListener = l;
+ }
+ }
/**
* Interface definition for a callback to be invoked when the media playback position is
@@ -946,6 +1069,13 @@ import java.lang.IllegalArgumentException;
/**
* The current remote control client generation ID across the system, as known by this object
*/
+
+ private OnSetBrowsedPlayerListener mSetBrowsedPlayerListener;
+
+ private OnSetPlayItemListener mSetPlayItemListener;
+
+ private OnGetNowPlayingEntriesListener mGetNowPlayingEntriesListener;
+
private int mCurrentClientGenId = -1;
/**
@@ -999,10 +1129,43 @@ import java.lang.IllegalArgumentException;
onUpdateMetadata(mCurrentClientGenId, MetadataEditor.RATING_KEY_BY_USER, rating);
}
}
+
+ @Override
+ public void setPlayItem(int scope, long uid) {
+ // only post messages, we can't block here
+ if (mEventHandler != null) {
+ mEventHandler.removeMessages(MSG_SET_PLAY_ITEM);
+ mEventHandler.sendMessage(mEventHandler.obtainMessage(
+ MSG_SET_PLAY_ITEM, 0 /* arg1 */, scope /* arg2, ignored */,
+ new Long(uid)));
+ }
+ }
+
+ @Override
+ public void getNowPlayingEntries() {
+ // only post messages, we can't block here
+ if (mEventHandler != null) {
+ mEventHandler.removeMessages(MSG_GET_NOW_PLAYING_ENTRIES);
+ mEventHandler.sendMessage(mEventHandler.obtainMessage(
+ MSG_GET_NOW_PLAYING_ENTRIES, 0, 0, null));
+ }
+ }
+
+ @Override
+ public void setBrowsedPlayer() {
+ Log.d(TAG, "setBrowsedPlayer in RemoteControlClient");
+ if (mEventHandler != null) {
+ mEventHandler.sendMessage(mEventHandler.obtainMessage(
+ MSG_SET_BROWSED_PLAYER, 0 /* arg1 */, 0 /* arg2*/, null));
+ }
+ }
};
private EventHandler mEventHandler;
private final static int MSG_POSITION_DRIFT_CHECK = 11;
+ private final static int MSG_SET_BROWSED_PLAYER = 12;
+ private final static int MSG_SET_PLAY_ITEM = 13;
+ private final static int MSG_GET_NOW_PLAYING_ENTRIES = 14;
private class EventHandler extends Handler {
public EventHandler(RemoteControlClient rcc, Looper looper) {
@@ -1015,6 +1178,16 @@ import java.lang.IllegalArgumentException;
case MSG_POSITION_DRIFT_CHECK:
onPositionDriftCheck();
break;
+ case MSG_SET_BROWSED_PLAYER:
+ Log.d(TAG, "MSG_SET_BROWSED_PLAYER in RemoteControlClient");
+ onSetBrowsedPlayer();
+ break;
+ case MSG_SET_PLAY_ITEM:
+ onSetPlayItem(msg.arg2, ((Long)msg.obj).longValue());
+ break;
+ case MSG_GET_NOW_PLAYING_ENTRIES:
+ onGetNowPlayingEntries();
+ break;
default:
Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler");
}
@@ -1040,6 +1213,36 @@ import java.lang.IllegalArgumentException;
}
}
+ private void onSetPlayItem(int scope, long uid) {
+ Log.d(TAG, "onSetPlayItem");
+ synchronized (mCacheLock) {
+ if (mSetPlayItemListener != null) {
+ Log.d(TAG, "mSetPlayItemListener.onSetPlayItem");
+ mSetPlayItemListener.onSetPlayItem(scope, uid);
+ }
+ }
+ }
+
+ private void onSetBrowsedPlayer() {
+ Log.d(TAG, "onSetBrowsedPlayer");
+ synchronized (mCacheLock) {
+ if (mSetBrowsedPlayerListener != null) {
+ Log.d(TAG, "mSetBrowsedPlayerListener.onSetBrowsedPlayer");
+ mSetBrowsedPlayerListener.onSetBrowsedPlayer();
+ }
+ }
+ }
+
+ private void onGetNowPlayingEntries() {
+ Log.d(TAG, "onGetNowPlayingEntries");
+ synchronized (mCacheLock) {
+ if (mGetNowPlayingEntriesListener != null) {
+ Log.d(TAG, "mGetNowPlayingEntriesListener.onGetNowPlayingEntries");
+ mGetNowPlayingEntriesListener.onGetNowPlayingEntries();
+ }
+ }
+ }
+
//===========================================================
// Internal utilities
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index d84cf30..aba7ad6 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -88,6 +88,7 @@ import java.util.List;
private boolean mIsRegistered = false;
private PendingIntent mClientPendingIntentCurrent;
private OnClientUpdateListener mOnClientUpdateListener;
+ private OnClientAvrcpUpdateListener mOnClientAvrcpUpdateListener;
private PlaybackInfo mLastPlaybackInfo;
private int mArtworkWidth = -1;
private int mArtworkHeight = -1;
@@ -150,6 +151,25 @@ import java.util.List;
}
}
+ /**
+ * @hide
+ */
+ public RemoteController(Context context, OnClientUpdateListener updateListener, Looper looper,
+ OnClientAvrcpUpdateListener avrcpUpdateListener) throws IllegalArgumentException {
+ this(context, updateListener, looper);
+ mOnClientAvrcpUpdateListener = avrcpUpdateListener;
+ }
+
+ /**
+ * @hide
+ */
+ public interface OnClientAvrcpUpdateListener {
+ public void onClientFolderInfoBrowsedPlayer(String stringUri);
+ public void onClientUpdateNowPlayingEntries(long[] playList);
+ public void onClientNowPlayingContentChange();
+ public void onClientPlayItemResponse(boolean success);
+ };
+
/**
* Interface definition for the callbacks to be invoked whenever media events, metadata
@@ -355,6 +375,7 @@ import java.util.List;
* @throws IllegalArgumentException
*/
public boolean seekTo(long timeMs) throws IllegalArgumentException {
+ Log.e(TAG, "seekTo() in RemoteController");
if (!mEnabled) {
Log.e(TAG, "Cannot use seekTo() from a disabled RemoteController");
return false;
@@ -370,6 +391,69 @@ import java.util.List;
return true;
}
+ /**
+ * @hide
+ * Request the user of a RemoteControlClient to play the requested item.
+ * @param generationId the RemoteControlClient generation counter for which this request is
+ * issued.
+ * @param uid uid of the song to be played.
+ * @scope scope of the file system to use
+ */
+ public void setRemoteControlClientPlayItem(long uid, int scope) {
+ Log.e(TAG, "setRemoteControlClientPlayItem()");
+ if (!mEnabled) {
+ Log.e(TAG, "Cannot use setRemoteControlClientPlayItem()" +
+ " from a disabled RemoteController");
+ return;
+ }
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ mCurrentSession.getTransportControls().setRemoteControlClientPlayItem(uid, scope);
+ }
+ }
+ return;
+ }
+
+ /**
+ * @hide
+ * Request the user of a RemoteControlClient to provide with the now playing list entries.
+ * @param generationId the RemoteControlClient generation counter for which this request is
+ * issued.
+ */
+ public void getRemoteControlClientNowPlayingEntries() {
+ Log.e(TAG, "getRemoteControlClientNowPlayingEntries()");
+ if (!mEnabled) {
+ Log.e(TAG, "Cannot use getRemoteControlClientNowPlayingEntries()" +
+ " from a disabled RemoteController");
+ return;
+ }
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ mCurrentSession.getTransportControls().getRemoteControlClientNowPlayingEntries();
+ }
+ }
+ return;
+ }
+
+ /**
+ * @hide
+ * Request the user of a RemoteControlClient to set the music player as current browsed player.
+ * @param packageName package name of the targeted media player.
+ */
+ public void setRemoteControlClientBrowsedPlayer() {
+ Log.e(TAG, "setRemoteControlClientBrowsedPlayer()");
+ if (!mEnabled) {
+ Log.e(TAG, "Cannot use setRemoteControlClientBrowsedPlayer()" +
+ " from a disabled RemoteController");
+ return;
+ }
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ mCurrentSession.getTransportControls().setRemoteControlClientBrowsedPlayer();
+ }
+ }
+ return;
+ }
/**
* @hide
@@ -704,6 +788,30 @@ import java.util.List;
public void onMetadataChanged(MediaMetadata metadata) {
onNewMediaMetadata(metadata);
}
+
+ @Override
+ public void onUpdateFolderInfoBrowsedPlayer(String stringUri) {
+ Log.d(TAG, "MediaControllerCallback: onUpdateFolderInfoBrowsedPlayer");
+ onFolderInfoBrowsedPlayer(stringUri);
+ }
+
+ @Override
+ public void onUpdateNowPlayingEntries(long[] playList) {
+ Log.d(TAG, "MediaControllerCallback: onUpdateNowPlayingEntries");
+ onNowPlayingEntriesUpdate(playList);
+ }
+
+ @Override
+ public void onUpdateNowPlayingContentChange() {
+ Log.d(TAG, "MediaControllerCallback: onUpdateNowPlayingContentChange");
+ onNowPlayingContentChange();
+ }
+
+ @Override
+ public void onPlayItemResponse(boolean success) {
+ Log.d(TAG, "MediaControllerCallback: onPlayItemResponse");
+ onSetPlayItemResponse(success);
+ }
}
/**
@@ -980,6 +1088,8 @@ import java.util.List;
synchronized (mInfoLock) {
if (controller == null) {
if (mCurrentSession != null) {
+ Log.v(TAG, "Updating current controller as null");
+ mAudioManager.updateMediaPlayerList(mCurrentSession.getPackageName(), false);
mCurrentSession.unregisterCallback(mSessionCb);
mCurrentSession = null;
sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
@@ -989,13 +1099,21 @@ import java.util.List;
|| !controller.getSessionToken()
.equals(mCurrentSession.getSessionToken())) {
if (mCurrentSession != null) {
+ Log.v(TAG, "Updating current controller package as " +
+ controller.getPackageName() + " from " + mCurrentSession.getPackageName());
mCurrentSession.unregisterCallback(mSessionCb);
+ } else {
+ Log.v(TAG, "Updating current controller package as " +
+ controller.getPackageName() + " from null");
}
+
sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
0 /* genId */, 0 /* clearing */, null /* obj */, 0 /* delay */);
mCurrentSession = controller;
mCurrentSession.registerCallback(mSessionCb, mEventHandler);
+ mAudioManager.updateMediaPlayerList(mCurrentSession.getPackageName(), true);
+
PlaybackState state = controller.getPlaybackState();
sendMsg(mEventHandler, MSG_NEW_PLAYBACK_STATE, SENDMSG_REPLACE,
0 /* genId */, 0, state /* obj */, 0 /* delay */);
@@ -1052,6 +1170,74 @@ import java.util.List;
}
}
+ private void onFolderInfoBrowsedPlayer(String stringUri) {
+ Log.d(TAG, "RemoteController: onFolderInfoBrowsedPlayer");
+ final OnClientAvrcpUpdateListener l;
+
+ synchronized(mInfoLock) {
+ l = mOnClientAvrcpUpdateListener;
+ }
+
+ try {
+ if (l != null) {
+ l.onClientFolderInfoBrowsedPlayer(stringUri);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error Updating AVRCP on receiving Browsed player response", e);
+ }
+ }
+
+ private void onNowPlayingEntriesUpdate(long[] playList) {
+ Log.d(TAG, "RemoteController: onUpdateNowPlayingEntries");
+ final OnClientAvrcpUpdateListener l;
+
+ synchronized(mInfoLock) {
+ l = mOnClientAvrcpUpdateListener;
+ }
+
+ try {
+ if (l != null) {
+ l.onClientUpdateNowPlayingEntries(playList);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error Updating AVRCP on receiving Now Playing Entries", e);
+ }
+ }
+
+ private void onNowPlayingContentChange() {
+ Log.d(TAG, "RemoteController: onNowPlayingContentChange");
+ final OnClientAvrcpUpdateListener l;
+
+ synchronized(mInfoLock) {
+ l = mOnClientAvrcpUpdateListener;
+ }
+
+ try {
+ if (l != null) {
+ l.onClientNowPlayingContentChange();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error Updating AVRCP on Now Playing Content Change", e);
+ }
+ }
+
+ private void onSetPlayItemResponse(boolean success) {
+ Log.d(TAG, "RemoteController: onPlayItemResponse");
+ final OnClientAvrcpUpdateListener l;
+
+ synchronized(mInfoLock) {
+ l = mOnClientAvrcpUpdateListener;
+ }
+
+ try {
+ if (l != null) {
+ l.onClientPlayItemResponse(success);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error Updating AVRCP on receiving Play Item response", e);
+ }
+ }
+
//==================================================
private static class PlaybackInfo {
int mState;
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index c2bcd93..2f96d1f 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -214,8 +214,14 @@ public class Ringtone {
if (Settings.AUTHORITY.equals(authority)) {
if (followSettingsUri) {
- Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context,
- RingtoneManager.getDefaultType(uri));
+ Uri actualUri;
+ if (RingtoneManager.getDefaultType(uri) == RingtoneManager.TYPE_RINGTONE) {
+ actualUri = RingtoneManager.getActualRingtoneUriBySubId(context,
+ RingtoneManager.getDefaultRingtoneSubIdByUri(uri));
+ } else {
+ actualUri = RingtoneManager.getActualDefaultRingtoneUri(context,
+ RingtoneManager.getDefaultType(uri));
+ }
String actualTitle = getTitle(
context, actualUri, false /*followSettingsUri*/, allowRemote);
title = context
@@ -412,9 +418,9 @@ public class Ringtone {
private boolean playFallbackRingtone() {
if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
!= 0) {
- int ringtoneType = RingtoneManager.getDefaultType(mUri);
- if (ringtoneType == -1 ||
- RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) != null) {
+ int subId = RingtoneManager.getDefaultRingtoneSubIdByUri(mUri);
+ if (subId != -1 &&
+ RingtoneManager.getActualRingtoneUriBySubId(mContext, subId) != null) {
// Default ringtone, try fallback ringtone.
try {
AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 025029e..fe4c91b 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -184,6 +184,16 @@ public class RingtoneManager {
*/
public static final String EXTRA_RINGTONE_PICKED_URI =
"android.intent.extra.ringtone.PICKED_URI";
+
+ /**
+ * Set the resource id theme to use for the dialog picker activity.<br/>
+ * The default theme is <code>com.android.internal.R.Theme_Holo_Dialog_Alert</code>.
+ *
+ * @see #ACTION_RINGTONE_PICKER
+ * @hide
+ */
+ public static final String EXTRA_RINGTONE_DIALOG_THEME =
+ "android.intent.extra.ringtone.DIALOG_THEME";
// Make sure the column ordering and then ..._COLUMN_INDEX are in sync
@@ -690,7 +700,9 @@ public class RingtoneManager {
public static int getDefaultType(Uri defaultRingtoneUri) {
if (defaultRingtoneUri == null) {
return -1;
- } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) {
+ } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI) ||
+ defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI_2) ||
+ defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI_3)) {
return TYPE_RINGTONE;
} else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) {
return TYPE_NOTIFICATION;
@@ -721,5 +733,106 @@ public class RingtoneManager {
return null;
}
}
-
+
+ /**
+ * Returns the subscription ID of {@link Uri}.
+ *
+ * @param defaultRingtoneUri The default {@link Uri}. For example,
+ * {@link System#DEFAULT_RINGTONE_URI},
+ * {@link System#DEFAULT_RINGTONE_URI_2}, or
+ * {@link System#DEFAULT_RINGTONE_URI_3}.
+ * @return The Subscription ID of the defaultRingtoneUri, or -1.
+ * @hide
+ */
+ public static int getDefaultRingtoneSubIdByUri(Uri defaultRingtoneUri) {
+ if (defaultRingtoneUri == null) {
+ return -1;
+ }
+ /**
+ * URI is encoded as below:
+ * DEFAULT_RINGTONE_URI: content://settings/system/ringtone
+ * DEFAULT_RINGTONE_URI_2: content://settings/system/ringtone_2
+ * DEFAULT_RINGTONE_URI_3: content://settings/system/ringtone_3
+ */
+ if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) {
+ return 0; /* Sub-1 */
+ }
+ final String uriString = defaultRingtoneUri.toString();
+ int parsedSubId = -1;
+ if (uriString.startsWith(Settings.System.DEFAULT_RINGTONE_URI.toString())) {
+ parsedSubId = Integer.parseInt(uriString.substring(uriString.lastIndexOf("_") + 1));
+ if ((parsedSubId > 0 && parsedSubId <= Settings.System.MAX_NUM_RINGTONES)) {
+ return parsedSubId - 1;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Gets the actual default sound's {@link Uri}. This will give the actual
+ * sound {@link Uri}, instead of using this, most clients can use
+ * {@link System#DEFAULT_RINGTONE_URI}.
+ *
+ * @param subId The Subscription ID.
+ * @return A {@link Uri} pointing to the default sound for the sound type.
+ * @hide
+ */
+ public static Uri getDefaultRingtoneUriBySubId(int subId) {
+ if (!(subId >= 0 && subId < Settings.System.MAX_NUM_RINGTONES)) {
+ return null;
+ }
+ if (subId == 0) {
+ return Settings.System.DEFAULT_RINGTONE_URI;
+ } else {
+ final String uriString =
+ Settings.System.DEFAULT_RINGTONE_URI.toString() + "_" + (subId + 1);
+ return Uri.parse(uriString);
+ }
+ }
+
+ /**
+ * Gets the current default sound's {@link Uri}. This will give the actual
+ * sound {@link Uri}, instead of using this, most clients can use
+ * {@link System#DEFAULT_RINGTONE_URI}.
+ *
+ * @param context A context used for querying.
+ * @param subId The Subscription ID.
+ * @return A {@link Uri} pointing to the default sound for the sound type.
+ * @hide
+ */
+ public static Uri getActualRingtoneUriBySubId(Context context, int subId) {
+ if (!(subId >= 0 && subId < Settings.System.MAX_NUM_RINGTONES)) {
+ return null;
+ }
+ String setting;
+ if (subId == 0) {
+ setting = Settings.System.RINGTONE;
+ } else {
+ setting = Settings.System.RINGTONE + "_" + (subId + 1);
+ }
+ final String uriString = Settings.System.getString(context.getContentResolver(), setting);
+ return uriString != null ? Uri.parse(uriString) : null;
+ }
+
+ /**
+ * Sets the {@link Uri} of the default sound for a given sound type.
+ *
+ * @param context A context used for querying.
+ * @param subId The Subscription ID.
+ * @param ringtoneUri A {@link Uri} pointing to the default sound to set.
+ * @hide
+ */
+ public static void setActualRingtoneUriBySubId(Context context, int subId, Uri ringtoneUri) {
+ if (!(subId >= 0 && subId < Settings.System.MAX_NUM_RINGTONES)) {
+ return;
+ }
+ String setting;
+ if (subId == 0) {
+ setting = Settings.System.RINGTONE;
+ } else {
+ setting = Settings.System.RINGTONE + "_" + (subId + 1);
+ }
+ Settings.System.putString(context.getContentResolver(), setting,
+ ringtoneUri != null ? ringtoneUri.toString() : null);
+ }
}
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index 4661226..08c49e7 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -728,13 +728,24 @@ public class ToneGenerator
* @see #ToneGenerator(int, int)
*/
public static final int TONE_CDMA_SIGNAL_OFF = 98;
+ /**
+ * SUPERVISORY_CH - 440Hz
+ *
+ * @hide #ToneGenerator(int, int)
+ */
+ public static final int TONE_SUPERVISORY_CH = 100;
+ /**
+ * HOLD_RECALL - 440Hz
+ *
+ * @hide #ToneGenerator(int, int)
+ */
+ public static final int TONE_HOLD_RECALL = 99;
/** Maximum volume, for use with {@link #ToneGenerator(int,int)} */
public static final int MAX_VOLUME = 100;
/** Minimum volume setting, for use with {@link #ToneGenerator(int,int)} */
public static final int MIN_VOLUME = 0;
-
/**
* ToneGenerator class contructor specifying output stream type and volume.
*
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index bd0019f..34eadcb 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -45,6 +45,10 @@ interface ISession {
void setQueueTitle(CharSequence title);
void setExtras(in Bundle extras);
void setRatingType(int type);
+ void playItemResponse(boolean success);
+ void updateNowPlayingEntries(in long[] playList);
+ void updateFolderInfoBrowsedPlayer(String stringUri);
+ void updateNowPlayingContentChange();
// These commands relate to volume handling
void setPlaybackToLocal(in AudioAttributes attributes);
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index adb6b06..ed13ff6 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -41,6 +41,9 @@ oneway interface ISessionCallback {
void onFastForward();
void onRewind();
void onSeekTo(long pos);
+ void setRemoteControlClientBrowsedPlayer();
+ void setRemoteControlClientPlayItem(long uid, int scope);
+ void getRemoteControlClientNowPlayingEntries();
void onRate(in Rating rating);
void onCustomAction(String action, in Bundle args);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 285e5f7..006ffac 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -62,6 +62,9 @@ interface ISessionController {
void fastForward();
void rewind();
void seekTo(long pos);
+ void setRemoteControlClientBrowsedPlayer();
+ void setRemoteControlClientPlayItem(long uid, int scope);
+ void getRemoteControlClientNowPlayingEntries();
void rate(in Rating rating);
void sendCustomAction(String action, in Bundle args);
MediaMetadata getMetadata();
diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
index cf31767..a5ad913 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -36,4 +36,8 @@ oneway interface ISessionControllerCallback {
void onQueueTitleChanged(CharSequence title);
void onExtrasChanged(in Bundle extras);
void onVolumeInfoChanged(in ParcelableVolumeInfo info);
+ void onPlayItemResponse(boolean success);
+ void onUpdateNowPlayingEntries(in long[] playList);
+ void onUpdateFolderInfoBrowsedPlayer(String stringUri);
+ void onUpdateNowPlayingContentChange();
}
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index b1a51a5..f1f9516 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -64,6 +64,10 @@ public final class MediaController {
private static final int MSG_UPDATE_QUEUE_TITLE = 6;
private static final int MSG_UPDATE_EXTRAS = 7;
private static final int MSG_DESTROYED = 8;
+ private static final int MSG_FOLDER_INFO_BROWSED_PLAYER = 9;
+ private static final int MSG_UPDATE_NOWPLAYING_ENTRIES = 10;
+ private static final int MSG_UPDATE_NOWPLAYING_CONTENT_CHANGE = 11;
+ private static final int MSG_PLAY_ITEM_RESPONSE = 12;
private final ISessionController mSessionBinder;
@@ -579,6 +583,31 @@ public final class MediaController {
*/
public void onAudioInfoChanged(PlaybackInfo info) {
}
+
+ /**
+ * @hide
+ */
+ public void onUpdateFolderInfoBrowsedPlayer(String stringUri) {
+ }
+
+ /**
+ * @hide
+ */
+ public void onUpdateNowPlayingEntries(long[] playList) {
+ }
+
+ /**
+ * @hide
+ */
+ public void onUpdateNowPlayingContentChange() {
+ }
+
+ /**
+ * @hide
+ */
+ public void onPlayItemResponse(boolean success) {
+ }
+
}
/**
@@ -704,6 +733,7 @@ public final class MediaController {
* @param pos Position to move to, in milliseconds.
*/
public void seekTo(long pos) {
+ Log.d(TAG, "seekTo in TransportControls");
try {
mSessionBinder.seekTo(pos);
} catch (RemoteException e) {
@@ -712,6 +742,42 @@ public final class MediaController {
}
/**
+ * @hide
+ */
+ public void setRemoteControlClientBrowsedPlayer() {
+ Log.d(TAG, "setRemoteControlClientBrowsedPlayer in TransportControls");
+ try {
+ mSessionBinder.setRemoteControlClientBrowsedPlayer();
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling setRemoteControlClientBrowsedPlayer.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setRemoteControlClientPlayItem(long uid, int scope) {
+ Log.d(TAG, "setRemoteControlClientPlayItem in TransportControls");
+ try {
+ mSessionBinder.setRemoteControlClientPlayItem(uid, scope);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling setRemoteControlClientPlayItem.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void getRemoteControlClientNowPlayingEntries() {
+ Log.d(TAG, "getRemoteControlClientNowPlayingEntries in TransportControls");
+ try {
+ mSessionBinder.getRemoteControlClientNowPlayingEntries();
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling getRemoteControlClientNowPlayingEntries.", e);
+ }
+ }
+
+ /**
* Start fast forwarding. If playback is already fast forwarding this
* may increase the rate.
*/
@@ -973,6 +1039,42 @@ public final class MediaController {
}
}
+ @Override
+ public void onUpdateFolderInfoBrowsedPlayer(String stringUri) {
+ Log.d(TAG, "CallBackStub: onUpdateFolderInfoBrowsedPlayer");
+ MediaController controller = mController.get();
+ if (controller != null) {
+ controller.postMessage(MSG_FOLDER_INFO_BROWSED_PLAYER, stringUri, null);
+ }
+ }
+
+ @Override
+ public void onUpdateNowPlayingEntries(long[] playList) {
+ Log.d(TAG, "CallBackStub: onUpdateNowPlayingEntries");
+ MediaController controller = mController.get();
+ if (controller != null) {
+ controller.postMessage(MSG_UPDATE_NOWPLAYING_ENTRIES, playList, null);
+ }
+ }
+
+ @Override
+ public void onUpdateNowPlayingContentChange() {
+ Log.d(TAG, "CallBackStub: onUpdateNowPlayingContentChange");
+ MediaController controller = mController.get();
+ if (controller != null) {
+ controller.postMessage(MSG_UPDATE_NOWPLAYING_CONTENT_CHANGE, null, null);
+ }
+ }
+
+ @Override
+ public void onPlayItemResponse(boolean success) {
+ Log.d(TAG, "CallBackStub: onPlayItemResponse");
+ MediaController controller = mController.get();
+ if (controller != null) {
+ controller.postMessage(MSG_PLAY_ITEM_RESPONSE, new Boolean(success), null);
+ }
+ }
+
}
private final static class MessageHandler extends Handler {
@@ -1014,6 +1116,18 @@ public final class MediaController {
case MSG_DESTROYED:
mCallback.onSessionDestroyed();
break;
+ case MSG_FOLDER_INFO_BROWSED_PLAYER:
+ mCallback.onUpdateFolderInfoBrowsedPlayer((String) msg.obj);
+ break;
+ case MSG_UPDATE_NOWPLAYING_ENTRIES:
+ mCallback.onUpdateNowPlayingEntries((long[]) msg.obj);
+ break;
+ case MSG_UPDATE_NOWPLAYING_CONTENT_CHANGE:
+ mCallback.onUpdateNowPlayingContentChange();
+ break;
+ case MSG_PLAY_ITEM_RESPONSE:
+ mCallback.onPlayItemResponse(((Boolean)(msg.obj)).booleanValue());
+ break;
}
}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e1e9b79..be89dfc 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -493,6 +493,58 @@ public final class MediaSession {
}
/**
+ * @hide
+ */
+ public void playItemResponse(boolean success) {
+ Log.d(TAG, "MediaSession: playItemResponse");
+
+ try {
+ mBinder.playItemResponse(success);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Dead object in playItemResponse.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void updateNowPlayingEntries(long[] playList) {
+ Log.d(TAG, "MediaSession: updateNowPlayingEntries");
+
+ try {
+ mBinder.updateNowPlayingEntries(playList);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Dead object in updateNowPlayingEntries.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void updateFolderInfoBrowsedPlayer(String stringUri) {
+ Log.d(TAG, "MediaSession: updateFolderInfoBrowsedPlayer");
+
+ try {
+ mBinder.updateFolderInfoBrowsedPlayer(stringUri);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Dead object in updateFolderInfoBrowsedPlayer.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void updateNowPlayingContentChange() {
+ Log.d(TAG, "MediaSession: updateNowPlayingContentChange");
+
+ try {
+ mBinder.updateNowPlayingContentChange();
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Dead object in updateNowPlayingContentChange.", e);
+ }
+ }
+
+ /**
* Notify the system that the remote volume changed.
*
* @param provider The provider that is handling volume changes.
@@ -572,6 +624,34 @@ public final class MediaSession {
postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent);
}
+ private void dispatchSetBrowsedPlayerCommand() {
+ postToCallback(CallbackMessageHandler.MSG_SET_BROWSED_PLAYER);
+ }
+
+ private void dispatchSetPlayItemCommand(long uid, int scope) {
+ PlayItemToken playItemToken = new PlayItemToken(uid, scope);
+ postToCallback(CallbackMessageHandler.MSG_SET_PLAY_ITEM, playItemToken);
+ }
+
+ private class PlayItemToken {
+ private long mUid;
+ private int mScope;
+ public PlayItemToken(long uid, int scope) {
+ mUid = uid;
+ mScope = scope;
+ }
+ public int getScope() {
+ return mScope;
+ }
+ public long getUid() {
+ return mUid;
+ }
+ }
+
+ private void dispatchGetNowPlayingItemsCommand() {
+ postToCallback(CallbackMessageHandler.MSG_GET_NOW_PLAYING_ITEMS);
+ }
+
private void dispatchAdjustVolume(int direction) {
postToCallback(CallbackMessageHandler.MSG_ADJUST_VOLUME, direction);
}
@@ -894,6 +974,25 @@ public final class MediaSession {
*/
public void onCustomAction(@NonNull String action, @Nullable Bundle extras) {
}
+
+ /**
+ * @hide
+ */
+ public void setBrowsedPlayer() {
+ }
+
+ /**
+ * @hide
+ */
+ public void setPlayItem(int scope, long uid) {
+ }
+
+ /**
+ * @hide
+ */
+ public void getNowPlayingEntries() {
+ }
+
}
/**
@@ -1034,6 +1133,33 @@ public final class MediaSession {
}
@Override
+ public void setRemoteControlClientBrowsedPlayer() throws RemoteException {
+ Log.d(TAG, "setRemoteControlClientBrowsedPlayer in CallbackStub");
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchSetBrowsedPlayerCommand();
+ }
+ }
+
+ @Override
+ public void setRemoteControlClientPlayItem(long uid, int scope) throws RemoteException {
+ Log.d(TAG, "setRemoteControlClientPlayItem in CallbackStub");
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchSetPlayItemCommand(uid, scope);
+ }
+ }
+
+ @Override
+ public void getRemoteControlClientNowPlayingEntries() throws RemoteException {
+ Log.d(TAG, "getRemoteControlClientNowPlayingEntries in CallbackStub");
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchGetNowPlayingItemsCommand();
+ }
+ }
+
+ @Override
public void onCustomAction(String action, Bundle args) {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1173,6 +1299,9 @@ public final class MediaSession {
private static final int MSG_ADJUST_VOLUME = 16;
private static final int MSG_SET_VOLUME = 17;
private static final int MSG_PLAY_URI = 18;
+ private static final int MSG_SET_BROWSED_PLAYER = 19;
+ private static final int MSG_SET_PLAY_ITEM = 20;
+ private static final int MSG_GET_NOW_PLAYING_ITEMS = 21;
private MediaSession.Callback mCallback;
@@ -1267,6 +1396,18 @@ public final class MediaSession {
if (vp != null) {
vp.onSetVolumeTo((int) msg.obj);
}
+ case MSG_SET_BROWSED_PLAYER:
+ Log.d(TAG, "MSG_SET_BROWSED_PLAYER received in CallbackMessageHandler");
+ mCallback.setBrowsedPlayer();
+ break;
+ case MSG_SET_PLAY_ITEM:
+ Log.d(TAG, "MSG_SET_PLAY_ITEM received in CallbackMessageHandler");
+ PlayItemToken playItemToken = (PlayItemToken) msg.obj;
+ mCallback.setPlayItem(playItemToken.getScope(), playItemToken.getUid());
+ break;
+ case MSG_GET_NOW_PLAYING_ITEMS:
+ Log.d(TAG, "MSG_GET_NOW_PLAYING_ITEMS received in CallbackMessageHandler");
+ mCallback.getNowPlayingEntries();
break;
}
}
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index c61d7ad..22082b9 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -549,6 +549,27 @@ public class MediaSessionLegacyHelper {
mRccListener.onSetRating(rating);
}
}
+
+ @Override
+ public void setBrowsedPlayer() {
+ if (mRccListener != null) {
+ mRccListener.setBrowsedPlayer();
+ }
+ }
+
+ @Override
+ public void setPlayItem(int scope, long uid) {
+ if (mRccListener != null) {
+ mRccListener.setPlayItem(scope, uid);
+ }
+ }
+
+ @Override
+ public void getNowPlayingEntries() {
+ if (mRccListener != null) {
+ mRccListener.getNowPlayingEntries();
+ }
+ }
}
}
}
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 3814630..e830afd 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -56,6 +56,10 @@ public class MtpServer implements Runnable {
native_send_device_property_changed(property);
}
+ public void sendObjectUpdated(int handle) {
+ native_send_object_updated(handle);
+ }
+
public void addStorage(MtpStorage storage) {
native_add_storage(storage);
}
@@ -70,6 +74,7 @@ public class MtpServer implements Runnable {
private native final void native_send_object_added(int handle);
private native final void native_send_object_removed(int handle);
private native final void native_send_device_property_changed(int property);
+ private native final void native_send_object_updated(int handle);
private native final void native_add_storage(MtpStorage storage);
private native final void native_remove_storage(int storageId);
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d8041f4..88670ea 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -49,6 +49,7 @@
#include <gui/Surface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <dlfcn.h>
#include "android_util_Binder.h"
// ----------------------------------------------------------------------------
@@ -137,6 +138,153 @@ void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *o
}
}
+
+static const char *EXTMEDIAJNI_LIB_NAME = "libextmedia_jni.so";
+static const char *kCreateJNIExtMediaPlayerListener = "CreateJNIExtMediaPlayerListener";
+static const char *kCheckExtMedia = "checkExtMedia";
+static const char *kCreateNativeQCMediaPlayer = "CreateNativeQCMediaPlayer";
+typedef MediaPlayerListener* (*CreateJNIExtMediaPlayerListenerFn)(JNIEnv *, jobject, jobject, sp<MediaPlayerListener> listener);
+typedef bool (*CheckExtMediaFn)(JNIEnv *env, jobject);
+typedef MediaPlayer* (*CreateNativeQCMediaPlayerFn)();
+
+
+
+class JNIMediaPlayerFactory {
+ public:
+ JNIMediaPlayerFactory() {};
+ static bool CheckAndCreateExtMediaPlayer(JNIEnv *env, jobject thiz, jobject weak_this, sp<MediaPlayerListener> &listener, sp<MediaPlayer> &mp);
+ private:
+ static void *mLibHandle;
+ static void loadLib();
+
+ static CreateJNIExtMediaPlayerListenerFn loadJNIExtMediaPlayerListener();
+ static CreateJNIExtMediaPlayerListenerFn sExtDashListnerFnPtr;
+
+ static CheckExtMediaFn sExtMediaFn;
+ static CheckExtMediaFn loadExtMedia();
+
+ static CreateNativeQCMediaPlayerFn sNativeQCMediaPlayerFn;
+ static CreateNativeQCMediaPlayerFn loadNativeQCMediaPlayer();
+
+ static sp<MediaPlayerListener> createExtMediaPlayerListener(JNIEnv *env, jobject thiz, jobject weak_this, sp<MediaPlayerListener> listener);
+ static bool checkExtMedia(JNIEnv *env, jobject thiz);
+ static void CreateNativeQCMediaPlayer(sp<MediaPlayer> &mp);
+};
+
+void *JNIMediaPlayerFactory::mLibHandle = NULL;
+
+CreateJNIExtMediaPlayerListenerFn JNIMediaPlayerFactory::sExtDashListnerFnPtr =
+ JNIMediaPlayerFactory::loadJNIExtMediaPlayerListener();
+
+CheckExtMediaFn JNIMediaPlayerFactory::sExtMediaFn =
+ JNIMediaPlayerFactory::loadExtMedia();
+
+CreateNativeQCMediaPlayerFn JNIMediaPlayerFactory::sNativeQCMediaPlayerFn =
+ JNIMediaPlayerFactory::loadNativeQCMediaPlayer();
+
+
+void JNIMediaPlayerFactory::loadLib()
+{
+ if (!mLibHandle) {
+ mLibHandle = ::dlopen(EXTMEDIAJNI_LIB_NAME, RTLD_LAZY);
+ if (!mLibHandle) {
+ ALOGV("%s", dlerror());
+ return;
+ }
+ ALOGV("Opened %s", EXTMEDIAJNI_LIB_NAME);
+ }
+}
+
+CreateJNIExtMediaPlayerListenerFn JNIMediaPlayerFactory::loadJNIExtMediaPlayerListener()
+{
+ loadLib();
+ CreateJNIExtMediaPlayerListenerFn pCreateExtDashListnerFnPtr = NULL;
+ if (mLibHandle != NULL) {
+ pCreateExtDashListnerFnPtr = (CreateJNIExtMediaPlayerListenerFn)
+ dlsym(mLibHandle, kCreateJNIExtMediaPlayerListener);
+ if (pCreateExtDashListnerFnPtr == NULL) {
+ ALOGW("Failed to load symbol %s : %s", kCreateJNIExtMediaPlayerListener, dlerror());
+ }
+ }
+ return pCreateExtDashListnerFnPtr;
+}
+
+CheckExtMediaFn JNIMediaPlayerFactory::loadExtMedia()
+{
+ loadLib();
+ CheckExtMediaFn pCheckExtMediaFnPtr = NULL;
+ if (mLibHandle != NULL) {
+ pCheckExtMediaFnPtr = (CheckExtMediaFn)dlsym(mLibHandle, kCheckExtMedia);
+ if (pCheckExtMediaFnPtr == NULL) {
+ ALOGW("Failed to load symbol %s : %s", kCheckExtMedia, dlerror());
+ }
+ }
+ return pCheckExtMediaFnPtr;
+}
+
+CreateNativeQCMediaPlayerFn JNIMediaPlayerFactory::loadNativeQCMediaPlayer()
+{
+ loadLib();
+ CreateNativeQCMediaPlayerFn pCreateNativeQCMediaPlayerFnPtr = NULL;
+ if (mLibHandle != NULL) {
+ pCreateNativeQCMediaPlayerFnPtr = (CreateNativeQCMediaPlayerFn)
+ dlsym(mLibHandle, kCreateNativeQCMediaPlayer);
+ if (pCreateNativeQCMediaPlayerFnPtr == NULL) {
+ ALOGW("Failed to load symbol %s : %s", kCreateNativeQCMediaPlayer, dlerror());
+ }
+ }
+ return pCreateNativeQCMediaPlayerFnPtr;
+}
+
+
+sp<MediaPlayerListener> JNIMediaPlayerFactory::createExtMediaPlayerListener(JNIEnv *env, jobject thiz, jobject weak_this, sp<MediaPlayerListener> listener)
+{
+ if (checkExtMedia(env, thiz)) {
+ if (sExtDashListnerFnPtr ) {
+ listener = (*sExtDashListnerFnPtr)(env, thiz, weak_this, listener);
+ if (listener != NULL) {
+ ALOGE("JNIMediaPlayerFactory: createExtMediaPlayerListener : success");
+ }
+ }
+ }
+ return listener;
+}
+
+void JNIMediaPlayerFactory::CreateNativeQCMediaPlayer(sp<MediaPlayer> &mp)
+{
+ if (sNativeQCMediaPlayerFn) {
+ mp = (*sNativeQCMediaPlayerFn)();
+ if (mp != NULL) {
+ ALOGE("JNIMediaPlayerFactory: CreateNativeQCMediaPlayer : Success");
+ }
+ }
+}
+
+
+bool JNIMediaPlayerFactory::checkExtMedia(JNIEnv *env, jobject thiz)
+{
+ bool bIsQCMediaPlayerPresent = false;
+ if (sExtMediaFn) {
+ bIsQCMediaPlayerPresent = (*sExtMediaFn)(env, thiz);
+ }
+ ALOGE("JNIMediaPlayerFactory: bIsQCMediaPlayerPresent %d", bIsQCMediaPlayerPresent);
+ return bIsQCMediaPlayerPresent;
+}
+
+bool JNIMediaPlayerFactory::CheckAndCreateExtMediaPlayer(
+ JNIEnv *env, jobject thiz, jobject weak_this, sp<MediaPlayerListener> &listener, sp<MediaPlayer> &mp)
+{
+ bool bOk = false;
+ listener = createExtMediaPlayerListener(env, thiz, weak_this, listener);
+ if (listener != NULL && checkExtMedia(env,thiz)) {
+ CreateNativeQCMediaPlayer(mp);
+ if (mp != NULL) {
+ bOk = true;
+ }
+ }
+ return bOk;
+}
+
// ----------------------------------------------------------------------------
static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
@@ -868,14 +1016,26 @@ static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
ALOGV("native_setup");
- sp<MediaPlayer> mp = new MediaPlayer();
+
+ sp<MediaPlayer> mp = NULL;
+
+ bool bOk = false;
+ JNIMediaPlayerFactory *jniMediaPlayerFactory = new JNIMediaPlayerFactory();
+
+ sp<MediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
+
+ if (jniMediaPlayerFactory) {
+ bOk = jniMediaPlayerFactory->CheckAndCreateExtMediaPlayer(env, thiz, weak_this, listener, mp);
+ delete(jniMediaPlayerFactory);
+ }
+
+ if (!bOk){
+ mp = new MediaPlayer();
+ }
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
}
-
- // create new listener and give it to MediaPlayer
- sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
mp->setListener(listener);
// Stow our new C++ MediaPlayer in an opaque field in the Java object.
@@ -1031,6 +1191,38 @@ android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject
;
}
+static jboolean
+android_media_MediaPlayer_suspend(JNIEnv *env, jobject thiz)
+{
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return false;
+ }
+
+ if (mp->suspend() != OK) {
+ return false;
+ }
+
+ return true;
+}
+
+static jboolean
+android_media_MediaPlayer_resume(JNIEnv *env, jobject thiz)
+{
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return false;
+ }
+
+ if (mp->resume() != OK) {
+ return false;
+ }
+
+ return true;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -1080,6 +1272,8 @@ static JNINativeMethod gMethods[] = {
{"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
{"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint},
{"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer},
+ {"_suspend", "()Z", (void *)android_media_MediaPlayer_suspend},
+ {"_resume", "()Z", (void *)android_media_MediaPlayer_resume},
};
// This function only registers the native methods
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index ca9db91..30fd4c4 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -92,12 +92,17 @@ android_media_MediaProfiles_native_get_video_encoder_cap(JNIEnv *env, jobject /*
int maxFrameWidth = sProfiles->getVideoEncoderParamByName("enc.vid.width.max", encoder);
int minFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.height.min", encoder);
int maxFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.height.max", encoder);
+ int maxHFRFrameWidth = sProfiles->getVideoEncoderParamByName("enc.vid.hfr.width.max", encoder);
+ int maxHFRFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.hfr.height.max", encoder);
+ int maxHFRMode = sProfiles->getVideoEncoderParamByName("enc.vid.hfr.mode.max", encoder);
// Check on the values retrieved
if ((minBitRate == -1 || maxBitRate == -1) ||
(minFrameRate == -1 || maxFrameRate == -1) ||
(minFrameWidth == -1 || maxFrameWidth == -1) ||
- (minFrameHeight == -1 || maxFrameHeight == -1)) {
+ (minFrameHeight == -1 || maxFrameHeight == -1) ||
+ (maxHFRFrameWidth == -1 || maxHFRFrameHeight == -1) ||
+ (maxHFRMode == -1)) {
jniThrowException(env, "java/lang/RuntimeException", "Error retrieving video encoder capability params");
return NULL;
@@ -105,14 +110,16 @@ android_media_MediaProfiles_native_get_video_encoder_cap(JNIEnv *env, jobject /*
// Construct an instance of the VideoEncoderCap and set its member variables
jclass videoEncoderCapClazz = env->FindClass("android/media/EncoderCapabilities$VideoEncoderCap");
- jmethodID videoEncoderCapConstructorMethodID = env->GetMethodID(videoEncoderCapClazz, "<init>", "(IIIIIIIII)V");
+ jmethodID videoEncoderCapConstructorMethodID = env->GetMethodID(videoEncoderCapClazz, "<init>", "(IIIIIIIIIIII)V");
jobject cap = env->NewObject(videoEncoderCapClazz,
videoEncoderCapConstructorMethodID,
static_cast<int>(encoder),
minBitRate, maxBitRate,
minFrameRate, maxFrameRate,
minFrameWidth, maxFrameWidth,
- minFrameHeight, maxFrameHeight);
+ minFrameHeight, maxFrameHeight,
+ maxHFRFrameWidth, maxHFRFrameHeight,
+ maxHFRMode);
return cap;
}
@@ -170,7 +177,9 @@ static bool isCamcorderQualityKnown(int quality)
(quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START &&
quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END) ||
(quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START &&
- quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END));
+ quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END) ||
+ (quality >= CAMCORDER_QUALITY_VENDOR_START &&
+ quality <= CAMCORDER_QUALITY_VENDOR_END));
}
static jobject
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index f60af63..69da951 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -40,6 +40,7 @@
#include <system/audio.h>
#include <android_runtime/android_view_Surface.h>
+#include "SeempLog.h"
// ----------------------------------------------------------------------------
@@ -219,7 +220,9 @@ static void
android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve)
{
ALOGV("setVideoEncoder(%d)", ve);
- if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) {
+ if (ve < VIDEO_ENCODER_DEFAULT ||
+ (ve >= VIDEO_ENCODER_LIST_END && ve <= VIDEO_ENCODER_LIST_VENDOR_START) ||
+ ve >= VIDEO_ENCODER_LIST_VENDOR_END) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video encoder");
return;
}
@@ -391,6 +394,14 @@ android_media_MediaRecorder_start(JNIEnv *env, jobject thiz)
}
static void
+android_media_MediaRecorder_pause(JNIEnv *env, jobject thiz)
+{
+ ALOGV("pause");
+ sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+ process_media_recorder_call(env, mr->pause(), "java/lang/RuntimeException", "pause failed.");
+}
+
+static void
android_media_MediaRecorder_stop(JNIEnv *env, jobject thiz)
{
ALOGV("stop");
@@ -527,6 +538,7 @@ static JNINativeMethod gMethods[] = {
{"getSurface", "()Landroid/view/Surface;", (void *)android_media_MediaRecorder_getSurface},
{"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude},
{"start", "()V", (void *)android_media_MediaRecorder_start},
+ {"pause", "()V", (void *)android_media_MediaRecorder_pause},
{"stop", "()V", (void *)android_media_MediaRecorder_stop},
{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},
{"release", "()V", (void *)android_media_MediaRecorder_release},
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 2ce2a90..b481b46 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -130,6 +130,18 @@ android_mtp_MtpServer_send_device_property_changed(JNIEnv *env, jobject thiz, ji
}
static void
+android_mtp_MtpServer_send_object_updated(JNIEnv *env, jobject thiz, jint handle)
+{
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->sendObjectUpdated(handle);
+ else
+ ALOGE("server is null in send_object_updated");
+}
+
+static void
android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
{
Mutex::Autolock autoLock(sMutex);
@@ -188,6 +200,7 @@ static JNINativeMethod gMethods[] = {
{"native_send_object_removed", "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
{"native_send_device_property_changed", "(I)V",
(void *)android_mtp_MtpServer_send_device_property_changed},
+ {"native_send_object_updated", "(I)V", (void *)android_mtp_MtpServer_send_object_updated},
{"native_add_storage", "(Landroid/mtp/MtpStorage;)V",
(void *)android_mtp_MtpServer_add_storage},
{"native_remove_storage", "(I)V", (void *)android_mtp_MtpServer_remove_storage},
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index aba4bbe..c392034 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -162,6 +162,15 @@ static void effectCallback(int event, void* user, void *info) {
ALOGV("EVENT_PARAMETER_CHANGED");
break;
case AudioEffect::EVENT_ERROR:
+ if (info == 0) {
+ ALOGW("EVENT_ERROR info == NULL");
+ goto effectCallback_Exit;
+ }
+ status_t status = *(status_t *)info;
+ if (status == DEAD_OBJECT) {
+ ALOGE("effectCallback: Client died, no need to send callback");
+ goto effectCallback_Exit;
+ }
ALOGW("EVENT_ERROR");
break;
}
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 0557019..10df3ae 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -248,6 +248,7 @@ static sp<Visualizer> setVisualizer(JNIEnv* env, jobject thiz,
v->incStrong((void*)setVisualizer);
}
if (old != 0) {
+ old->cancelCaptureCallBack();
old->decStrong((void*)setVisualizer);
}
env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)v.get());
diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java
index 883c8c6..afa9dab 100644
--- a/obex/javax/obex/ClientOperation.java
+++ b/obex/javax/obex/ClientOperation.java
@@ -52,7 +52,7 @@ public final class ClientOperation implements Operation, BaseStream {
private static final String TAG = "ClientOperation";
- private static final boolean V = ObexHelper.VDBG;
+ private static final boolean V = Log.isLoggable(ObexHelper.LOG_TAG, Log.VERBOSE);
private ClientSession mParent;
@@ -632,21 +632,32 @@ public final class ClientOperation implements Operation, BaseStream {
if (mGetOperation) {
if (!mOperationDone) {
- mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
- while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
- more = sendRequest(ObexHelper.OBEX_OPCODE_GET);
- }
- // For GET we need to loop until all headers have been sent,
- // And then we wait for the first continue package with the
- // reply.
- if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
- mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL,
- null, mReplyHeader, mPrivateInput, mSrmActive);
- }
- if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
- mOperationDone = true;
+ if (!mGetFinalFlag) {
+ mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
+ while ((more) && (mReplyHeader.responseCode ==
+ ResponseCodes.OBEX_HTTP_CONTINUE)) {
+ more = sendRequest(ObexHelper.OBEX_OPCODE_GET);
+ }
+ // For GET we need to loop until all headers have been sent,
+ // And then we wait for the first continue package with the
+ // reply.
+ if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
+ mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL,
+ null, mReplyHeader, mPrivateInput, mSrmActive);
+ }
+ if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
+ mOperationDone = true;
+ } else {
+ checkForSrm();
+ }
} else {
- checkForSrm();
+ more = sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
+
+ if (more) {
+ throw new IOException("FINAL_GET forced, data didn't fit into one packet");
+ }
+
+ mOperationDone = true;
}
}
} else {
@@ -705,7 +716,15 @@ public final class ClientOperation implements Operation, BaseStream {
if (mPrivateInput == null) {
mPrivateInput = new PrivateInputStream(this);
}
- sendRequest(ObexHelper.OBEX_OPCODE_GET);
+
+ if (!mGetFinalFlag) {
+ sendRequest(ObexHelper.OBEX_OPCODE_GET);
+ } else {
+ sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
+ }
+ if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
+ mOperationDone = true;
+ }
return true;
} else if (mOperationDone) {
diff --git a/obex/javax/obex/ClientSession.java b/obex/javax/obex/ClientSession.java
index 272a920..f360944 100644
--- a/obex/javax/obex/ClientSession.java
+++ b/obex/javax/obex/ClientSession.java
@@ -48,6 +48,7 @@ import android.util.Log;
public final class ClientSession extends ObexSession {
private static final String TAG = "ClientSession";
+ private static final boolean V = Log.isLoggable(ObexHelper.LOG_TAG, Log.VERBOSE);
private boolean mOpen;
@@ -68,7 +69,7 @@ public final class ClientSession extends ObexSession {
private final OutputStream mOutput;
- private final boolean mLocalSrmSupported;
+ private boolean mLocalSrmSupported;
private final ObexTransport mTransport;
@@ -613,4 +614,9 @@ public final class ClientSession extends ObexSession {
public boolean isSrmSupported() {
return mLocalSrmSupported;
}
+
+ public void setLocalSrmStatus(boolean SrmEnabled) {
+ mLocalSrmSupported = SrmEnabled;
+ if (V) Log.v(TAG, "setLocalSrmStatus: " + mLocalSrmSupported);
+ }
}
diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java
index fa50943..431525e 100644
--- a/obex/javax/obex/ObexHelper.java
+++ b/obex/javax/obex/ObexHelper.java
@@ -52,7 +52,8 @@ import android.util.Log;
public final class ObexHelper {
private static final String TAG = "ObexHelper";
- public static final boolean VDBG = false;
+ public static final String LOG_TAG = "BluetoothObex";
+ public static final boolean VDBG = Log.isLoggable(LOG_TAG, Log.VERBOSE);
/**
* Defines the basic packet length used by OBEX. Every OBEX packet has the
* same basic format:<BR>
@@ -190,6 +191,7 @@ public final class ObexHelper {
try {
while (index < headerArray.length) {
headerID = 0xFF & headerArray[index];
+ if (VDBG) Log.v(TAG,"updateHeaderSet headerID = " + headerID);
switch (headerID & (0xC0)) {
/*
@@ -375,8 +377,9 @@ public final class ObexHelper {
* Determine if there is a connection ID to send. If there is,
* then it should be the first header in the packet.
*/
+ if (VDBG) Log.v(TAG,"createHeader = " + head);
if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) {
-
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.CONNECTION_ID);
out.write((byte)HeaderSet.CONNECTION_ID);
out.write(headImpl.mConnectionID);
}
@@ -384,6 +387,7 @@ public final class ObexHelper {
// Count Header
intHeader = (Long)headImpl.getHeader(HeaderSet.COUNT);
if (intHeader != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.COUNT);
out.write((byte)HeaderSet.COUNT);
value = ObexHelper.convertToByteArray(intHeader.longValue());
out.write(value);
@@ -395,6 +399,7 @@ public final class ObexHelper {
// Name Header
stringHeader = (String)headImpl.getHeader(HeaderSet.NAME);
if (stringHeader != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.NAME);
out.write((byte)HeaderSet.NAME);
value = ObexHelper.convertToUnicodeByteArray(stringHeader);
length = value.length + 3;
@@ -415,6 +420,7 @@ public final class ObexHelper {
// Type Header
stringHeader = (String)headImpl.getHeader(HeaderSet.TYPE);
if (stringHeader != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.TYPE);
out.write((byte)HeaderSet.TYPE);
try {
value = stringHeader.getBytes("ISO8859_1");
@@ -436,6 +442,7 @@ public final class ObexHelper {
// Length Header
intHeader = (Long)headImpl.getHeader(HeaderSet.LENGTH);
if (intHeader != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.LENGTH);
out.write((byte)HeaderSet.LENGTH);
value = ObexHelper.convertToByteArray(intHeader.longValue());
out.write(value);
@@ -447,7 +454,7 @@ public final class ObexHelper {
// Time ISO Header
dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_ISO_8601);
if (dateHeader != null) {
-
+ if (VDBG) Log.v(TAG," Add dateHeader = " + HeaderSet.TIME_ISO_8601);
/*
* The ISO Header should take the form YYYYMMDDTHHMMSSZ. The
* 'Z' will only be included if it is a UTC time.
@@ -509,6 +516,7 @@ public final class ObexHelper {
// Time 4 Byte Header
dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_4_BYTE);
if (dateHeader != null) {
+ if (VDBG) Log.v(TAG," Add dateHeader = " + HeaderSet.TIME_4_BYTE);
out.write(HeaderSet.TIME_4_BYTE);
/*
@@ -543,6 +551,7 @@ public final class ObexHelper {
// Target Header
value = (byte[])headImpl.getHeader(HeaderSet.TARGET);
if (value != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.TARGET);
out.write((byte)HeaderSet.TARGET);
length = value.length + 3;
lengthArray[0] = (byte)(255 & (length >> 8));
@@ -571,6 +580,7 @@ public final class ObexHelper {
// Who Header
value = (byte[])headImpl.getHeader(HeaderSet.WHO);
if (value != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.WHO);
out.write((byte)HeaderSet.WHO);
length = value.length + 3;
lengthArray[0] = (byte)(255 & (length >> 8));
@@ -582,9 +592,10 @@ public final class ObexHelper {
}
}
- // Connection ID Header
+ // Application Parameter Header
value = (byte[])headImpl.getHeader(HeaderSet.APPLICATION_PARAMETER);
if (value != null) {
+ if (VDBG) Log.v(TAG," Add APP PARAM Header = " + HeaderSet.APPLICATION_PARAMETER);
out.write((byte)HeaderSet.APPLICATION_PARAMETER);
length = value.length + 3;
lengthArray[0] = (byte)(255 & (length >> 8));
@@ -623,6 +634,7 @@ public final class ObexHelper {
lengthArray[1] = (byte)(255 & length);
out.write(lengthArray);
out.write(value);
+ if (VDBG) Log.v(TAG," Add Unicode String value = " + value);
if (nullOut) {
headImpl.setHeader(i + 0x30, null);
}
@@ -637,6 +649,7 @@ public final class ObexHelper {
lengthArray[1] = (byte)(255 & length);
out.write(lengthArray);
out.write(value);
+ if (VDBG) Log.v(TAG," Add ByteSeq value = " + value);
if (nullOut) {
headImpl.setHeader(i + 0x70, null);
}
@@ -647,6 +660,7 @@ public final class ObexHelper {
if (byteHeader != null) {
out.write((byte)i + 0xB0);
out.write(byteHeader.byteValue());
+ if (VDBG) Log.v(TAG," Add ByteHeader value = " + byteHeader.byteValue());
if (nullOut) {
headImpl.setHeader(i + 0xB0, null);
}
@@ -657,6 +671,7 @@ public final class ObexHelper {
if (intHeader != null) {
out.write((byte)i + 0xF0);
out.write(ObexHelper.convertToByteArray(intHeader.longValue()));
+ if (VDBG) Log.v(TAG," Add Int value = " + intHeader.longValue());
if (nullOut) {
headImpl.setHeader(i + 0xF0, null);
}
@@ -671,6 +686,7 @@ public final class ObexHelper {
lengthArray[1] = (byte)(255 & length);
out.write(lengthArray);
out.write(headImpl.mAuthChall);
+ if (VDBG) Log.v(TAG," Add mAuthChall value = " + headImpl.mAuthChall);
if (nullOut) {
headImpl.mAuthChall = null;
}
@@ -684,6 +700,7 @@ public final class ObexHelper {
lengthArray[1] = (byte)(255 & length);
out.write(lengthArray);
out.write(headImpl.mAuthResp);
+ if (VDBG) Log.v(TAG," Add mAuthChall value = " + headImpl.mAuthResp);
if (nullOut) {
headImpl.mAuthResp = null;
}
@@ -699,8 +716,10 @@ public final class ObexHelper {
// Add the SRM header
byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
if (byteHeader != null) {
+ if (VDBG) Log.v(TAG," Add SRM Header = " + HeaderSet.SINGLE_RESPONSE_MODE);
out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE);
out.write(byteHeader.byteValue());
+ if (VDBG) Log.v(TAG," Add SRM value = " + byteHeader.byteValue());
if (nullOut) {
headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, null);
}
@@ -709,6 +728,7 @@ public final class ObexHelper {
// Add the SRM parameter header
byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
if (byteHeader != null) {
+ if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
out.write(byteHeader.byteValue());
if (nullOut) {
diff --git a/obex/javax/obex/ObexSession.java b/obex/javax/obex/ObexSession.java
index 542b9c8..f5e607c 100644
--- a/obex/javax/obex/ObexSession.java
+++ b/obex/javax/obex/ObexSession.java
@@ -50,7 +50,7 @@ import android.util.Log;
public class ObexSession {
private static final String TAG = "ObexSession";
- private static final boolean V = ObexHelper.VDBG;
+ private static final boolean V = Log.isLoggable(ObexHelper.LOG_TAG, Log.VERBOSE);
protected Authenticator mAuthenticator;
diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java
index 56a675a..87943bf 100644
--- a/obex/javax/obex/ServerOperation.java
+++ b/obex/javax/obex/ServerOperation.java
@@ -59,7 +59,7 @@ public final class ServerOperation implements Operation, BaseStream {
private static final String TAG = "ServerOperation";
- private static final boolean V = ObexHelper.VDBG; // Verbose debugging
+ private static final boolean V = Log.isLoggable(ObexHelper.LOG_TAG, Log.VERBOSE);
public boolean isAborted;
@@ -124,6 +124,7 @@ public final class ServerOperation implements Operation, BaseStream {
*/
public ServerOperation(ServerSession p, InputStream in, int request, int maxSize,
ServerRequestHandler listen) throws IOException {
+ if (V) Log.v(TAG, "ServerOperation");
isAborted = false;
mParent = p;
@@ -195,7 +196,12 @@ public final class ServerOperation implements Operation, BaseStream {
if(!handleObexPacket(packet)) {
return;
}
- if (!mHasBody) {
+ /* Don't Pre-Send continue when Remote requested for SRM
+ * Let the Application confirm.
+ */
+ if(V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled
+ + " not hasBody case: " + mHasBody);
+ if (!mHasBody && !mSrmEnabled) {
while ((!mGetOperation) && (!finalBitSet)) {
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
if (mPrivateInput.available() > 0) {
@@ -204,8 +210,13 @@ public final class ServerOperation implements Operation, BaseStream {
}
}
}
-
- while ((!mGetOperation) && (!finalBitSet) && (mPrivateInput.available() == 0)) {
+ /* Don't Pre-Send continue when Remote requested for SRM
+ * Let the Application confirm.
+ */
+ if(V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled
+ + " not finalPacket: " + finalBitSet + " not GETOp Case: " + mGetOperation);
+ while ((!mSrmEnabled) && (!mGetOperation) && (!finalBitSet)
+ && (mPrivateInput.available() == 0)) {
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
if (mPrivateInput.available() > 0) {
break;
@@ -330,14 +341,17 @@ public final class ServerOperation implements Operation, BaseStream {
*/
public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
throws IOException {
+ if (V) Log.v(TAG, "continueOperation");
if (!mGetOperation) {
if (!finalBitSet) {
if (sendEmpty) {
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
+ if (V) Log.v(TAG, "continueOperation:ServerSet SRM sendEmpty clause");
return true;
} else {
if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) {
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
+ if (V) Log.v(TAG, "continueOperation: Server setting SRM");
return true;
} else {
return false;
@@ -347,6 +361,7 @@ public final class ServerOperation implements Operation, BaseStream {
return false;
}
} else {
+ if (V) Log.v(TAG, "Get continueOperation ");
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
return true;
}
@@ -395,6 +410,8 @@ public final class ServerOperation implements Operation, BaseStream {
bodyLength = mPrivateOutput.size();
orginalBodyLength = bodyLength;
}
+ if(V)Log.v(TAG, "mMaxPcKLen : " + mMaxPacketLength);
+ if(V)Log.v(TAG, "headerArryLen : " + headerArray.length);
if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) {
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index acee5dd..33b0bde 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -47,7 +47,7 @@ import java.io.OutputStream;
public final class ServerSession extends ObexSession implements Runnable {
private static final String TAG = "Obex ServerSession";
- private static final boolean V = ObexHelper.VDBG;
+ private static final boolean V = Log.isLoggable(ObexHelper.LOG_TAG, Log.VERBOSE);
private ObexTransport mTransport;
@@ -104,7 +104,6 @@ public final class ServerSession extends ObexSession implements Runnable {
case ObexHelper.OBEX_OPCODE_DISCONNECT:
handleDisconnectRequest();
- done = true;
break;
case ObexHelper.OBEX_OPCODE_GET:
@@ -125,6 +124,7 @@ public final class ServerSession extends ObexSession implements Runnable {
break;
case -1:
+ Log.v(TAG, "Read request returned -1, exiting from loop");
done = true;
break;
@@ -175,7 +175,7 @@ public final class ServerSession extends ObexSession implements Runnable {
mInput.read();
}
code = mListener.onAbort(request, reply);
- Log.v(TAG, "onAbort request handler return value- " + code);
+ Log.d(TAG, "onAbort request handler return value- " + code);
code = validateResponseCode(code);
}
sendResponse(code, null);
@@ -195,6 +195,7 @@ public final class ServerSession extends ObexSession implements Runnable {
* @throws IOException if an error occurred at the transport layer
*/
private void handlePutRequest(int type) throws IOException {
+ if (V) Log.v(TAG, "handlePutRequest");
ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
try {
int response = -1;
@@ -206,10 +207,12 @@ public final class ServerSession extends ObexSession implements Runnable {
response = validateResponseCode(mListener.onPut(op));
}
if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) {
+ if (V) Log.v(TAG, "handlePutRequest pre != HTTP_OK sendReply");
op.sendReply(response);
} else if (!op.isAborted) {
// wait for the final bit
while (!op.finalBitSet) {
+ if (V) Log.v(TAG, "handlePutRequest pre looped sendReply");
op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
}
op.sendReply(response);
@@ -220,7 +223,7 @@ public final class ServerSession extends ObexSession implements Runnable {
*internal error should not be sent because server has already replied with
*OK response in "sendReply")
*/
- if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
+ if(V) Log.w(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
if (!op.isAborted) {
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
}
@@ -241,6 +244,7 @@ public final class ServerSession extends ObexSession implements Runnable {
* @throws IOException if an error occurred at the transport layer
*/
private void handleGetRequest(int type) throws IOException {
+ if (V) Log.v(TAG, "handleGetRequest");
ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
try {
int response = validateResponseCode(mListener.onGet(op));
@@ -263,6 +267,7 @@ public final class ServerSession extends ObexSession implements Runnable {
public void sendResponse(int code, byte[] header) throws IOException {
int totalLength = 3;
byte[] data = null;
+ if (V) Log.v(TAG,"sendResponse code " + code + " header : " + header);
OutputStream op = mOutput;
if (op == null) {
return;
@@ -270,6 +275,7 @@ public final class ServerSession extends ObexSession implements Runnable {
if (header != null) {
totalLength += header.length;
+ if (V) Log.v(TAG, "header != null totalLength = " + totalLength);
data = new byte[totalLength];
data[0] = (byte)code;
data[1] = (byte)(totalLength >> 8);
@@ -658,6 +664,12 @@ public final class ServerSession extends ObexSession implements Runnable {
*/
byte[] sendData = new byte[totalLength];
int maxRxLength = ObexHelper.getMaxRxPacketSize(mTransport);
+ //PTS expects least of maxPacketLen
+ if(maxRxLength > mMaxPacketLength) {
+ if(V) Log.v(TAG,"Set maxRxLength to min of maxRxServrLen:" + maxRxLength +
+ " and MaxNegotiated from Client: " + mMaxPacketLength);
+ maxRxLength = mMaxPacketLength;
+ }
sendData[0] = (byte)code;
sendData[1] = length[2];
sendData[2] = length[3];
diff --git a/packages/BackupRestoreConfirmation/res/values-ast-rES/strings.xml b/packages/BackupRestoreConfirmation/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..33757ee
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values-ast-rES/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="backup_confirm_title">Copia de seguranza completa</string>
+ <string name="restore_confirm_title">Restauración completa</string>
+ <string name="backup_confirm_text">Solicitóse una copia de seguranza completa de tolos datos nun ordenador coneutáu. ¿Quies permitir la copia de seguranza?\n\nNun permitas la copia de seguranza si nun ficisti tu la solicitú.</string>
+ <string name="allow_backup_button_label">Copia de seguranza de datos</string>
+ <string name="deny_backup_button_label">Nun facer copia de seguranza</string>
+ <string name="restore_confirm_text">Solicitóse una restauración completa de tolos datos dende un ordenador coneutáu. ¿Quies permitir la restauración?\n\nNun tienes de permitir la restauración si nun ficisti tu la solicitú. Van sustituyise los datos actuales del preséu!</string>
+ <string name="allow_restore_button_label">Restaurar datos</string>
+ <string name="deny_restore_button_label">Nun restaurar</string>
+ <string name="current_password_text">Introduz la contraseña actual de copia de seguranza:</string>
+ <string name="device_encryption_restore_text">Introduz la contraseña de cifráu del preséu.</string>
+ <string name="device_encryption_backup_text">Introduz la contraseña de cifráu del preséu. Esta contraseña va usase pa cifrar el ficheru de copia de seguranza.</string>
+ <string name="backup_enc_password_text">Introduz la contraseña que quieras usar pa cifrar los datos de la copia de seguranza completa. Si dexes esti campu baleru, va usase la to contraseña de copia de seguridá actual:</string>
+ <string name="backup_enc_password_optional">Si quies cifrar los datos de la copia de seguranza completa, introduz la contraseña a continuación:</string>
+ <string name="backup_enc_password_required">Como\'l preséu ta cifráu, necesítase cifrar la copia de seguranza. Escribi la contraseña:</string>
+ <string name="restore_enc_password_text">Si los datos de restauración tán cifraos, introduz la contraseña:</string>
+ <string name="toast_backup_started">Aniciando copia de seguranza...</string>
+ <string name="toast_backup_ended">Finó la copia de seguridá</string>
+ <string name="toast_restore_started">Aniciando restauración...</string>
+ <string name="toast_restore_ended">Finó la restauración</string>
+ <string name="toast_timeout">Tiempu d\'espera d\'operación escosáu</string>
+</resources>
diff --git a/packages/BackupRestoreConfirmation/res/values-be/strings.xml b/packages/BackupRestoreConfirmation/res/values-be/strings.xml
new file mode 100644
index 0000000..e35876c
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values-be/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="backup_confirm_title">Поўнае рэзервовае капіяванне</string>
+ <string name="restore_confirm_title">Поўнае аднаўленне</string>
+ <string name="backup_confirm_text">Было прапанавана поўнае рэзервовае капіяванне ўсіх дадзеных на падлучаным настольным кампутары. Дазволіць гэта?\n\nКалі вы самі не запытвалі рэзервовае капiяванне, спынiце аперацыю.</string>
+ <string name="allow_backup_button_label">Рэзервовае капіяванне дадзеных</string>
+ <string name="deny_backup_button_label">Не ствараць рэзервовыя копіі</string>
+ <string name="restore_confirm_text">Запытана поўнае аднаўленне ўсіх дадзеных з падлучанага настольнага кампутара. Дазволіць гэта?\n\nКалі вы самі не запытвалі аднаўленне, не дазваляйце працягваць аперацыю. Гэта прывядзе да замены якіх-небудзь дадзеных, якія зараз знаходзяцца на прыладзе!</string>
+ <string name="allow_restore_button_label">Аднавіць мае дадзеныя</string>
+ <string name="deny_restore_button_label">Не аднаўляць</string>
+ <string name="current_password_text">Увядзіце ваш бягучы пароль рэзервовага капіявання ніжэй:</string>
+ <string name="device_encryption_restore_text">Увядзіце нiжэй пароль для расшыфравання прылады.</string>
+ <string name="device_encryption_backup_text">Увядзіце пароль для расшыфравання прылады. Ён таксама будзе выкарыстоўвацца для расшыфравання рэзервовай копіі.</string>
+ <string name="backup_enc_password_text">Увядзіце пароль, які выкарыстоўваецца для шыфравання ўсіх дадзеных рэзервовага капіявання. Калі гэтае поле пакінуць пустым, будзе выкарыстоўвацца бягучы пароль рэзервовага капіявання:</string>
+ <string name="backup_enc_password_optional">Калі вы жадаеце зашыфраваць усе дадзеныя рэзервовага капіявання, увядзіце пароль ніжэй:</string>
+ <string name="backup_enc_password_required">У сувязі з тым, што ваша прылада зашыфраваная, трэба таксама зашыфраваць і рэзервовую копію. Калі ласка, увядзіце пароль:</string>
+ <string name="restore_enc_password_text">Калі дадзеныя для аднаўлення зашыфраваныя, увядзіце пароль ніжэй:</string>
+ <string name="toast_backup_started">Рэзервовае капіяванне...</string>
+ <string name="toast_backup_ended">Рэзервовае капіяванне скончылася</string>
+ <string name="toast_restore_started">Пачынаецца аднаўленне...</string>
+ <string name="toast_restore_ended">Аднаўленне скончылася</string>
+ <string name="toast_timeout">Тайм-аўт аперацыі</string>
+</resources>
diff --git a/packages/BackupRestoreConfirmation/res/values-eo/strings.xml b/packages/BackupRestoreConfirmation/res/values-eo/strings.xml
new file mode 100644
index 0000000..64ce001
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values-eo/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="backup_confirm_title">Kompleta savkopio</string>
+ <string name="restore_confirm_title">Kompleta restaŭro</string>
+ <string name="deny_restore_button_label">Ne restaŭri</string>
+</resources>
diff --git a/packages/BackupRestoreConfirmation/res/values-ku/strings.xml b/packages/BackupRestoreConfirmation/res/values-ku/strings.xml
new file mode 100644
index 0000000..d5ccd4b
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values-ku/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="backup_confirm_title">پاراستنی گشت</string>
+ <string name="restore_confirm_title">گه‌ڕاندنه‌وه‌ی گشت</string>
+ <string name="backup_confirm_text">پاراستنێکی گشتیی بۆ هه‌موو ئه‌و داتایانه‌ی که‌ په‌یوه‌ست کراوه‌ به‌ کۆمپیوته‌ره‌وه‌ داواکراوه‌. ده‌ته‌وێت ئه‌مه‌ ڕووبدات؟\n\n ئه‌گه‌ر خۆت ئه‌م داواکارییه‌ت نه‌کردووه‌، مه‌هێڵه‌ ئه‌م کاره‌ ڕووبدات.</string>
+ <string name="allow_backup_button_label">داتاکانم بپارێزه‌</string>
+ <string name="deny_backup_button_label">مه‌یپارێزه‌</string>
+ <string name="restore_confirm_text">گه‌ڕانه‌وه‌ی ته‌واوی داتاکان بۆ په‌یوه‌ندی کردن به‌ ڕوونمای کۆمپیوته‌ره‌وه‌ داواکراوه‌ ، ئه‌ته‌وێ ئه‌مه‌ ڕووبدات؟\n\n ئه‌گه‌ر خۆت داوای ئه‌م پاراستنه‌ت نه‌کردووه‌، مه‌هێڵه‌ ئه‌م کاره‌ ڕووبدات. ئه‌گه‌رنا شوێنی هه‌موو ئه‌و داتایانه‌ ده‌گرێته‌وه‌ که‌ ئێستا له‌ ئامێره‌که‌دایه‌!</string>
+ <string name="allow_restore_button_label">داتاکانم بگه‌ڕێنه‌ره‌وه‌</string>
+ <string name="deny_restore_button_label">مه‌یگه‌ڕێنه‌ره‌وه‌</string>
+ <string name="current_password_text">تکایه‌ تێپه‌ڕه‌وشه‌ی پاراستن بنوسه‌ له‌ خواره‌وه‌:</string>
+ <string name="device_encryption_restore_text">تکایه تێپه‌ڕه‌وشه‌ی ئامێره‌ به‌ هێماکراوه‌که‌ت بنوسه‌.</string>
+ <string name="device_encryption_backup_text">تکایه تێپه‌ڕه‌وشه‌ی ئامێره‌ ڕه‌مزکراوه‌که‌ت له‌ خواره‌وه‌بنوسه‌. ئه‌مه‌ ده‌توانرێت بۆ ڕه‌مزکردنی ئه‌رشیفی پاراستنیش به‌کار بهێنرێت.</string>
+ <string name="backup_enc_password_text">تکایه‌ تێپه‌ڕه‌وشه‌یه‌ک بنوسه‌ بۆ به‌کارهێنانی به‌ هێماکردنی پاراستنی ته‌واوی داتاکان. ئه‌گه‌ر ئه‌مه‌ به‌ به‌تاڵیی جێ بهێڵرێت، دوایین تێپه‌ڕه‌وشه‌ی پاراستنت به‌کارده‌هێنرێت:</string>
+ <string name="backup_enc_password_optional">ئه‌گه‌ر ده‌ته‌وێت ته‌واوی پاراستنی داتاکان به‌ هێما بکه‌یت، تێپه‌ڕه‌وشه‌یه‌ک له‌ خواره‌وه‌ بنوسه‌:</string>
+ <string name="backup_enc_password_required">لەوەتەی ئامێرەکەت پارێزراوە، تۆ پێویستیت بە هەڵگرتنی داتاکانتە. تکایە ژمارەی تێپەڕەوشە لێبدە:</string>
+ <string name="restore_enc_password_text">ئه‌گه‌ر داتای گه‌ڕاندنه‌وه‌ به‌ هێما کراوه‌، تکایه‌ تێپه‌ڕه‌وشه‌که‌ له‌ خواره‌وه‌ بنوسه‌:</string>
+ <string name="toast_backup_started">پاراستن ده‌ستپێده‌کات...</string>
+ <string name="toast_backup_ended">پاراستن ته‌واو بوو</string>
+ <string name="toast_restore_started">گه‌ڕاندنه‌وه‌ ده‌ستپێده‌کات...</string>
+ <string name="toast_restore_ended">گه‌ڕاندنه‌وه‌ کۆتایی هات</string>
+ <string name="toast_timeout">کاتی کرداره‌که‌ ته‌واو بوو</string>
+</resources>
diff --git a/packages/BackupRestoreConfirmation/res/values-lb/strings.xml b/packages/BackupRestoreConfirmation/res/values-lb/strings.xml
new file mode 100644
index 0000000..835788f
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values-lb/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="backup_confirm_title">Komplett Sécherung</string>
+ <string name="restore_confirm_title">Komplett Erëmhierstellung</string>
+ <string name="backup_confirm_text">Eng komplett Sécherung vun allen Daten op en ugeschlossene Büroscomputer ass gefrot ginn. Wëlls du dat zouloossen\?\n\nFalls du dës Sécherung net gefrot hues, dann erlab dës Operatioun net.</string>
+ <string name="allow_backup_button_label">Meng Date sécheren</string>
+ <string name="deny_backup_button_label">Net sécheren</string>
+ <string name="restore_confirm_text">Eng komplett Erëmhierstellung vun allen Daten op en ugeschlosse Büroscomputer ass gefrot ginn. Wëlls du dat zouloossen\?\n\nFalls du dës Erëmhierstellung net gefrot hues, dann erlab dës Operatioun net!</string>
+ <string name="allow_restore_button_label">Meng Daten erëmhierstellen</string>
+ <string name="deny_restore_button_label">Net erëmhierstellen</string>
+ <string name="current_password_text">Gëff w.e.g. däin aktuellt Sécherungspasswuert an:</string>
+ <string name="device_encryption_restore_text">Gëff w.e.g. d\'Passwuert fir d\'Entschlësselung vun dengem Apparat an.</string>
+ <string name="device_encryption_backup_text">Gëff w.e.g. d\'Passwuert fir d\'Entschlësselung vun dengem Apparat an. Dat Passwuert gëtt och benotzt fir d\'Sécherungsarchiv ze verschlësselen.</string>
+ <string name="backup_enc_password_text">Gëff w.e.g. e Passwuert a fir d\'Verschlësselung vun de gesécherten Daten. Falls et eidel ass, gëtt däin aktuellt Sécherungspasswuert benotzt:</string>
+ <string name="backup_enc_password_optional">Falls du deng Datesécherung wëlls verschlësselen, gëff e Passwuert an:</string>
+ <string name="backup_enc_password_required">Well däin Apparat verschlësselt ass, muss du och deng Sécherung verschlësselen. Gëff w.e.g. e Passwuert an:</string>
+ <string name="restore_enc_password_text">Falls d\'Erëmhierstellungsdate verschlësselt sinn, gëff d\'Passwuert an:</string>
+ <string name="toast_backup_started">Sécherung start...</string>
+ <string name="toast_backup_ended">Sécherung ofgeschoss</string>
+ <string name="toast_restore_started">Erëmhierstellung start...</string>
+ <string name="toast_restore_ended">Erëmhierstellung ofgeschloss</string>
+ <string name="toast_timeout">D\'Operatioun huet d\'Zäit iwwerschratt</string>
+</resources>
diff --git a/packages/BackupRestoreConfirmation/res/values-ug/strings.xml b/packages/BackupRestoreConfirmation/res/values-ug/strings.xml
new file mode 100644
index 0000000..86998b3
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values-ug/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="backup_confirm_title">تولۇق زاپاسلاش</string>
+ <string name="restore_confirm_title">تولۇق ئەسلىگە كەلتۈرۈش</string>
+ <string name="backup_confirm_text">سىستېما بارلىق سانلىق مەلۇماتلارنى باغلانغان ئۈستەلئۈستى كومپيۇتېرغا زاپاسلاشنى ئىلتىماس قىلدى. بۇ مەشغۇلاتقا يول قويامسىز؟\n\nئەگەر ئۆزىڭىز زاپاسلاشنى ئىلتىماس قىلمىسىڭىز، بۇ مەشغۇلاتقا يول قويماڭ.</string>
+ <string name="allow_backup_button_label">سانلىق مەلۇماتلىرىمنى زاپاسلا</string>
+ <string name="deny_backup_button_label">زاپاسلىما</string>
+ <string name="restore_confirm_text">سىستېما بارلىق سانلىق مەلۇماتلارنى باغلانغان ئۈستەلئۈستى كومپيۇتېرغا ئەسلىگە كەلتۈرۈشنى ئىلتىماس قىلدى. بۇ مەشغۇلاتقا يول قويامسىز؟\n\nئەگەر ئۆزىڭىز ئەسلىگە كەلتۈرۈشنى ئىلتىماس قىلمىسىڭىز، بۇ مەشغۇلاتقا يول قويماڭ. بۇ مەشغۇلات ئۈسكۈنىدىكى ھەممە سانلىق مەلۇماتلارنى قاپلىۋېتىدۇ!</string>
+ <string name="allow_restore_button_label">سانلىق-مەلۇماتىمنى ئەسلىگە كەلتۈر</string>
+ <string name="deny_restore_button_label">ئەسلىگە كەلتۈرمە</string>
+ <string name="current_password_text">تۆۋەندە نۆۋەتتىكى زاپاسنىڭ ئىمنى كىرگۈزۈڭ:</string>
+ <string name="device_encryption_restore_text">تۆۋەندە ئۈسكۈنىڭىزنىڭ شىفىرلانغان ئىمنى كىرگۈزۈڭ.</string>
+ <string name="device_encryption_backup_text">تۆۋەندە ئۈسكۈنىڭىزنىڭ شىفىرلانغان ئىمنى كىرگۈزۈڭ. ئەگەر بوش قالدۇرسىڭىز سىستېما نۆۋەتتىكى زاپاسنىڭ ئىمنى ئىشلىتىدۇ.</string>
+ <string name="backup_enc_password_text">سانلىق مەلۇماتنى تولۇق زاپاسلاشقا ئىشلىتىدىغان ئىمنى كىرگۈزۈڭ. ئەگەر بوش قالدۇرسىڭىز سىستېما نۆۋەتتىكى زاپاسنىڭ ئىمنى ئىشلىتىدۇ.</string>
+ <string name="backup_enc_password_optional">ئەگەر سانلىق مەلۇماتنى تولۇق زاپاسلاشنى شىفىرلىسىڭىز، تۆۋەندە ئىمنى كىرگۈزۈڭ:</string>
+ <string name="restore_enc_password_text">ئەگەر ئەسلىگە كەلتۈرىدىغان سانلىق مەلۇمات شىفىرلانغان بولسا تۆۋەندە ئىمنى كىرگۈزۈڭ:</string>
+ <string name="toast_backup_started">زاپاسلاش باشلاندى…</string>
+ <string name="toast_backup_ended">زاپاسلاش تامام</string>
+ <string name="toast_restore_started">ئەسلىگە كەلتۈرۈش باشلاندى…</string>
+ <string name="toast_restore_ended">ئەسلىگە كەلتۈرۈش ئاخىرلاشتى</string>
+ <string name="toast_timeout">مەشغۇلات ۋاقىت ھالقىدى</string>
+</resources>
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index aea8585..2e73119 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -32,6 +32,10 @@
<action android:name="android.net.conn.CAPTIVE_PORTAL"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
+ <intent-filter>
+ <action android:name="android.net.action.captive_portal_login"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
</activity>
</application>
</manifest>
diff --git a/packages/CaptivePortalLogin/res/values-ast-rES/strings.xml b/packages/CaptivePortalLogin/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..5030302
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/values-ast-rES/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_name">CaptivePortalLogin</string>
+ <string name="action_use_network">Usar esta rede tal cual</string>
+ <string name="action_do_not_use_network">Nun usar esta rede</string>
+</resources>
diff --git a/packages/CaptivePortalLogin/res/values-be/strings.xml b/packages/CaptivePortalLogin/res/values-be/strings.xml
new file mode 100644
index 0000000..33dc69a
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/values-be/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_name">CaptivePortalLogin</string>
+ <string name="action_use_network">Выкарыстоўваць гэтую сетку</string>
+ <string name="action_do_not_use_network">Не выкарыстоўваць гэтую сетку</string>
+</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ku/strings.xml b/packages/CaptivePortalLogin/res/values-ku/strings.xml
new file mode 100644
index 0000000..574b14f
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/values-ku/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="action_use_network">بەکارهێنانی ئەم تۆڕە وەکو</string>
+ <string name="action_do_not_use_network">ئەم تۆڕە بەکارمەهێنە</string>
+</resources>
diff --git a/packages/CaptivePortalLogin/res/values-lb/strings.xml b/packages/CaptivePortalLogin/res/values-lb/strings.xml
new file mode 100644
index 0000000..3b783cb
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/values-lb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_name">CaptivePortalLogin</string>
+ <string name="action_use_network">Dëst Netzwierk benotzen als</string>
+ <string name="action_do_not_use_network">Dëst Netzwierk net benotzen</string>
+</resources>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0fe5509..ed9c111 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -20,8 +20,10 @@ import android.app.Activity;
import android.app.LoadedApk;
import android.content.Context;
import android.content.Intent;
+import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.net.CaptivePortal;
+import android.graphics.drawable.ColorDrawable;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
@@ -32,6 +34,7 @@ import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.TypedValue;
@@ -57,6 +60,11 @@ import java.util.Random;
public class CaptivePortalLoginActivity extends Activity {
private static final String TAG = "CaptivePortalLogin";
private static final String DEFAULT_SERVER = "connectivitycheck.gstatic.com";
+
+ private static final String EXTRA_STATUS_BAR_COLOR = "status_bar_color";
+ private static final String EXTRA_ACTION_BAR_COLOR = "action_bar_color";
+ private static final String EXTRA_PROGRESS_COLOR = "progress_bar_color";
+
private static final int SOCKET_TIMEOUT_MS = 10000;
private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
@@ -68,6 +76,7 @@ public class CaptivePortalLoginActivity extends Activity {
private ConnectivityManager mCm;
private boolean mLaunchBrowser = false;
private MyWebViewClient mWebViewClient;
+ private String mResponseToken;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -81,11 +90,27 @@ public class CaptivePortalLoginActivity extends Activity {
} catch (MalformedURLException e) {
// System misconfigured, bail out in a way that at least provides network access.
Log.e(TAG, "Invalid captive portal URL, server=" + server);
+ setResult(Activity.RESULT_CANCELED);
done(Result.WANTED_AS_IS);
}
+ mResponseToken = getIntent().getStringExtra(Intent.EXTRA_TEXT);
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
+ final Intent intent = getIntent();
+ if (intent.hasExtra(EXTRA_STATUS_BAR_COLOR)) {
+ int color = intent.getIntExtra(EXTRA_STATUS_BAR_COLOR, -1);
+ if (color != -1) {
+ getWindow().setStatusBarColor(color);
+ }
+ }
+ if (intent.hasExtra(EXTRA_ACTION_BAR_COLOR)) {
+ int color = intent.getIntExtra(EXTRA_ACTION_BAR_COLOR, -1);
+ if (color != -1) {
+ getActionBar().setBackgroundDrawable(new ColorDrawable(color));
+ }
+ }
+
// Also initializes proxy system properties.
mCm.bindProcessToNetwork(mNetwork);
@@ -95,6 +120,14 @@ public class CaptivePortalLoginActivity extends Activity {
getActionBar().setDisplayShowHomeEnabled(false);
+ ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ if (intent.hasExtra(EXTRA_PROGRESS_COLOR)) {
+ int color = intent.getIntExtra(EXTRA_PROGRESS_COLOR, -1);
+ if (color != -1) {
+ myProgressBar.setProgressTintList(ColorStateList.valueOf(color));
+ }
+ }
+
// Exit app if Network disappears.
final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
if (networkCapabilities == null) {
@@ -165,6 +198,9 @@ public class CaptivePortalLoginActivity extends Activity {
mCaptivePortal.useNetwork();
break;
}
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_TEXT, mResponseToken);
+ setResult(Activity.RESULT_OK, intent);
finish();
}
@@ -298,6 +334,11 @@ public class CaptivePortalLoginActivity extends Activity {
} else if (mPagesLoaded == 2) {
// Prevent going back to empty first page.
view.clearHistory();
+ } else {
+ if (TextUtils.isEmpty(view.getUrl()) || view.getUrl().contains("text/html")) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ }
}
testForCaptivePortal();
}
diff --git a/packages/DefaultContainerService/res/values-ast-rES/strings.xml b/packages/DefaultContainerService/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..43defac
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-ast-rES/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name">Encontu d\'accesu a paquete</string>
+</resources>
diff --git a/packages/DefaultContainerService/res/values-be/strings.xml b/packages/DefaultContainerService/res/values-be/strings.xml
new file mode 100644
index 0000000..0bc61ed
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-be/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name">Памочнік доступу да пакетаў</string>
+</resources>
diff --git a/packages/DefaultContainerService/res/values-ku/strings.xml b/packages/DefaultContainerService/res/values-ku/strings.xml
new file mode 100644
index 0000000..c535010
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-ku/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name">یارمه‌تیده‌ری چوونه‌ژووره‌وه‌ی پاکێجه‌کان</string>
+</resources>
diff --git a/packages/DefaultContainerService/res/values-lb/strings.xml b/packages/DefaultContainerService/res/values-lb/strings.xml
new file mode 100644
index 0000000..37df97c
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-lb/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name">Zougrëffshëllef fir Päck</string>
+</resources>
diff --git a/packages/DefaultContainerService/res/values-ug/strings.xml b/packages/DefaultContainerService/res/values-ug/strings.xml
new file mode 100644
index 0000000..cf93ddd
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-ug/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name">بوغچا زىيارەت ياردەمچىسى</string>
+</resources>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index cc1e01a..055da3e 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -189,6 +189,7 @@ public class DefaultContainerService extends IntentService {
ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
pkg.packageName, pkg.installLocation, sizeBytes, flags);
ret.multiArch = pkg.multiArch;
+ ret.isTheme = pkg.isTheme;
return ret;
}
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/activity.xml
index 32431e3..8c35e54 100644
--- a/packages/DocumentsUI/res/layout/activity.xml
+++ b/packages/DocumentsUI/res/layout/activity.xml
@@ -29,7 +29,7 @@
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
- android:elevation="8dp"
+ android:elevation="@dimen/toolbar_elevation"
android:theme="?android:attr/actionBarTheme">
<Spinner
@@ -63,7 +63,7 @@
android:layout_gravity="start"
android:orientation="vertical"
android:elevation="16dp"
- android:background="@*android:color/white">
+ android:background="@color/drawer_background_color">
<Toolbar
android:id="@+id/roots_toolbar"
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index d62d050..90938ae 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -66,7 +66,7 @@
android:ellipsize="middle"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
- android:textColor="@*android:color/primary_text_default_material_dark" />
+ android:textColor="@color/font_color_doc_grid" />
<ImageView
android:id="@android:id/icon1"
@@ -95,7 +95,7 @@
android:ellipsize="end"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Caption"
- android:textColor="@*android:color/primary_text_default_material_dark" />
+ android:textColor="@color/font_color_doc_grid" />
<TextView
android:id="@+id/size"
@@ -107,7 +107,7 @@
android:ellipsize="end"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Caption"
- android:textColor="@*android:color/primary_text_default_material_dark" />
+ android:textColor="@color/font_color_doc_grid" />
<ImageView
android:id="@android:id/icon2"
diff --git a/packages/DocumentsUI/res/values-ast-rES/strings.xml b/packages/DocumentsUI/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..e307428
--- /dev/null
+++ b/packages/DocumentsUI/res/values-ast-rES/strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">Documentos</string>
+ <string name="title_open">Abrir dende</string>
+ <string name="title_save">Guardar en</string>
+ <string name="menu_create_dir">Crear carpeta</string>
+ <string name="menu_grid">Vista de cuadrícula</string>
+ <string name="menu_list">Vista de llista</string>
+ <string name="menu_sort">Ordenar por</string>
+ <string name="menu_search">Guetar</string>
+ <string name="menu_settings">Axustes</string>
+ <string name="menu_open">Abrir</string>
+ <string name="menu_save">Guardar</string>
+ <string name="menu_share">Compartir</string>
+ <string name="menu_delete">Desaniciar</string>
+ <string name="menu_advanced_show" product="nosdcard">Amosar almac. internu</string>
+ <string name="menu_advanced_show" product="default">Amosar tarxeta SD</string>
+ <string name="menu_advanced_hide" product="nosdcard">Anubrir almac. internu</string>
+ <string name="menu_advanced_hide" product="default">Anubrir tarxeta SD</string>
+ <string name="menu_file_size_show">Amosar tamañu de ficheru</string>
+ <string name="menu_file_size_hide">Anubrir tamañu de ficheru</string>
+ <string name="sort_name">Por nome</string>
+ <string name="sort_date">Por data de modificación</string>
+ <string name="sort_size">Por tamañu</string>
+ <string name="drawer_open">Amosar raíces</string>
+ <string name="drawer_close">Anubrir raíces</string>
+ <string name="save_error">Fallu al guardar documentu</string>
+ <string name="create_error">Fallu al crear carpeta</string>
+ <string name="query_error">Fallu al solicitar documentos</string>
+ <string name="root_recent">Recién</string>
+ <string name="root_available_bytes"><xliff:g id="size" example="3GB">%1$s</xliff:g> d\'espaciu llibre</string>
+ <string name="root_type_service">Servicios d\'almacenamientu</string>
+ <string name="root_type_shortcut">Atayos</string>
+ <string name="root_type_device">Preseos</string>
+ <string name="root_type_apps">Más apps</string>
+ <string name="empty">Ensin elementos</string>
+ <string name="toast_no_application">Nun pue abrise\'l ficheru</string>
+ <string name="toast_failed_delete">Nun pudieron desaniciase dalgunos documentos</string>
+ <string name="share_via">Compartir per aciu de</string>
+</resources>
diff --git a/packages/DocumentsUI/res/values-be/strings.xml b/packages/DocumentsUI/res/values-be/strings.xml
new file mode 100644
index 0000000..b7a9b9c
--- /dev/null
+++ b/packages/DocumentsUI/res/values-be/strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">Дакументы</string>
+ <string name="title_open">Адкрыць</string>
+ <string name="title_save">Захаваць</string>
+ <string name="menu_create_dir">Стварыць тэчку</string>
+ <string name="menu_grid">У выглядзе сеткі</string>
+ <string name="menu_list">У выглядзе спісу</string>
+ <string name="menu_sort">Сартаваць паводле</string>
+ <string name="menu_search">Пошук</string>
+ <string name="menu_settings">Налады</string>
+ <string name="menu_open">Адкрыць</string>
+ <string name="menu_save">Захаваць</string>
+ <string name="menu_share">Падзяліцца</string>
+ <string name="menu_delete">Выдаліць</string>
+ <string name="menu_advanced_show" product="nosdcard">Унутраная памяць</string>
+ <string name="menu_advanced_show" product="default">SD-картка</string>
+ <string name="menu_advanced_hide" product="nosdcard">Схаваць унутраную памяць</string>
+ <string name="menu_advanced_hide" product="default">Схаваць SD-картку</string>
+ <string name="menu_file_size_show">Паказаць памеры файлаў</string>
+ <string name="menu_file_size_hide">Схаваць памеры файлаў</string>
+ <string name="sort_name">Паводле назвы</string>
+ <string name="sort_date">Паводле даты зменаў</string>
+ <string name="sort_size">Паводле памеру</string>
+ <string name="drawer_open">Паказаць</string>
+ <string name="drawer_close">Схаваць</string>
+ <string name="save_error">Не атрымалася захаваць дакумент</string>
+ <string name="create_error">Не атрымалася стварыць тэчку</string>
+ <string name="query_error">Не атрымалася даслаць запыт</string>
+ <string name="root_recent">Апошнія</string>
+ <string name="root_available_bytes">Вольна <xliff:g id="size" example="3GB">%1$s</xliff:g></string>
+ <string name="root_type_service">Анлайн-сховішча</string>
+ <string name="root_type_shortcut">Цэтлікі</string>
+ <string name="root_type_device">Прылады</string>
+ <string name="root_type_apps">Іншыя праграмы</string>
+ <string name="empty">Няма элементаў</string>
+ <string name="toast_no_application">Немагчыма адкрыць файл</string>
+ <string name="toast_failed_delete">Не атрымалася выдаліць некаторыя дакументы</string>
+ <string name="share_via">Падзяліцца праз</string>
+</resources>
diff --git a/packages/DocumentsUI/res/values-eo/strings.xml b/packages/DocumentsUI/res/values-eo/strings.xml
new file mode 100644
index 0000000..e1321d2
--- /dev/null
+++ b/packages/DocumentsUI/res/values-eo/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">Dokumentoj</string>
+ <string name="menu_sort">Ordigi laŭ</string>
+ <string name="menu_search">Serĉi</string>
+ <string name="menu_settings">Agordoj</string>
+ <string name="menu_open">Malfermi</string>
+ <string name="menu_save">Konservi</string>
+ <string name="menu_share">Komunigi</string>
+ <string name="menu_delete">Forigi</string>
+ <string name="sort_name">Laŭ nomo</string>
+ <string name="root_recent">Lasttempaj</string>
+ <string name="root_type_device">Aparatoj</string>
+</resources>
diff --git a/packages/DocumentsUI/res/values-ku/strings.xml b/packages/DocumentsUI/res/values-ku/strings.xml
new file mode 100644
index 0000000..1677291
--- /dev/null
+++ b/packages/DocumentsUI/res/values-ku/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">به‌ڵگه‌نامه‌کان</string>
+ <string name="title_open">بیکه‌ره‌وه‌ له‌</string>
+ <string name="title_save">پاشه‌که‌وتی بکه‌ له‌</string>
+ <string name="menu_create_dir">بوخچه‌ دروست بکه‌</string>
+ <string name="menu_grid">بینینی خانه‌یی</string>
+ <string name="menu_list">بینینی لیسته‌یی</string>
+ <string name="menu_sort">ڕیزکردن به‌پێی</string>
+ <string name="menu_search">گه‌ڕان</string>
+ <string name="menu_settings">ڕێکخستنه‌کان</string>
+ <string name="menu_open">کردنه‌وه‌</string>
+ <string name="menu_save">پاشەکەوت</string>
+ <string name="menu_share">په‌رش</string>
+ <string name="menu_delete">سڕینه‌وه‌</string>
+ <string name="sort_name">به‌پێی ناو</string>
+ <string name="sort_date">به‌پێی به‌رواری ده‌ستکاریی</string>
+ <string name="sort_size">به‌پێی قه‌باره‌</string>
+ <string name="drawer_open">ڕه‌گه‌کان پیشان بده‌</string>
+ <string name="drawer_close">ڕه‌گه‌کان بشاره‌وه‌</string>
+ <string name="save_error">پاشه‌که‌وتی به‌ڵگه‌نامه‌ شکستی هێنا</string>
+ <string name="create_error">دروستکردنی بوخچه‌ شکستی هێنا</string>
+ <string name="query_error">پرسی به‌ڵگه‌نامه‌کان شکستی هێنا</string>
+ <string name="root_recent">تازه‌</string>
+ <string name="root_available_bytes"><xliff:g id="size" example="3GB">%1$s</xliff:g> به‌تاڵه‌</string>
+ <string name="root_type_service">ڕاژه‌کانی بیرگە</string>
+ <string name="root_type_shortcut">کورتبڕییه‌کان</string>
+ <string name="root_type_device">ئامێره‌کان</string>
+ <string name="root_type_apps">به‌رنامه‌ی زیاتر</string>
+ <string name="empty">هیچ بڕگه‌یه‌ک نییه‌</string>
+ <string name="toast_no_application">نه‌توانرا په‌ڕگه‌ بکرێته‌وه‌</string>
+ <string name="toast_failed_delete">نه‌توانرا هه‌ندێ به‌ڵگه‌نامه‌ بسڕێنه‌وه‌</string>
+ <string name="share_via">په‌رشیکه‌ له‌ڕێی</string>
+</resources>
diff --git a/packages/DocumentsUI/res/values-lb/strings.xml b/packages/DocumentsUI/res/values-lb/strings.xml
new file mode 100644
index 0000000..c610d82
--- /dev/null
+++ b/packages/DocumentsUI/res/values-lb/strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">Dokumenter</string>
+ <string name="title_open">Opmaache vun</string>
+ <string name="title_save">Späicheren ënner</string>
+ <string name="menu_create_dir">Dossier uleeën</string>
+ <string name="menu_grid">Gitterusiicht</string>
+ <string name="menu_list">Lëschtenusiicht</string>
+ <string name="menu_sort">Zortéieren no</string>
+ <string name="menu_search">Sichen</string>
+ <string name="menu_settings">Astellungen</string>
+ <string name="menu_open">Opmaachen</string>
+ <string name="menu_save">Späicheren</string>
+ <string name="menu_share">Deelen</string>
+ <string name="menu_delete">Läschen</string>
+ <string name="menu_advanced_show" product="nosdcard">Interne Späicher uweisen</string>
+ <string name="menu_advanced_show" product="default">SD-Kaart uweisen</string>
+ <string name="menu_advanced_hide" product="nosdcard">Interne Späicher verstoppen</string>
+ <string name="menu_advanced_hide" product="default">SD-Kaart verstoppen</string>
+ <string name="menu_file_size_show">Fichiersgréisst uweisen</string>
+ <string name="menu_file_size_hide">Fichiersgréisst verstoppen</string>
+ <string name="sort_name">No Numm</string>
+ <string name="sort_date">No Ännerungsdatum</string>
+ <string name="sort_size">No Gréisst</string>
+ <string name="drawer_open">Wuerzelen uweisen</string>
+ <string name="drawer_close">Wuerzele verstoppen</string>
+ <string name="save_error">D\'Dokument konnt net gespäichert ginn</string>
+ <string name="create_error">Den Dossier konnt net erstallt ginn</string>
+ <string name="query_error">D\'Dokumenter konnten net ofgeruff ginn</string>
+ <string name="root_recent">Rezent</string>
+ <string name="root_available_bytes"><xliff:g id="size" example="3GB">%1$s</xliff:g> fräi</string>
+ <string name="root_type_service">Späicherservicer</string>
+ <string name="root_type_shortcut">Ofkierzungen</string>
+ <string name="root_type_device">Apparater</string>
+ <string name="root_type_apps">Méi Appen</string>
+ <string name="empty">Keng Elementer</string>
+ <string name="toast_no_application">Fichier kann net opgemaach ginn</string>
+ <string name="toast_failed_delete">Verschidden Dokumenter konnten net geläscht ginn</string>
+ <string name="share_via">Deelen iwwer</string>
+</resources>
diff --git a/packages/DocumentsUI/res/values-ug/strings.xml b/packages/DocumentsUI/res/values-ug/strings.xml
new file mode 100644
index 0000000..66f0536
--- /dev/null
+++ b/packages/DocumentsUI/res/values-ug/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">پۈتۈكلەر</string>
+ <string name="title_open">ئېچىش ئورنى</string>
+ <string name="title_save">ساقلاش ئورنى</string>
+ <string name="menu_create_dir">قىسقۇچ قۇر</string>
+ <string name="menu_grid">سېتكا كۆرۈنۈش</string>
+ <string name="menu_list">تىزىم كۆرۈنۈشى</string>
+ <string name="menu_sort">تەرتىپلەش ئۇسۇلى</string>
+ <string name="menu_search">ئىزدە</string>
+ <string name="menu_settings">تەڭشەكلەر</string>
+ <string name="menu_open">ئاچ</string>
+ <string name="menu_save">ساقلا</string>
+ <string name="menu_share">ھەمبەھىر</string>
+ <string name="menu_delete">ئۆچۈر</string>
+ <string name="sort_name">ئاتى بويىچە</string>
+ <string name="sort_date">ئۆزگەرتكەن چېسلا بويىچە</string>
+ <string name="sort_size">چوڭلۇقى بويىچە</string>
+ <string name="drawer_open">غول مۇندەرىجە كۆرسەت</string>
+ <string name="drawer_close">غول مۇندەرىجە يوشۇر</string>
+ <string name="save_error">پۈتۈكنى ساقلىيالمىدى</string>
+ <string name="create_error">قىسقۇچ قۇرالمىدى</string>
+ <string name="query_error">پۈتۈكنى سۈرۈشتۈرەلمىدى</string>
+ <string name="root_recent">يېقىنقى</string>
+ <string name="root_available_bytes"><xliff:g id="SIZE">%1$s</xliff:g> بوش</string>
+ <string name="root_type_service">ساقلاش مۇلازىمەتلىرى</string>
+ <string name="root_type_shortcut">قىسقا يول</string>
+ <string name="root_type_device">ئۈسكۈنەلەر</string>
+ <string name="root_type_apps">تېخىمۇ كۆپ ئەپلەر</string>
+ <string name="empty">تۈرلەر يوق</string>
+ <string name="toast_no_application">ھۆججەت ئاچالمىدى</string>
+ <string name="toast_failed_delete">بەزى پۈتۈكلەرنى ئۆچۈرەلمەيدۇ</string>
+ <string name="share_via">ھەمبەھىر ئۇسۇلى</string>
+</resources>
diff --git a/packages/DocumentsUI/res/values/cm_colors.xml b/packages/DocumentsUI/res/values/cm_colors.xml
new file mode 100644
index 0000000..1fa1a80
--- /dev/null
+++ b/packages/DocumentsUI/res/values/cm_colors.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<resources>
+
+ <!-- adding new exposed theme components -->
+ <color name="drawer_background_color">#ffffffff</color>
+ <color name="font_color_doc_grid">#ffffffff</color>
+
+</resources>
diff --git a/packages/DocumentsUI/res/values/cm_dimens.xml b/packages/DocumentsUI/res/values/cm_dimens.xml
new file mode 100644
index 0000000..7388a4f
--- /dev/null
+++ b/packages/DocumentsUI/res/values/cm_dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The CyanogenMod 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.
+-->
+<resources>
+
+ <dimen name="toolbar_elevation">8dp</dimen>
+
+</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 0d326ec..9a86c8e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -530,8 +530,10 @@ public class DirectoryFragment extends Fragment {
for (int i = 0; i < size; i++) {
if (checked.valueAt(i)) {
final Cursor cursor = mAdapter.getItem(checked.keyAt(i));
- final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
- docs.add(doc);
+ if (cursor != null) {
+ final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
+ docs.add(doc);
+ }
}
}
diff --git a/packages/ExternalStorageProvider/res/values-ast-rES/strings.xml b/packages/ExternalStorageProvider/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..f51601a
--- /dev/null
+++ b/packages/ExternalStorageProvider/res/values-ast-rES/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Almacenamientu esternu</string>
+ <string name="root_internal_storage">Almacenamientu internu</string>
+ <string name="root_documents">Documentos</string>
+</resources>
diff --git a/packages/ExternalStorageProvider/res/values-be/strings.xml b/packages/ExternalStorageProvider/res/values-be/strings.xml
new file mode 100644
index 0000000..8882e66
--- /dev/null
+++ b/packages/ExternalStorageProvider/res/values-be/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Знешняе сховішча</string>
+ <string name="root_internal_storage">Унутраная памяць</string>
+ <string name="root_documents">Дакументы</string>
+</resources>
diff --git a/packages/ExternalStorageProvider/res/values-eo/strings.xml b/packages/ExternalStorageProvider/res/values-eo/strings.xml
new file mode 100644
index 0000000..f766f11
--- /dev/null
+++ b/packages/ExternalStorageProvider/res/values-eo/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="root_documents">Dokumentoj</string>
+</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ku/strings.xml b/packages/ExternalStorageProvider/res/values-ku/strings.xml
new file mode 100644
index 0000000..65570a3
--- /dev/null
+++ b/packages/ExternalStorageProvider/res/values-ku/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">بیرگەی ده‌ره‌کی</string>
+ <string name="root_internal_storage">بیرگەی ناوه‌کی</string>
+ <string name="root_documents">به‌ڵگه‌نامه‌کان</string>
+</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lb/strings.xml b/packages/ExternalStorageProvider/res/values-lb/strings.xml
new file mode 100644
index 0000000..ff8bb8d
--- /dev/null
+++ b/packages/ExternalStorageProvider/res/values-lb/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Externe Späicher</string>
+ <string name="root_internal_storage">Interne Späicher</string>
+ <string name="root_documents">Dokumenter</string>
+</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ug/strings.xml b/packages/ExternalStorageProvider/res/values-ug/strings.xml
new file mode 100644
index 0000000..a7f691a
--- /dev/null
+++ b/packages/ExternalStorageProvider/res/values-ug/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">سىرتقى ساقلىغۇچ</string>
+ <string name="root_internal_storage">ئىچىدىكى ساقلىغۇچ</string>
+ <string name="root_documents">پۈتۈكلەر</string>
+</resources>
diff --git a/packages/FusedLocation/res/values-ast-rES/strings.xml b/packages/FusedLocation/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..3077218
--- /dev/null
+++ b/packages/FusedLocation/res/values-ast-rES/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">Llocalización combinada</string>
+</resources>
diff --git a/packages/FusedLocation/res/values-be/strings.xml b/packages/FusedLocation/res/values-be/strings.xml
new file mode 100644
index 0000000..597f549
--- /dev/null
+++ b/packages/FusedLocation/res/values-be/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">Fused Location</string>
+</resources>
diff --git a/packages/FusedLocation/res/values-ku/strings.xml b/packages/FusedLocation/res/values-ku/strings.xml
new file mode 100644
index 0000000..b2e420d
--- /dev/null
+++ b/packages/FusedLocation/res/values-ku/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">شوێنه‌ فیوزه‌کان</string>
+</resources>
diff --git a/packages/FusedLocation/res/values-lb/strings.xml b/packages/FusedLocation/res/values-lb/strings.xml
new file mode 100644
index 0000000..3330a6d
--- /dev/null
+++ b/packages/FusedLocation/res/values-lb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">Fusionéiert Lokaliséierung</string>
+</resources>
diff --git a/packages/FusedLocation/res/values-ug/strings.xml b/packages/FusedLocation/res/values-ug/strings.xml
new file mode 100644
index 0000000..1f02fae
--- /dev/null
+++ b/packages/FusedLocation/res/values-ug/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">بىرلەشكەن ئورنى</string>
+</resources>
diff --git a/packages/InputDevices/res/values-ast-rES/strings.xml b/packages/InputDevices/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..c1e3a75
--- /dev/null
+++ b/packages/InputDevices/res/values-ast-rES/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">Preseos d\'entrada</string>
+ <string name="keyboard_layouts_label">Tecláu d\'Android</string>
+ <string name="keyboard_layout_english_uk_label">Inglés (UK)</string>
+ <string name="keyboard_layout_english_us_label">Inglés (US)</string>
+ <string name="keyboard_layout_english_us_intl">Inglés (US), estilu International</string>
+ <string name="keyboard_layout_english_us_colemak_label">Inglés (US), estilu Colemak</string>
+ <string name="keyboard_layout_english_us_dvorak_label">Inglés (US), estilu Dvorak</string>
+ <string name="keyboard_layout_german_label">Alemán</string>
+ <string name="keyboard_layout_french_label">Francés</string>
+ <string name="keyboard_layout_french_ca_label">Francés (Canadá)</string>
+ <string name="keyboard_layout_russian_label">Rusu</string>
+ <string name="keyboard_layout_russian_mac_label">Rusu, estilu Mac</string>
+ <string name="keyboard_layout_spanish_label">Español</string>
+ <string name="keyboard_layout_swiss_french_label">Francés de Suiza</string>
+ <string name="keyboard_layout_swiss_german_label">Alemán suizu</string>
+ <string name="keyboard_layout_belgian">Belga</string>
+ <string name="keyboard_layout_bulgarian">Búlgaru</string>
+ <string name="keyboard_layout_italian">Italianu</string>
+ <string name="keyboard_layout_danish">Danés</string>
+ <string name="keyboard_layout_norwegian">Noruegu</string>
+ <string name="keyboard_layout_swedish">Suecu</string>
+ <string name="keyboard_layout_finnish">Finlandés</string>
+ <string name="keyboard_layout_croatian">Croata</string>
+ <string name="keyboard_layout_czech">Checu</string>
+ <string name="keyboard_layout_estonian">Estoniu</string>
+ <string name="keyboard_layout_hungarian">Húngaru</string>
+ <string name="keyboard_layout_icelandic">Islandés</string>
+ <string name="keyboard_layout_brazilian">Brasileñu</string>
+ <string name="keyboard_layout_portuguese">Portugués</string>
+ <string name="keyboard_layout_slovak">Eslovacu</string>
+ <string name="keyboard_layout_slovenian">Eslovenu</string>
+ <string name="keyboard_layout_turkish">Turcu</string>
+ <string name="keyboard_layout_ukrainian">Ucrainianu</string>
+ <string name="keyboard_layout_arabic">Árabe</string>
+ <string name="keyboard_layout_greek">Griegu</string>
+ <string name="keyboard_layout_hebrew">Hebréu</string>
+ <string name="keyboard_layout_lithuanian">Lituanu</string>
+ <string name="keyboard_layout_spanish_latin">Español (Llatinu)</string>
+ <string name="keyboard_layout_latvian">Letón</string>
+</resources>
diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml
new file mode 100644
index 0000000..872143f
--- /dev/null
+++ b/packages/InputDevices/res/values-be/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">Прылады ўводу</string>
+ <string name="keyboard_layouts_label">Клавіятура Android</string>
+ <string name="keyboard_layout_english_uk_label">Англійская (Вялікабрытанія)</string>
+ <string name="keyboard_layout_english_us_label">Англійская (ЗША)</string>
+ <string name="keyboard_layout_english_us_intl">Англійская (ЗША, міжнародная)</string>
+ <string name="keyboard_layout_english_us_colemak_label">Англійская (ЗША, Colemak)</string>
+ <string name="keyboard_layout_english_us_dvorak_label">Англійская (ЗША, Dvorak)</string>
+ <string name="keyboard_layout_german_label">Нямецкая</string>
+ <string name="keyboard_layout_french_label">Французская</string>
+ <string name="keyboard_layout_french_ca_label">Французская (Канада)</string>
+ <string name="keyboard_layout_russian_label">Руская</string>
+ <string name="keyboard_layout_russian_mac_label">Руская, раскладка Mac</string>
+ <string name="keyboard_layout_spanish_label">Іспанская</string>
+ <string name="keyboard_layout_swiss_french_label">Французская (Швейцарыя)</string>
+ <string name="keyboard_layout_swiss_german_label">Нямецкая (Швейцарыя)</string>
+ <string name="keyboard_layout_belgian">Бельгійская</string>
+ <string name="keyboard_layout_bulgarian">Балгарская</string>
+ <string name="keyboard_layout_italian">Італьянская</string>
+ <string name="keyboard_layout_danish">Дацкая</string>
+ <string name="keyboard_layout_norwegian">Нарвежская</string>
+ <string name="keyboard_layout_swedish">Шведская</string>
+ <string name="keyboard_layout_finnish">Фінская</string>
+ <string name="keyboard_layout_croatian">Харвацкая</string>
+ <string name="keyboard_layout_czech">Чэшская</string>
+ <string name="keyboard_layout_estonian">Эстонская</string>
+ <string name="keyboard_layout_hungarian">Венгерская</string>
+ <string name="keyboard_layout_icelandic">Ісландская</string>
+ <string name="keyboard_layout_brazilian">Бразільская</string>
+ <string name="keyboard_layout_portuguese">Партугальская</string>
+ <string name="keyboard_layout_slovak">Славацкая</string>
+ <string name="keyboard_layout_slovenian">Славенская</string>
+ <string name="keyboard_layout_turkish">Турэцкая</string>
+ <string name="keyboard_layout_ukrainian">Украінская</string>
+ <string name="keyboard_layout_arabic">Арабская</string>
+ <string name="keyboard_layout_greek">Грэцкая</string>
+ <string name="keyboard_layout_hebrew">Hebrew</string>
+ <string name="keyboard_layout_lithuanian">Літоўская</string>
+ <string name="keyboard_layout_spanish_latin">Іспанская (Лацінская Амерыка)</string>
+ <string name="keyboard_layout_latvian">Латышская</string>
+</resources>
diff --git a/packages/InputDevices/res/values-eo/strings.xml b/packages/InputDevices/res/values-eo/strings.xml
new file mode 100644
index 0000000..6f46f59
--- /dev/null
+++ b/packages/InputDevices/res/values-eo/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="keyboard_layout_croatian">Kroata</string>
+ <string name="keyboard_layout_icelandic">Islanda</string>
+ <string name="keyboard_layout_turkish">Turka</string>
+ <string name="keyboard_layout_ukrainian">Ukraina</string>
+ <string name="keyboard_layout_arabic">Araba</string>
+ <string name="keyboard_layout_greek">Greka</string>
+ <string name="keyboard_layout_hebrew">Hebrea</string>
+</resources>
diff --git a/packages/InputDevices/res/values-ku/strings.xml b/packages/InputDevices/res/values-ku/strings.xml
new file mode 100644
index 0000000..b002621
--- /dev/null
+++ b/packages/InputDevices/res/values-ku/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">ئامێری تێچان</string>
+ <string name="keyboard_layouts_label">ته‌خته‌کلیلی ئه‌ندرۆید</string>
+ <string name="keyboard_layout_english_uk_label">ئینگلیزی (به‌ریتانیا)</string>
+ <string name="keyboard_layout_english_us_label">ئینگلیزی (ئه‌مریکا)</string>
+ <string name="keyboard_layout_english_us_intl">ئینگلیزی (ئه‌مریکا)، شێوازی نێوده‌وڵه‌تی</string>
+ <string name="keyboard_layout_english_us_colemak_label">ئینگلیزی (ئه‌مریکا)، شێوازی کۆلیمارک</string>
+ <string name="keyboard_layout_english_us_dvorak_label">ئینگلیزی(ئه‌مریکا)، شێوازی دڤۆراک</string>
+ <string name="keyboard_layout_german_label">ئه‌ڵمانی</string>
+ <string name="keyboard_layout_french_label">فه‌ره‌نسی</string>
+ <string name="keyboard_layout_french_ca_label">فه‌ره‌نسی (که‌نه‌دا)</string>
+ <string name="keyboard_layout_russian_label">ڕووسی</string>
+ <string name="keyboard_layout_russian_mac_label">ڕووسی، شێوازی ماک</string>
+ <string name="keyboard_layout_spanish_label">ئیسپانی</string>
+ <string name="keyboard_layout_swiss_french_label">فه‌ره‌نسیی سویسری</string>
+ <string name="keyboard_layout_swiss_german_label">فه‌ره‌نسیی ئه‌ڵمانی</string>
+ <string name="keyboard_layout_belgian">به‌لجیکی</string>
+ <string name="keyboard_layout_bulgarian">بولگاری</string>
+ <string name="keyboard_layout_italian">ئیتالی</string>
+ <string name="keyboard_layout_danish">دانی</string>
+ <string name="keyboard_layout_norwegian">نه‌رویجی</string>
+ <string name="keyboard_layout_swedish">سویدی</string>
+ <string name="keyboard_layout_finnish">فینله‌ندی</string>
+ <string name="keyboard_layout_croatian">کرواتی</string>
+ <string name="keyboard_layout_czech">چیکی</string>
+ <string name="keyboard_layout_estonian">ئیستۆنی</string>
+ <string name="keyboard_layout_hungarian">هه‌نگاری</string>
+ <string name="keyboard_layout_icelandic">ئایسله‌ندی</string>
+ <string name="keyboard_layout_brazilian">به‌ڕازیلی</string>
+ <string name="keyboard_layout_portuguese">پورتوگالی</string>
+ <string name="keyboard_layout_slovak">سلۆڤاکی</string>
+ <string name="keyboard_layout_slovenian">سلۆڤینی</string>
+ <string name="keyboard_layout_turkish">تورکی</string>
+ <string name="keyboard_layout_ukrainian">ئۆکرانی</string>
+</resources>
diff --git a/packages/InputDevices/res/values-lb/strings.xml b/packages/InputDevices/res/values-lb/strings.xml
new file mode 100644
index 0000000..3193fa6
--- /dev/null
+++ b/packages/InputDevices/res/values-lb/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">Apparater fir anzeginn</string>
+ <string name="keyboard_layouts_label">Android-Tastatur</string>
+ <string name="keyboard_layout_english_uk_label">Englesch (Groussbritannien)</string>
+ <string name="keyboard_layout_english_us_label">Englesch (USA)</string>
+ <string name="keyboard_layout_english_us_intl">Englesch (USA), international</string>
+ <string name="keyboard_layout_english_us_colemak_label">Englesch (USA), Colemak</string>
+ <string name="keyboard_layout_english_us_dvorak_label">Englesch (USA), Dvorak</string>
+ <string name="keyboard_layout_german_label">Däitsch</string>
+ <string name="keyboard_layout_french_label">Franséisch</string>
+ <string name="keyboard_layout_french_ca_label">Franséisch (Kanada)</string>
+ <string name="keyboard_layout_russian_label">Russesch</string>
+ <string name="keyboard_layout_russian_mac_label">Russesch, Mac</string>
+ <string name="keyboard_layout_spanish_label">Spuenesch</string>
+ <string name="keyboard_layout_swiss_french_label">Schwäizer Franséisch</string>
+ <string name="keyboard_layout_swiss_german_label">Schwäizer Däitsch</string>
+ <string name="keyboard_layout_belgian">Belsch</string>
+ <string name="keyboard_layout_bulgarian">Bulgaresch</string>
+ <string name="keyboard_layout_italian">Italienesch</string>
+ <string name="keyboard_layout_danish">Dänesch</string>
+ <string name="keyboard_layout_norwegian">Norwegesch</string>
+ <string name="keyboard_layout_swedish">Schwedesch</string>
+ <string name="keyboard_layout_finnish">Finnesch</string>
+ <string name="keyboard_layout_croatian">Kroatesch</string>
+ <string name="keyboard_layout_czech">Tschechesch</string>
+ <string name="keyboard_layout_estonian">Estnesch</string>
+ <string name="keyboard_layout_hungarian">Ungaresch</string>
+ <string name="keyboard_layout_icelandic">Islännesch</string>
+ <string name="keyboard_layout_brazilian">Brasilianesch</string>
+ <string name="keyboard_layout_portuguese">Portugisesch</string>
+ <string name="keyboard_layout_slovak">Slowakesch</string>
+ <string name="keyboard_layout_slovenian">Slowenesch</string>
+ <string name="keyboard_layout_turkish">Tierkesch</string>
+ <string name="keyboard_layout_ukrainian">Ukrainesch</string>
+ <string name="keyboard_layout_arabic">Arabesch</string>
+ <string name="keyboard_layout_greek">Griichesch</string>
+ <string name="keyboard_layout_hebrew">Hebräesch</string>
+ <string name="keyboard_layout_lithuanian">Litauesch</string>
+ <string name="keyboard_layout_spanish_latin">Spuenesch (Latäin)</string>
+ <string name="keyboard_layout_latvian">Lettesch</string>
+</resources>
diff --git a/packages/InputDevices/res/values-ug/strings.xml b/packages/InputDevices/res/values-ug/strings.xml
new file mode 100644
index 0000000..a82c1b1
--- /dev/null
+++ b/packages/InputDevices/res/values-ug/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<resources>
+ <string name="app_label">كىرگۈزۈش ئۈسكۈنىلىرى</string>
+ <string name="keyboard_layouts_label">ئاندىرويىد ھەرپتاختا</string>
+ <string name="keyboard_layout_english_uk_label">ئىنگلىزچە (ئەنگلىيە)</string>
+ <string name="keyboard_layout_english_us_label">ئىنگلىزچە (ئا ق ش)</string>
+ <string name="keyboard_layout_english_us_intl">ئىنگلىزچە (ئا ق ش)، خەلقئارا ئۇسلۇبى</string>
+ <string name="keyboard_layout_english_us_colemak_label">ئىنگلىزچە (ئا ق ش)، Colemak ئۇسلۇبى</string>
+ <string name="keyboard_layout_english_us_dvorak_label">ئىنگلىزچە (ئا ق ش)، Dvorak ئۇسلۇبى</string>
+ <string name="keyboard_layout_german_label">گېرمانچە</string>
+ <string name="keyboard_layout_french_label">فىرانسۇزچە</string>
+ <string name="keyboard_layout_french_ca_label">فىرانسۇزچە (كانادا)</string>
+ <string name="keyboard_layout_russian_label">رۇسچە</string>
+ <string name="keyboard_layout_russian_mac_label">رۇسچە، Mac ئۇسلۇبى</string>
+ <string name="keyboard_layout_spanish_label">ئىسپانچە</string>
+ <string name="keyboard_layout_swiss_french_label">فىرانسۇزچە شىۋېتسارىيە</string>
+ <string name="keyboard_layout_swiss_german_label">گېرمانچە شىۋېتسارىيە</string>
+ <string name="keyboard_layout_belgian">بېلگىيەچە</string>
+ <string name="keyboard_layout_bulgarian">بۇلغارچە</string>
+ <string name="keyboard_layout_italian">ئىتالىيانچە</string>
+ <string name="keyboard_layout_danish">دانىشچە</string>
+ <string name="keyboard_layout_norwegian">نورۋىگىيەچە</string>
+ <string name="keyboard_layout_swedish">شۋېدچە</string>
+ <string name="keyboard_layout_finnish">فىنچە</string>
+ <string name="keyboard_layout_croatian">خورۋاتچە</string>
+ <string name="keyboard_layout_czech">چېخچە</string>
+ <string name="keyboard_layout_estonian">ئېستونچە</string>
+ <string name="keyboard_layout_hungarian">ھونگىرچە</string>
+ <string name="keyboard_layout_icelandic">ئىسلاندچە</string>
+ <string name="keyboard_layout_brazilian">بىرازىلىيەچە</string>
+ <string name="keyboard_layout_portuguese">پورتۇگالچە</string>
+ <string name="keyboard_layout_slovak">سلوۋاكچە</string>
+ <string name="keyboard_layout_slovenian">سىلوۋېنىيەچە</string>
+ <string name="keyboard_layout_turkish">تۈركچە</string>
+ <string name="keyboard_layout_ukrainian">ئۇكرائىنچە</string>
+</resources>
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 9083212..ad33536f 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -18,6 +18,8 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files)
+LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.sdk
+
LOCAL_MODULE := Keyguard
LOCAL_CERTIFICATE := platform
diff --git a/packages/Keyguard/res/layout/keyguard_pin_view.xml b/packages/Keyguard/res/layout/keyguard_pin_view.xml
index d3fb982..b0a86bb 100644
--- a/packages/Keyguard/res/layout/keyguard_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pin_view.xml
@@ -78,7 +78,7 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
- android:background="#28FFFFFF"
+ android:background="@color/keyguard_sim_view_divider"
/>
</com.android.keyguard.AlphaOptimizedRelativeLayout>
<LinearLayout
diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
index b0a93e6..fe514a6 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
@@ -83,7 +83,7 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
- android:background="#28FFFFFF"
+ android:background="@color/keyguard_sim_view_divider"
/>
</RelativeLayout>
<LinearLayout
diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
index cf41bd3..30cc815 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
@@ -84,7 +84,7 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
- android:background="#28FFFFFF"
+ android:background="@color/keyguard_sim_view_divider"
/>
</RelativeLayout>
<LinearLayout
diff --git a/packages/Keyguard/res/values-af/cm_strings.xml b/packages/Keyguard/res/values-af/cm_strings.xml
new file mode 100644
index 0000000..c9fb74e
--- /dev/null
+++ b/packages/Keyguard/res/values-af/cm_strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM Perso gesluit</string>
+ <string name="lockscreen_sim_error_message_short">Ongeldige kaart.</string>
+ <string name="kg_invalid_sim_length">Fout: Invoer is korter as die minimum lengte</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ar/cm_strings.xml b/packages/Keyguard/res/values-ar/cm_strings.xml
new file mode 100644
index 0000000..46f5512
--- /dev/null
+++ b/packages/Keyguard/res/values-ar/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">بطاقة غير صالحة.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ast-rES/cm_strings.xml b/packages/Keyguard/res/values-ast-rES/cm_strings.xml
new file mode 100644
index 0000000..ead7e33
--- /dev/null
+++ b/packages/Keyguard/res/values-ast-rES/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Tarxeta inválida.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ast-rES/strings.xml b/packages/Keyguard/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..46bc659
--- /dev/null
+++ b/packages/Keyguard/res/values-ast-rES/strings.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">Bloquéu</string>
+ <string name="keyguard_password_enter_pin_code">Inxerta\'l códigu PIN.</string>
+ <string name="keyguard_password_enter_puk_code">Escribi\'l PUK de la tarxeta SIM y un códigu PIN nuevu</string>
+ <string name="keyguard_password_enter_puk_prompt">Códigu PUK de la tarxeta SIM</string>
+ <string name="keyguard_password_enter_pin_prompt">Códigu nuevu PIN de tarxeta SIM</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">Toca pa introducir contraseña</font></string>
+ <string name="keyguard_password_enter_password_code">Inxerta la contraseña pa desbloquiar.</string>
+ <string name="keyguard_password_enter_pin_password_code">Inxerta\'l códigu PIN pa desbloquiar.</string>
+ <string name="keyguard_password_wrong_pin_code">Códigu PIN incorreutu</string>
+ <string name="keyguard_charged">Cargada</string>
+ <string name="keyguard_plugged_in">Cargando</string>
+ <string name="keyguard_low_battery">Coneuta\'l cargador.</string>
+ <string name="keyguard_instructions_when_pattern_disabled">Empobina al menú pa desbloquiar la pantalla.</string>
+ <string name="keyguard_network_locked_message">Bloquiada pa la rede</string>
+ <string name="keyguard_missing_sim_message_short">Falta la tarxeta SIM</string>
+ <string name="keyguard_missing_sim_message" product="tablet">Nun s\'inxertó nenguna tarxeta SIM na tablet.</string>
+ <string name="keyguard_missing_sim_message" product="default">Nun s\'inxertó nenguna tarxeta SIM nel teléfonu.</string>
+ <string name="keyguard_missing_sim_instructions">Inxerta una tarxeta SIM.</string>
+ <string name="keyguard_missing_sim_instructions_long">Falta la tarxeta SIM o nun pue lleese. Inxerta una tarxeta SIM.</string>
+ <string name="keyguard_permanent_disabled_sim_message_short">Tarxeta SIM inutilizable</string>
+ <string name="keyguard_permanent_disabled_sim_instructions">La to tarxeta SIM inhabilitóse dafechu.\n Pa obtener otra, ponte en contautu col to fornidor de servicios de telefonía.</string>
+ <string name="keyguard_sim_locked_message">La tarxeta SIM ta bloquiada.</string>
+ <string name="keyguard_sim_puk_locked_message">La tarxeta SIM ta bloquiada col códigu PUK.</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message">Desbloquiando tarxeta SIM…</string>
+ <string name="keyguard_accessibility_pattern_unlock">Desbloquéu por patrón</string>
+ <string name="keyguard_accessibility_pin_unlock">Desbloquéu por PIN</string>
+ <string name="keyguard_accessibility_password_unlock">Desbloquéu por contraseña</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">Área de patrón</string>
+ <string name="keyguard_accessibility_slide_area">Área pa eslizar</string>
+ <string name="keyguard_accessibility_next_alarm">Próxima alarma afitada a les <xliff:g id="alarm" example="Fri 8:30 AM">%1$s</xliff:g></string>
+ <string name="keyboardview_keycode_delete">Desaniciar</string>
+ <string name="keyboardview_keycode_enter">Intro</string>
+ <string name="kg_forgot_pattern_button_text">¿Escaecisti\'l patrón?</string>
+ <string name="kg_wrong_pattern">El patrón ye incorreutu</string>
+ <string name="kg_wrong_password">Contraseña incorreuta</string>
+ <string name="kg_wrong_pin">PIN incorreutu</string>
+ <string name="kg_too_many_failed_attempts_countdown">Inténtalo otra vegada en <xliff:g id="NUMBER">%d</xliff:g> segundos.</string>
+ <string name="kg_pattern_instructions">Dibuxa\'l to patrón de desbloquéu.</string>
+ <string name="kg_sim_pin_instructions">Inxerta\'l PIN de la tarxeta SIM.</string>
+ <string name="kg_pin_instructions">Inxerta\'l PIN.</string>
+ <string name="kg_password_instructions">Escribi la contraseña.</string>
+ <string name="kg_puk_enter_puk_hint">La tarxeta SIM ta inhabilitada. Pa continuar, inxerta\'l códigu PUK. Si quies más información, ponte en contautu col operador</string>
+ <string name="kg_puk_enter_pin_hint">Inxerta\'l códigu PIN deseáu</string>
+ <string name="kg_enter_confirm_pin_hint">Confirma\'l códigu PIN</string>
+ <string name="kg_sim_unlock_progress_dialog_message">Desbloquiando tarxeta SIM…</string>
+ <string name="kg_invalid_sim_pin_hint">Inxerta un códigu PIN con una llonxitú ente cuatro y ocho díxitos.</string>
+ <string name="kg_invalid_sim_puk_hint">El códigu PUK tien de tener ocho númberos como mínimu.</string>
+ <string name="kg_invalid_puk">Vuelvi a inxertar el códigu PUK correutu. Si inxertes un códigu incorreutu delles vegaes, va inhabilitase la tarxeta SIM.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">Los códigos PIN nun concasen.</string>
+ <string name="kg_login_too_many_attempts">Abondos intentos incorreutos de crear el patrón</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">Inxertasti un códigu PIN incorreutu <xliff:g id="NUMBER_0">%d</xliff:g> vegaes. \n\nInténtalo otra vegada en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">Inxertasti una contraseña incorreuta <xliff:g id="NUMBER_0">%d</xliff:g> vegaes. \n\nInténtalo otra vegada en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. \n\nInténtalo otra vegada en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet">
+ Intentasti desbloquiar la tablet <xliff:g id="number">%d</xliff:g> vegaes.
+ Dempués de <xliff:g id="number">%d</xliff:g> intentos fallíos más,
+ esta tablet va resetease, desaniciando tolos sos datos.
+ </string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default">
+ Intentasti desbloquiar el teléfonu tablet <xliff:g id="number">%d</xliff:g> vegaes.
+ Dempués de <xliff:g id="number">%d</xliff:g> intentos fallíos más,
+ esta tablet va resetease, desaniciando tolos sos datos.</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet">
+ Intentasti desbloquiar la tablet <xliff:g id="number">%d</xliff:g> vegaes.
+ Esta tablet va resetease, desaniciando tolos sos datos. </string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, vas tener d\'usar una cuenta de corréu-e pa desbloquiar la tablet.\n\n Inténtalo otra vegada en <xliff:g id="NUMBER_2">%d</xliff:g> segundos.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">Fallasti <xliff:g id="NUMBER_0">%d</xliff:g> vegaes al dibuxar el patrón de desbloquéu. Si falles otres <xliff:g id="NUMBER_1">%d</xliff:g> vegaes, vas tener d\'usar una cuenta de corréu-e pa desbloquiar el teléfonu.\n\n Inténtalo otra vegada en <xliff:g id="NUMBER_2">%d</xliff:g> segundos.</string>
+ <string name="kg_password_wrong_pin_code_pukked">Códigu PIN de la tarxeta SIM incorreutu. Tienes de contautar col to operador pa desbloquiar el preséu.</string>
+ <string name="kg_password_wrong_puk_code_dead">La tarxeta SIM nun pue usase. Ponte en contautu col to operador.</string>
+ <string name="kg_password_pin_failed">Fallu al intentar desbloquiar la tarxeta SIM col códigu PIN</string>
+ <string name="kg_password_puk_failed">Fallu al intentar desbloquiar la tarxeta SIM col códigu PUK</string>
+ <string name="kg_pin_accepted">Códigu aceutáu</string>
+ <string name="keyguard_carrier_default">Ensin serviciu</string>
+</resources>
diff --git a/packages/Keyguard/res/values-az-rAZ/cm_strings.xml b/packages/Keyguard/res/values-az-rAZ/cm_strings.xml
new file mode 100644
index 0000000..260bf77
--- /dev/null
+++ b/packages/Keyguard/res/values-az-rAZ/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Etibarsız kart.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-be/cm_strings.xml b/packages/Keyguard/res/values-be/cm_strings.xml
new file mode 100644
index 0000000..9a7baf5
--- /dev/null
+++ b/packages/Keyguard/res/values-be/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM-картка заблакавана аператарам</string>
+ <string name="lockscreen_sim_error_message_short">Памылка карты.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Увядзіце PIN-код. У вас засталася <xliff:g id="number">%d</xliff:g> спроба перад тым, як вам давядзецца звярнуцца да аператара дзеля разблакоўкі.</item>
+ <item quantity="few">Увядзіце PIN-код. У вас засталося<xliff:g id="number">%d</xliff:g> спробы.</item>
+ <item quantity="other">Увядзіце PIN-код. У вас засталося <xliff:g id="number">%d</xliff:g> спробы.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Памылка: маленькая даўжыня</string>
+</resources>
diff --git a/packages/Keyguard/res/values-bg/cm_strings.xml b/packages/Keyguard/res/values-bg/cm_strings.xml
new file mode 100644
index 0000000..08e97f6
--- /dev/null
+++ b/packages/Keyguard/res/values-bg/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">СИМ картата е блокирана от оператора</string>
+ <string name="lockscreen_sim_error_message_short">Невалидна карта.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Въведете ПИН кода на СИМ картата, имате още <xliff:g id="number">%d </xliff:g> останал опит, преди да трябва да се свържете с вашия оператор за отключване на устройството.</item>
+ <item quantity="other">Въведете ПИН кода на СИМ картата, имате още <xliff:g id="number">%d </xliff:g> останали опити.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Грешка: Въведеното е по-късо от минималната дължина</string>
+</resources>
diff --git a/packages/Keyguard/res/values-bn-rBD/cm_strings.xml b/packages/Keyguard/res/values-bn-rBD/cm_strings.xml
new file mode 100644
index 0000000..bdb0111
--- /dev/null
+++ b/packages/Keyguard/res/values-bn-rBD/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">অবৈধ কার্ড।</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ca/cm_strings.xml b/packages/Keyguard/res/values-ca/cm_strings.xml
new file mode 100644
index 0000000..83bfdce
--- /dev/null
+++ b/packages/Keyguard/res/values-ca/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">La targeta SIM té un bloqueig Personal</string>
+ <string name="lockscreen_sim_error_message_short">Targeta invàlida.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Introdueix el PIN de la SIM, tens <xliff:g id="number">%d</xliff:g> intent restant abans que hagis de contactar amb el teu operador per desbloquejar el teu dispositiu.</item>
+ <item quantity="other">Introdueix el PIN de la SIM, tens <xliff:g id="number">%d</xliff:g> intents restants.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Error: L\'entrada és més curta que la longitud mínima</string>
+</resources>
diff --git a/packages/Keyguard/res/values-cs/cm_strings.xml b/packages/Keyguard/res/values-cs/cm_strings.xml
new file mode 100644
index 0000000..20fae9d
--- /dev/null
+++ b/packages/Keyguard/res/values-cs/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM je zamčená pomocí Perso</string>
+ <string name="lockscreen_sim_error_message_short">Neplatná SIM karta.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Zadejte PIN kód, máte <xliff:g id="number">%d</xliff:g> zbývající pokus než budete muset kontaktovat operátora pro odemčení zařízení.</item>
+ <item quantity="few">Zadejte PIN kód, máte <xliff:g id="number">%d</xliff:g> zbývající pokusy.</item>
+ <item quantity="other">Zadejte PIN kód, máte <xliff:g id="number">%d</xliff:g> zbývajících pokusů.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Chyba: vstup je kratší než minimální délka</string>
+</resources>
diff --git a/packages/Keyguard/res/values-da/cm_strings.xml b/packages/Keyguard/res/values-da/cm_strings.xml
new file mode 100644
index 0000000..34c3190
--- /dev/null
+++ b/packages/Keyguard/res/values-da/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Ugyldigt SIM-kort.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-de/cm_strings.xml b/packages/Keyguard/res/values-de/cm_strings.xml
new file mode 100644
index 0000000..2369d8e
--- /dev/null
+++ b/packages/Keyguard/res/values-de/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM-Karte ist gesperrt</string>
+ <string name="lockscreen_sim_error_message_short">Ungültige SIM-Karte.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">SIM-PIN eingeben. Sie haben noch <xliff:g id="number">%d</xliff:g> Versuch, bevor Sie den Netzbetreiber zum Entsperren des Gerätes kontaktieren müssen.</item>
+ <item quantity="other">SIM-PIN eingeben. Sie haben noch <xliff:g id="number">%d</xliff:g> Versuche, bevor Sie den Netzbetreiber zum Entsperren des Gerätes kontaktieren müssen.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Fehler: Eingabe ist kürzer als die Mindestlänge.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-el/cm_strings.xml b/packages/Keyguard/res/values-el/cm_strings.xml
new file mode 100644
index 0000000..6ea7b00
--- /dev/null
+++ b/packages/Keyguard/res/values-el/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">Η κάρτα SIM είναι κλειδωμένη</string>
+ <string name="lockscreen_sim_error_message_short">Μη έγκυρη κάρτα.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Εισάγετε το PIN, έχετε <xliff:g id="number">%d</xliff:g> προσπάθειες πριν χρειαστεί να επικοινωνήσετε με τον πάροχό σας για να ξεκλειδώσετε τη συσκευή σας.</item>
+ <item quantity="other">Εισάγετε το PIN, έχετε <xliff:g id="number">%d</xliff:g> προσπάθειες.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Σφάλμα: Το μήκος εισόδου είναι μικρότερο από το ελάχιστο μήκος</string>
+</resources>
diff --git a/packages/Keyguard/res/values-en-rAU/cm_strings.xml b/packages/Keyguard/res/values-en-rAU/cm_strings.xml
new file mode 100644
index 0000000..5bf42fa
--- /dev/null
+++ b/packages/Keyguard/res/values-en-rAU/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Invalid card.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-en-rIN/cm_strings.xml b/packages/Keyguard/res/values-en-rIN/cm_strings.xml
new file mode 100644
index 0000000..f737d9e
--- /dev/null
+++ b/packages/Keyguard/res/values-en-rIN/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM is Perso locked</string>
+ <string name="lockscreen_sim_error_message_short">Invalid card.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item>
+ <item quantity="other">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Error: Input shorter than minimum length</string>
+</resources>
diff --git a/packages/Keyguard/res/values-eo/cm_strings.xml b/packages/Keyguard/res/values-eo/cm_strings.xml
new file mode 100644
index 0000000..60da84e
--- /dev/null
+++ b/packages/Keyguard/res/values-eo/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Nevalida karto.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-eo/strings.xml b/packages/Keyguard/res/values-eo/strings.xml
new file mode 100644
index 0000000..dcaafc1
--- /dev/null
+++ b/packages/Keyguard/res/values-eo/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_plugged_in">Ŝarĝado</string>
+ <string name="keyboardview_keycode_delete">Forigi</string>
+ <string name="keyguard_carrier_default">Neniu servo.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-es/cm_strings.xml b/packages/Keyguard/res/values-es/cm_strings.xml
new file mode 100644
index 0000000..72ed182
--- /dev/null
+++ b/packages/Keyguard/res/values-es/cm_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">La tarjeta SIM tiene un bloqueo personalizado</string>
+ <string name="lockscreen_sim_error_message_short">Tarjeta no válida.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Introduce el código PIN. Tienes <xliff:g id="number">%d</xliff:g> intento restante antes de tener que comunicarte con tu operadora para desbloquear el dispositivo.</item>
+ <item quantity="other">Introduce el código PIN. Tienes <xliff:g id="number">%d</xliff:g> intentos restantes.</item>
+ </plurals>
+</resources>
diff --git a/packages/Keyguard/res/values-et-rEE/cm_strings.xml b/packages/Keyguard/res/values-et-rEE/cm_strings.xml
new file mode 100644
index 0000000..01fd936
--- /dev/null
+++ b/packages/Keyguard/res/values-et-rEE/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Kehtetu kaart.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-eu-rES/cm_strings.xml b/packages/Keyguard/res/values-eu-rES/cm_strings.xml
new file mode 100644
index 0000000..41081c9
--- /dev/null
+++ b/packages/Keyguard/res/values-eu-rES/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM txartelak blokeo pertsonala du</string>
+ <string name="lockscreen_sim_error_message_short">Txartela baliogabea.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Sartu SIM txartelaren PIN kodea, saiakera <xliff:g id="number">%d</xliff:g> geratzen zaizu gailua desblokeatzeko zure operadorearekin kontaktuan jarri behar aurretik.</item>
+ <item quantity="other">Sartu SIM txartelaren PIN kodea, <xliff:g id="number">%d</xliff:g> saiakera geratzen zaizkizu.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Errorea: Sarrera gutxieneko luzera baino laburragoa da</string>
+</resources>
diff --git a/packages/Keyguard/res/values-fa/cm_strings.xml b/packages/Keyguard/res/values-fa/cm_strings.xml
new file mode 100644
index 0000000..84bca66
--- /dev/null
+++ b/packages/Keyguard/res/values-fa/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">سیم کارت نامعتبر.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-fi/cm_strings.xml b/packages/Keyguard/res/values-fi/cm_strings.xml
new file mode 100644
index 0000000..62cc982
--- /dev/null
+++ b/packages/Keyguard/res/values-fi/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM-kortti on Perso-lukittu</string>
+ <string name="lockscreen_sim_error_message_short">Virheellinen kortti.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Syötä SIM-kortin PIN-koodi, sinulla on <xliff:g id="number">%d</xliff:g> yritys jäljellä, tai sinun on pyydetttävä operaattoriasi poistamaan laitteen lukitus.</item>
+ <item quantity="other">Anna SIM-kortin PIN-koodi, sinulla on <xliff:g id="number">%d</xliff:g> yritystä jäljellä.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Virhe: Syöttö lyhyempi kuin vähimmäispituus</string>
+</resources>
diff --git a/packages/Keyguard/res/values-fr/cm_strings.xml b/packages/Keyguard/res/values-fr/cm_strings.xml
new file mode 100644
index 0000000..4d3398e
--- /dev/null
+++ b/packages/Keyguard/res/values-fr/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">La carte SIM possède un verrouillage personnel</string>
+ <string name="lockscreen_sim_error_message_short">Carte SIM incorrecte.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Entrez le code PIN de la carte SIM, il vous reste <xliff:g id="number">%d</xliff:g> tentative avant d\'avoir à contacter votre opérateur pour déverrouiller votre appareil.</item>
+ <item quantity="other">Entrez le code PIN de la carte SIM, il vous reste <xliff:g id="number">%d</xliff:g> tentatives.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Erreur : code entré trop court</string>
+</resources>
diff --git a/packages/Keyguard/res/values-gl-rES/cm_strings.xml b/packages/Keyguard/res/values-gl-rES/cm_strings.xml
new file mode 100644
index 0000000..1e46e59
--- /dev/null
+++ b/packages/Keyguard/res/values-gl-rES/cm_strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">A SIM/RUIM personalizada está bloqueada</string>
+ <string name="lockscreen_sim_error_message_short">Esta tarxeta non é válida.</string>
+ <string name="kg_invalid_sim_length">Erro: O dato introducido é máis curto có mínimo esixido</string>
+</resources>
diff --git a/packages/Keyguard/res/values-hi/cm_strings.xml b/packages/Keyguard/res/values-hi/cm_strings.xml
new file mode 100644
index 0000000..424c41c
--- /dev/null
+++ b/packages/Keyguard/res/values-hi/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">अमान्य कार्ड।</string>
+</resources>
diff --git a/packages/Keyguard/res/values-hr/cm_strings.xml b/packages/Keyguard/res/values-hr/cm_strings.xml
new file mode 100644
index 0000000..fc1c567
--- /dev/null
+++ b/packages/Keyguard/res/values-hr/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM kartica je Perso zaključana</string>
+ <string name="lockscreen_sim_error_message_short">Kartica nije valjana.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Upišite SIM PIN, preostao vam je <xliff:g id="number">%d</xliff:g> pokušaj nakon čega ćete morati kontaktirati svog pružatelja usluga da otključa vaš uređaj.</item>
+ <item quantity="few">Upišite SIM PIN, preostalo vam je <xliff:g id="number">%d</xliff:g> pokušaja.</item>
+ <item quantity="other">Upišite SIM PIN, preostalo vam je <xliff:g id="number">%d</xliff:g> pokušaja.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Pogreška: Ulaz je kraći od minimalne potrebne duljine</string>
+</resources>
diff --git a/packages/Keyguard/res/values-hu/cm_strings.xml b/packages/Keyguard/res/values-hu/cm_strings.xml
new file mode 100644
index 0000000..b985e02
--- /dev/null
+++ b/packages/Keyguard/res/values-hu/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM Perso zárva</string>
+ <string name="lockscreen_sim_error_message_short">Érvénytelen kártya.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Adja meg a SIM-kártya PIN-kódját. <xliff:g id="number">%d</xliff:g> kísérlete maradt mielőtt fel kell vennie a kapcsolatot a mobilszolgáltatójával a készülék feloldásához.</item>
+ <item quantity="other">Adja meg a SIM-kártya PIN-kódját. <xliff:g id="number">%d</xliff:g> kísérlete maradt.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Hiba: A bemeneti adat rövidebb, mint a minimális hossz</string>
+</resources>
diff --git a/packages/Keyguard/res/values-in/cm_strings.xml b/packages/Keyguard/res/values-in/cm_strings.xml
new file mode 100644
index 0000000..0a880fb
--- /dev/null
+++ b/packages/Keyguard/res/values-in/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Kartu tidak valid.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-it/cm_strings.xml b/packages/Keyguard/res/values-it/cm_strings.xml
new file mode 100644
index 0000000..1c48611
--- /dev/null
+++ b/packages/Keyguard/res/values-it/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM bloccata</string>
+ <string name="lockscreen_sim_error_message_short">Scheda non valida.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Inserisci il PIN della SIM, hai ancora <xliff:g id="number">%d</xliff:g> tentativo rimanente prima di dover contattare l\'operatore per sbloccare il dispositivo.</item>
+ <item quantity="other">Inserisci il PIN della SIM, hai ancora <xliff:g id="number">%d</xliff:g> tentativi rimanenti.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Errore: input non sufficientemente lungo</string>
+</resources>
diff --git a/packages/Keyguard/res/values-iw/cm_strings.xml b/packages/Keyguard/res/values-iw/cm_strings.xml
new file mode 100644
index 0000000..0cd676b
--- /dev/null
+++ b/packages/Keyguard/res/values-iw/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">כרטיס SIM נעול להתאמות</string>
+ <string name="lockscreen_sim_error_message_short">כרטיס שגוי.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">הזן את קוד ה-PIN של כרטיס ה-SIM, נותר לך ניסיון <xliff:g id="number">%d</xliff:g> לפני שתיאלץ לפנות לספק הסלולרי שלך על מנת לבטל את נעילת המכשיר.</item>
+ <item quantity="other">הזן את קוד ה-PIN של כרטיס ה-SIM, נותרו לך <xliff:g id="number">%d</xliff:g> ניסיונות.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">שגיאה: הקלט קצר יותר מהאורך המינימלי</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ja/cm_strings.xml b/packages/Keyguard/res/values-ja/cm_strings.xml
new file mode 100644
index 0000000..0088dfc
--- /dev/null
+++ b/packages/Keyguard/res/values-ja/cm_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIMはペルソロックされています</string>
+ <string name="lockscreen_sim_error_message_short">無効なカードです。</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="other">SIMのPINを入力してください、残り<xliff:g id="number">%d</xliff:g>回試行することができます。</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">エラー: 入力が最小長よりも短いです</string>
+</resources>
diff --git a/packages/Keyguard/res/values-kn-rIN/cm_strings.xml b/packages/Keyguard/res/values-kn-rIN/cm_strings.xml
new file mode 100644
index 0000000..fd17bce
--- /dev/null
+++ b/packages/Keyguard/res/values-kn-rIN/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">ಅಮಾನ್ಯ ಕಾರ್ಡ್.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ko/cm_strings.xml b/packages/Keyguard/res/values-ko/cm_strings.xml
new file mode 100644
index 0000000..4be11f7
--- /dev/null
+++ b/packages/Keyguard/res/values-ko/cm_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM이 Perso lock되어 있습니다.</string>
+ <string name="lockscreen_sim_error_message_short">올바르지 않은 카드입니다.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="other">SIM PIN을 입력하십시오. <xliff:g id="number">%d</xliff:g>회 후에는 이동통신사에 연락하여 기기를 잠금 해제해야 합니다.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">오류: 입력한 값이 최소 길이보다 짧음</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ku/cm_strings.xml b/packages/Keyguard/res/values-ku/cm_strings.xml
new file mode 100644
index 0000000..d5fed16
--- /dev/null
+++ b/packages/Keyguard/res/values-ku/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">کارته‌که‌ نادرووستە.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ku/strings.xml b/packages/Keyguard/res/values-ku/strings.xml
new file mode 100644
index 0000000..84be97e
--- /dev/null
+++ b/packages/Keyguard/res/values-ku/strings.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_password_enter_pin_code">PIN کۆد بنوسه‌</string>
+ <string name="keyguard_password_enter_puk_code">PUK ی سیمکارته‌که‌ و PIN ی نوێ بنوسه‌</string>
+ <string name="keyguard_password_enter_puk_prompt">کۆدی PUK ی سیمکارت</string>
+ <string name="keyguard_password_enter_pin_prompt">پین کۆدی نوێی سیمکارت</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">بیسووه‌ بۆ نوسینی تێپەڕەوشە</font></string>
+ <string name="keyguard_password_enter_password_code">تێپه‌ڕه‌وشه‌ بنوسه‌ بۆ کردنه‌وه‌</string>
+ <string name="keyguard_password_enter_pin_password_code">PIN بنوسه‌ بۆ کردنه‌وه‌</string>
+ <string name="keyguard_password_wrong_pin_code">پین کۆد هەڵە بوو.</string>
+ <string name="keyguard_charged">بارگاویی بوو</string>
+ <string name="keyguard_low_battery">بارگاویکه‌رەکەت ببەستەوە.</string>
+ <string name="keyguard_instructions_when_pattern_disabled">دەست بنێ بە پێڕستدا بۆ کردنه‌وه‌.</string>
+ <string name="keyguard_network_locked_message">تۆڕی نێت داخرا</string>
+ <string name="keyguard_missing_sim_message_short">سیمکارتی تێدا نییە</string>
+ <string name="keyguard_missing_sim_message" product="tablet">تابلێته‌که‌ سیمکارتی تێدا نییه‌.</string>
+ <string name="keyguard_missing_sim_message" product="default">ته‌له‌فۆنه‌که‌ سیمکارتی تێدا نییه‌.</string>
+ <string name="keyguard_missing_sim_instructions">سیمکارتێکی تێبکه‌.</string>
+ <string name="keyguard_missing_sim_instructions_long">سیمکارتی تێ نه‌کراوه‌ یان نایخوێنێته‌وه‌. سیمکارتێکی تێکه‌.</string>
+ <string name="keyguard_permanent_disabled_sim_message_short">سیمکارتەکە بەکارنایەت.</string>
+ <string name="keyguard_permanent_disabled_sim_instructions">سیمکارتەکەت بۆ هه‌میشه‌ لەکار خرا .\n
+ پەیوەندیی بکە بە دابینکه‌ری ڕاژه‌ی بێته‌له‌وه‌ بۆ سیمکارتێکی تر.</string>
+ <string name="keyguard_sim_locked_message">سیمکارتەکە داخرا.</string>
+ <string name="keyguard_sim_puk_locked_message">سیمکارتەکە به‌ شێوه‌ی PUK داخرا.</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message">کردنەوەی سیمکارت\u2026</string>
+ <string name="keyguard_accessibility_pattern_unlock">کردنه‌وه‌ بە کێشان.</string>
+ <string name="keyguard_accessibility_pin_unlock">کردنه‌وه‌ی پین.</string>
+ <string name="keyguard_accessibility_password_unlock">کردنه‌وه‌ی تێپه‌ڕه‌وشه‌.</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">ناوچەی خه‌تکێشان.</string>
+ <string name="keyguard_accessibility_slide_area">ناوچەی لادان.</string>
+ <string name="keyboardview_keycode_delete">سڕینه‌وه‌</string>
+ <string name="keyboardview_keycode_enter">دانان</string>
+ <string name="kg_forgot_pattern_button_text">بیرچونی خه‌تکێشان</string>
+ <string name="kg_wrong_pattern">خه‌تکێشان هه‌ڵه‌یه‌</string>
+ <string name="kg_wrong_password">تێپەڕەوشە هەڵەیه‌</string>
+ <string name="kg_wrong_pin">PIN هەڵەیە</string>
+ <string name="kg_too_many_failed_attempts_countdown">دووبارە هەوڵبدەرەوە له‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا.</string>
+ <string name="kg_pattern_instructions">خه‌ت بکێشه‌</string>
+ <string name="kg_sim_pin_instructions">دانانی PIN ی سیم</string>
+ <string name="kg_pin_instructions">دانانی PIN</string>
+ <string name="kg_password_instructions">دانانی تێپەڕەوشە</string>
+ <string name="kg_puk_enter_puk_hint">ئێستا سیمه‌که‌ ناکارایه‌. کۆدی PUK دابنێ بۆ به‌رده‌وامبوون. بۆ زانیاریی زیاتر په‌یوه‌ندیی بکه‌ به‌ کۆمپانیای دابینه‌که‌ره‌وه‌.</string>
+ <string name="kg_puk_enter_pin_hint">دانانی PIN کۆد بە ئارەزوی خۆت</string>
+ <string name="kg_enter_confirm_pin_hint">دڵنیاکردنەوەی PIN کۆد</string>
+ <string name="kg_sim_unlock_progress_dialog_message">کردنه‌وه‌ی سیمکارت\u2026</string>
+ <string name="kg_invalid_sim_pin_hint">PIN ێک بنوسه‌ له‌ 4 بۆ 8 ژماره‌ پێکهاتبێت.</string>
+ <string name="kg_invalid_sim_puk_hint">کۆدی PUK ده‌بێت 8 ژمارە یان زیاتر بێت.</string>
+ <string name="kg_invalid_puk">دوبارە کۆدی PUK لێدەرەوە. هه‌وڵی چه‌ندباره‌ سیمکارته‌که‌ت له‌کار ده‌خات.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">PIN کۆد هاوتا نییە</string>
+ <string name="kg_login_too_many_attempts">زۆر هه‌وڵی خه‌تکێشانت داوه‌</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">
+ بە هەڵە PIN ت نوسیوە <xliff:g id="number">%d</xliff:g> جار.
+ \n\nدوبارە هەوڵبدەرەوە له‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا.
+
+    </string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">
+ بەهەڵە تێپەڕە وشەت لێداوە <xliff:g id="number">%d</xliff:g> جار.
+ \n\nدوبارە هەوڵبدەرەوە له‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا.
+
+    </string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">
+ بە هەڵە خه‌تکێشانت لێداوه‌ <xliff:g id="number">%d</xliff:g> جار.
+ \n\nدووبارە هەوڵبدەره‌وه‌ له‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا.
+
+   
+</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">
+ به‌ هه‌ڵه‌ کردنەوەی خه‌تکێشانه‌که‌ت داوە <xliff:g id="number">%d</xliff:g> times جار.
+ پاش <xliff:g id="number">%d</xliff:g> هه‌وڵی سه‌رنه‌که‌وتووی زیاتر،
+ داوات لێ ده‌کرێت تابلێته‌که‌ت بکه‌یته‌وه‌ به‌ به‌کارهێنانی هه‌ژماری ئیمه‌یڵ.\n\n
+ جارێکی تر هه‌وڵ بده‌ره‌وه‌ له‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا.
+ </string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">
+ به‌ هه‌ڵه‌ کردنەوەی خه‌تکێشانه‌که‌ت لێداوە <xliff:g id="number">%d</xliff:g> times جار.
+ پاش <xliff:g id="number">%d</xliff:g> هه‌وڵی سه‌رنه‌که‌وتووی زیاتر،
+ داوات لێ ده‌کرێت ته‌له‌فۆنه‌که‌ بکه‌یته‌وه‌ به‌ به‌کارهێنانی هه‌ژماری ئیمه‌یڵ. \n\n
+ جارێکی تر هه‌وڵ بده‌ره‌وه‌ له‌ <xliff:g id="number">%d</xliff:g> چرکه‌دا.
+ </string>
+ <string name="kg_password_wrong_pin_code_pukked">PIN کۆد هه‌ڵه‌یه‌ پێویسته‌ ئێستا په‌یوه‌ندیی بکه‌یت به‌ کۆمپانیای دابینکه‌ره‌وه‌ بۆ کردنه‌وه‌ی ئامێره‌که‌ت.</string>
+ <string name="kg_password_wrong_puk_code_dead">سیمه‌که‌ له‌کار که‌وتووه‌. په‌یوه‌ندیی بکه‌ به‌ کۆمپانیای دابینکه‌ره‌وه‌.</string>
+ <string name="kg_password_pin_failed">کارپێکردنی PIN ی سیم شکستی هێنا!</string>
+ <string name="kg_password_puk_failed">کارپێکردنی PUK ی سیم شکستی هێنا!</string>
+ <string name="kg_pin_accepted">کۆدەکە وه‌رگیرا!</string>
+ <string name="keyguard_carrier_default">خزمەتگوزاریی به‌رده‌ست نییە.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-lb/cm_strings.xml b/packages/Keyguard/res/values-lb/cm_strings.xml
new file mode 100644
index 0000000..805aad0
--- /dev/null
+++ b/packages/Keyguard/res/values-lb/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Ongëlteg Kaart.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-lb/strings.xml b/packages/Keyguard/res/values-lb/strings.xml
new file mode 100644
index 0000000..f0cd53f
--- /dev/null
+++ b/packages/Keyguard/res/values-lb/strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">Tastespär</string>
+ <string name="keyguard_password_enter_pin_code">PIN-Code aginn</string>
+ <string name="keyguard_password_enter_puk_code">SIM-PUK an nei PIN aginn</string>
+ <string name="keyguard_password_enter_puk_prompt">SIM-PUK-Code</string>
+ <string name="keyguard_password_enter_pin_prompt">Neie SIM-PIN-Code</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">Dréck fir d\'Passwuert anzeginn</font></string>
+ <string name="keyguard_password_enter_password_code">Passwuert agi fir z\'entspären</string>
+ <string name="keyguard_password_enter_pin_password_code">PIN agi fir z\'entspären</string>
+ <string name="keyguard_password_wrong_pin_code">Falsche PIN-Code.</string>
+ <string name="keyguard_charged">Opgelueden</string>
+ <string name="keyguard_plugged_in">Gëtt opgelueden</string>
+ <string name="keyguard_low_battery">Connectéier däin Oplueder.</string>
+ <string name="keyguard_instructions_when_pattern_disabled">Menü drécke fir z\'entspären.</string>
+ <string name="keyguard_network_locked_message">Netzwierk gespaart</string>
+ <string name="keyguard_missing_sim_message_short">Keng SIM-Kaart</string>
+ <string name="keyguard_missing_sim_message" product="tablet">Keng SIM-Kaart am Tablet.</string>
+ <string name="keyguard_missing_sim_message" product="default">Keng SIM-Kaart am Telefon.</string>
+ <string name="keyguard_missing_sim_instructions">SIM-Kaart asetzen.</string>
+ <string name="keyguard_missing_sim_instructions_long">D\'SIM-Kaart feelt oder ass net liesbar. Setz eng SIM-Kaart an.</string>
+ <string name="keyguard_permanent_disabled_sim_message_short">Onbenotzbar SIM-Kaart.</string>
+ <string name="keyguard_permanent_disabled_sim_instructions">Deng SIM-Kaart gouf permanent ausgeschalt.\n
+Kontaktéier däi Provider fir eng aner SIM-Kaart ze kréien.</string>
+ <string name="keyguard_sim_locked_message">D\'SIM-Kaart ass gespaart.</string>
+ <string name="keyguard_sim_puk_locked_message">D\'SIM-Kaart ass PUK-gespaart.</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message">D\'SIM-Kaart gëtt entspaart\u2026</string>
+ <string name="keyguard_accessibility_pattern_unlock">Entspäre mat Muster.</string>
+ <string name="keyguard_accessibility_pin_unlock">Entspäre mat PIN.</string>
+ <string name="keyguard_accessibility_password_unlock">Entspäre mat Passwuert.</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">Musterberäich.</string>
+ <string name="keyguard_accessibility_slide_area">Beräich fir Fangerbeweegung.</string>
+ <string name="keyguard_accessibility_pin_area">PIN-Beräich</string>
+ <string name="keyguard_accessibility_sim_pin_area">SIM-PIN-Beräich</string>
+ <string name="keyguard_accessibility_sim_puk_area">SIM-PUK-Beräich</string>
+ <string name="keyguard_accessibility_next_alarm">Nächste Wecker gesat fir <xliff:g id="alarm" example="Fri 8:30 AM">%1$s</xliff:g></string>
+ <string name="keyboardview_keycode_delete">Läschen</string>
+ <string name="keyboardview_keycode_enter">Enter</string>
+ <string name="kg_forgot_pattern_button_text">Muster vergiess</string>
+ <string name="kg_wrong_pattern">Falscht Muster</string>
+ <string name="kg_wrong_password">Falscht Passwuert</string>
+ <string name="kg_wrong_pin">Falsche PIN</string>
+ <string name="kg_too_many_failed_attempts_countdown">Probéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_pattern_instructions">Mol däi Muster</string>
+ <string name="kg_sim_pin_instructions">SIM-PIN aginn</string>
+ <string name="kg_sim_pin_instructions_multi">SIM-PIN fir \"<xliff:g id="carrier" example="CARD 1">%1$s</xliff:g>\" aginn</string>
+ <string name="kg_pin_instructions">PIN aginn</string>
+ <string name="kg_password_instructions">Passwuert aginn</string>
+ <string name="kg_puk_enter_puk_hint">D\'SIM ass elo desaktivéiert. Gëff e PUK-Code a fir weiderzemaachen. Kontaktéier däi Provider fir Detailer.</string>
+ <string name="kg_puk_enter_puk_hint_multi">D\'SIM \"<xliff:g id="carrier" example="CARD 1">%1$s</xliff:g>\" ass elo desaktivéiert. Gëff de PUK-Code an, fir weiderzemaachen. Kontaktéier däi Provider fir méi Detailer.</string>
+ <string name="kg_puk_enter_pin_hint">Gëff de gewënschte PIN-Code an</string>
+ <string name="kg_enter_confirm_pin_hint">Bestäteg de gewënschte PIN-Code</string>
+ <string name="kg_sim_unlock_progress_dialog_message">D\'SIM-Kaart gëtt entspaart\u2026</string>
+ <string name="kg_invalid_sim_pin_hint">Gëff e PIN an, deen tëscht 4 an 8 Zifferen huet.</string>
+ <string name="kg_invalid_sim_puk_hint">De PUK-Code misst 8 oder méi Zifferen hunn.</string>
+ <string name="kg_invalid_puk">Gëff de korrekte PUK-Code nees an. Bei widderhuelende Versich gëtt d\'SIM permanent desaktivéiert.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">D\'PIN-Codë stëmmen net iwwereneen</string>
+ <string name="kg_login_too_many_attempts">Ze vill Musterversich</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">Du hues däi PIN <xliff:g id="number">%d</xliff:g>-mol falsch aginn.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">Du hues däi Passwuert <xliff:g id="number">%d</xliff:g>-mol falsch aginn.\n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">
+ Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gemoolt.
+ \n\nProbéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.
+    </string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Date gi verluer.</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Telefon op d\'Wierksastellungen zréckgesat an all d\'Date gi verluer.</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht, den Tablet z\'entspären. Dësen Tablet gëtt zréckgesat, wat all d\'Date läscht.</string>
+ <string name="kg_failed_attempts_now_wiping" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht, den Telefon z\'entspären. Dësen Telefon gëtt zréckgesat, wat all d\'Date läscht.</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt dëse Benotzer a seng Benotzerdate geläscht.</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt dëse Benotzer a seng Benotzerdate geläscht.</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht, den Tablet z\'entspären. Dëse Benotzer a seng Date gi geläscht.</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht, den Telefon z\'entspären. Dëse Benotzer a seng Date gi geläscht.</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Aarbechtsprofil a seng Profildate geläscht.</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëtt den Aarbechtsprofil a seng Profildate geläscht.</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Tablet z\'entspären. Den Aarbechtsprofil a seng Profildate gi geläscht.</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default">Du hues <xliff:g id="number">%d</xliff:g>-mol ouni Erfolleg versicht den Telefon z\'entspären. Den Aarbechtsprofil a seng Profildate gi geläscht.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gemoolt. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëss du gefrot däin Tablet duerch en E-Mail-Kont z\'entspären. Probéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">Du hues däin Entspärmuster <xliff:g id="number">%d</xliff:g>-mol falsch gemoolt. No <xliff:g id="number">%d</xliff:g> weidere feelgeschloene Versich gëss du gefrot däin Telefon duerch en E-Mail-Kont z\'entspären. Probéier nees a(n) <xliff:g id="number">%d</xliff:g> Sekonnen.</string>
+ <string name="kg_password_wrong_pin_code_pukked">Inkorrekte SIM-PIN-Code. Du muss elo däi Provider kontaktéiere fir däin Apparat z\'entspären.</string>
+ <string name="kg_password_wrong_puk_code_dead">D\'SIM ass onbrauchbar. Kontaktéier däi Provider.</string>
+ <string name="kg_password_pin_failed">SIM-PIN-Operatioun feelgeschloen!</string>
+ <string name="kg_password_puk_failed">SIM-PUK-Operatioun feelgeschloen!</string>
+ <string name="kg_pin_accepted">Code acceptéiert!</string>
+ <string name="keyguard_carrier_default">Kee Service.</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">Knäppche fir d\'Method fir anzeginn ze wiesselen.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-lt/cm_strings.xml b/packages/Keyguard/res/values-lt/cm_strings.xml
new file mode 100644
index 0000000..9f0cd5e
--- /dev/null
+++ b/packages/Keyguard/res/values-lt/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Neteisinga kortelė.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-lv/cm_strings.xml b/packages/Keyguard/res/values-lv/cm_strings.xml
new file mode 100644
index 0000000..f2b5d62
--- /dev/null
+++ b/packages/Keyguard/res/values-lv/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM ir personīgi bloķēta</string>
+ <string name="lockscreen_sim_error_message_short">Nepareiza karte.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="zero">Ievadiet SIM kartes PIN kodu, jums ir atlicis <xliff:g id="number">%d </xliff:g> mēģinājums.</item>
+ <item quantity="one">Ievadiet SIM kartes PIN kodu, jums ir atlicis <xliff:g id="number">%d </xliff:g> mēģinājums.</item>
+ <item quantity="other">Ievadiet SIM kartes PIN kodu, jums ir atlikuši <xliff:g id="number">%d </xliff:g> mēģinājumi.</item>
+ </plurals>
+</resources>
diff --git a/packages/Keyguard/res/values-nb/cm_strings.xml b/packages/Keyguard/res/values-nb/cm_strings.xml
new file mode 100644
index 0000000..bdbebac
--- /dev/null
+++ b/packages/Keyguard/res/values-nb/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM er Person låst</string>
+ <string name="lockscreen_sim_error_message_short">Ugyldig kort.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Angi SIM PIN, du har <xliff:g id="number">%d</xliff:g> forsøk igjen før må du kontakte operatøren for å låse opp enheten.</item>
+ <item quantity="other">Angi SIM PIN, du har <xliff:g id="number">%d</xliff:g> gjenstående forsøk.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Feil: Input kortere enn minimumslengden</string>
+</resources>
diff --git a/packages/Keyguard/res/values-nl/cm_strings.xml b/packages/Keyguard/res/values-nl/cm_strings.xml
new file mode 100644
index 0000000..a2266f9
--- /dev/null
+++ b/packages/Keyguard/res/values-nl/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">Simkaart is Perso-vergrendeld</string>
+ <string name="lockscreen_sim_error_message_short">Ongeldige simkaart.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">SIM-PIN invoeren, u heeft <xliff:g id="number">%d</xliff:g> resterende pogingen voordat u contact moet opnemen met uw provider om uw apparaat te ontgrendelen.</item>
+ <item quantity="other">SIM-PIN invoeren, u heeft <xliff:g id="number">%d</xliff:g> resterende pogingen.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Fout: Invoer is korter dan minimumlengte</string>
+</resources>
diff --git a/packages/Keyguard/res/values-pl/cm_strings.xml b/packages/Keyguard/res/values-pl/cm_strings.xml
new file mode 100644
index 0000000..1a2563c
--- /dev/null
+++ b/packages/Keyguard/res/values-pl/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">Blokada Perso karty SIM/RUIM</string>
+ <string name="lockscreen_sim_error_message_short">Nieprawidłowa karta.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Wprowadź PIN karty SIM, masz <xliff:g id="number">%d</xliff:g> pozostałą próbę zanim będziesz musiał skontaktować się z operatorem, by odblokować urządzenie.</item>
+ <item quantity="few">Wprowadź PIN karty SIM, masz <xliff:g id="number">%d</xliff:g> pozostałe próby.</item>
+ <item quantity="other">Wprowadź PIN karty SIM, masz <xliff:g id="number">%d</xliff:g> pozostałych prób.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Błąd: Podany kod jest za krótki</string>
+</resources>
diff --git a/packages/Keyguard/res/values-pt-rBR/cm_strings.xml b/packages/Keyguard/res/values-pt-rBR/cm_strings.xml
new file mode 100644
index 0000000..5ebd5be
--- /dev/null
+++ b/packages/Keyguard/res/values-pt-rBR/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">O cartão SIM está bloqueado</string>
+ <string name="lockscreen_sim_error_message_short">Cartão SIM inválido.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Digite o PIN do cartão SIM, você tem <xliff:g id="number">%d</xliff:g> tentativa restante antes de precisar contatar sua operadora para desbloquear seu aparelho.</item>
+ <item quantity="other">Digite o PIN do cartão SIM, você tem <xliff:g id="number">%d</xliff:g> tentativas restantes.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Erro: Entrada mais curta do que o comprimento mínimo</string>
+</resources>
diff --git a/packages/Keyguard/res/values-pt-rPT/cm_strings.xml b/packages/Keyguard/res/values-pt-rPT/cm_strings.xml
new file mode 100644
index 0000000..bfa6b3a
--- /dev/null
+++ b/packages/Keyguard/res/values-pt-rPT/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">O cartão SIM está bloqueado</string>
+ <string name="lockscreen_sim_error_message_short">Cartão inválido.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Digite o código PIN do cartão SIM. Tem mais <xliff:g id="number">%d</xliff:g> tentativa antes de ter de contactar a sua operadora para desbloquear o dispositivo.</item>
+ <item quantity="other">Digite o código PIN do cartão SIM. Tem mais <xliff:g id="number">%d</xliff:g> tentativas.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Erro: o tamanho é menor que o requerido</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ro/cm_strings.xml b/packages/Keyguard/res/values-ro/cm_strings.xml
new file mode 100644
index 0000000..5f9203b
--- /dev/null
+++ b/packages/Keyguard/res/values-ro/cm_strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Cartelă SIM incorectă.</string>
+ <string name="kg_invalid_sim_length">Eroare: Introducere mai scurtă decât lungimea minimă</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ru/cm_strings.xml b/packages/Keyguard/res/values-ru/cm_strings.xml
new file mode 100644
index 0000000..4d64761
--- /dev/null
+++ b/packages/Keyguard/res/values-ru/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM-карта заблокирована оператором</string>
+ <string name="lockscreen_sim_error_message_short">Ошибка карты.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Введите PIN-код. У вас осталась <xliff:g id="number">%d</xliff:g> попытка перед тем, как вам придется обратиться к оператору для разблокировки.</item>
+ <item quantity="few">Введите PIN-код. У вас осталось <xliff:g id="number">%d</xliff:g> попытки.</item>
+ <item quantity="other">Введите PIN-код. У вас осталось <xliff:g id="number">%d</xliff:g> попыток.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Ошибка: введено меньше минимальной длины</string>
+</resources>
diff --git a/packages/Keyguard/res/values-sk/cm_strings.xml b/packages/Keyguard/res/values-sk/cm_strings.xml
new file mode 100644
index 0000000..8e5df9a
--- /dev/null
+++ b/packages/Keyguard/res/values-sk/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Neplatná karta.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-sl/cm_strings.xml b/packages/Keyguard/res/values-sl/cm_strings.xml
new file mode 100644
index 0000000..84c794e
--- /dev/null
+++ b/packages/Keyguard/res/values-sl/cm_strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">Kartica SIM je zaklenjena v načinu Perso</string>
+ <string name="lockscreen_sim_error_message_short">Neveljavna kartica.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Vnesite PIN kartice SIM, imate še <xliff:g id="number">%d</xliff:g> preostali poskus, preden boste morali stopiti v stik s svojim ponudnikom, da vam odklene napravo.</item>
+ <item quantity="two">Vnesite PIN kartice SIM, imate še <xliff:g id="number">%d</xliff:g> preostala poskusa.</item>
+ <item quantity="few">Vnesite PIN kartice SIM, imate še <xliff:g id="number">%d</xliff:g> preostale poskuse.</item>
+ <item quantity="other">Vnesite PIN kartice SIM, imate še <xliff:g id="number">%d</xliff:g> preostalih poskusov.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Napaka: Vnos je krajši od minimalne zahtevane dolžine</string>
+</resources>
diff --git a/packages/Keyguard/res/values-sr/cm_strings.xml b/packages/Keyguard/res/values-sr/cm_strings.xml
new file mode 100644
index 0000000..f770859
--- /dev/null
+++ b/packages/Keyguard/res/values-sr/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM картица је лично закључана</string>
+ <string name="lockscreen_sim_error_message_short">Неважећа картица.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Унеси SIM PIN, имаш <xliff:g id="number">%d</xliff:g> преостали покушај пре него што мораш контактирати свог оператора да откључаш уређај.</item>
+ <item quantity="few">Унеси SIM PIN, имаш <xliff:g id="number">%d</xliff:g> преостала покушаја пре него што мораш контактирати свог оператора да откључаш уређај.</item>
+ <item quantity="other">Унеси SIM PIN, имаш <xliff:g id="number">%d</xliff:g> преостала покушаја пре него што мораш контактирати свог оператора да откључаш уређај.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Грешка: Унос је краћи од минималне дужине</string>
+</resources>
diff --git a/packages/Keyguard/res/values-sv/cm_strings.xml b/packages/Keyguard/res/values-sv/cm_strings.xml
new file mode 100644
index 0000000..2a225d4
--- /dev/null
+++ b/packages/Keyguard/res/values-sv/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM-kortet är personligt låst</string>
+ <string name="lockscreen_sim_error_message_short">Ogiltigt SIM.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Ange SIM-kortets PIN-kod, du har <xliff:g id="number">%d</xliff:g> försök kvar innan du behöver kontakta din operatör för att låsa upp din enhet.</item>
+ <item quantity="other">Ange SIM-kortets PIN-kod, du har <xliff:g id="number">%d</xliff:g> försök kvar innan du behöver kontakta din operatör för att låsa upp din enhet.</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">Fel: Input kortare än minsta längd</string>
+</resources>
diff --git a/packages/Keyguard/res/values-th/cm_strings.xml b/packages/Keyguard/res/values-th/cm_strings.xml
new file mode 100644
index 0000000..ce76f24
--- /dev/null
+++ b/packages/Keyguard/res/values-th/cm_strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">ซิมการ์ดถูกเปโซล็อค</string>
+ <string name="lockscreen_sim_error_message_short">ซิมการ์ดไม่ถูกต้อง</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="other">ใส่รหัสซิมการ์ด สามารถใส่รหัสได้อีก <xliff:g id="number">%d</xliff:g> ก่อนจะต้องติดต่อติดต่อผู้ให้บริการเพื่อปลดล็อคอุปกรณ์ของคุณ</item>
+ </plurals>
+</resources>
diff --git a/packages/Keyguard/res/values-tr/cm_strings.xml b/packages/Keyguard/res/values-tr/cm_strings.xml
new file mode 100644
index 0000000..919607e
--- /dev/null
+++ b/packages/Keyguard/res/values-tr/cm_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM Özel kilitli</string>
+ <string name="lockscreen_sim_error_message_short">Geçersiz kart.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">SIM PIN kodunuzu girin, <xliff:g id="number">%d</xliff:g> deneme hakkınız kaldı, yoksa cihazınızın kilidini açabilmek için operatörünüz ile iletişim kurmak zorunda kalacaksınız.</item>
+ <item quantity="other">SIM PIN kodunuzu girin, <xliff:g id="number">%d</xliff:g> deneme hakkınız kaldı.</item>
+ </plurals>
+</resources>
diff --git a/packages/Keyguard/res/values-ug/cm_strings.xml b/packages/Keyguard/res/values-ug/cm_strings.xml
new file mode 100644
index 0000000..ce1bb8b
--- /dev/null
+++ b/packages/Keyguard/res/values-ug/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">ئىناۋەتسىز كارتا.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-ug/strings.xml b/packages/Keyguard/res/values-ug/strings.xml
new file mode 100644
index 0000000..6c45a13
--- /dev/null
+++ b/packages/Keyguard/res/values-ug/strings.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_password_enter_pin_code">PIN كودىنى كىرگۈزۈڭ</string>
+ <string name="keyguard_password_enter_puk_code">SIM PUK ۋە يېڭى PIN كودىنى كىرگۈزۈڭ</string>
+ <string name="keyguard_password_enter_puk_prompt">SIM PUK كودى</string>
+ <string name="keyguard_password_enter_pin_prompt">يېڭى SIM كارتا PIN كودى</string>
+ <string name="keyguard_password_entry_touch_hint"><font size="17">\"بۇ جاينى چېكىپ ئىم كىرگۈزۈڭ\"</font></string>
+ <string name="keyguard_password_enter_password_code">قۇلۇپ ئېچىش ئۈچۈن ئىم كىرگۈزۈڭ</string>
+ <string name="keyguard_password_enter_pin_password_code">PIN كىرگۈزۈپ قۇلۇپ ئېچىڭ</string>
+ <string name="keyguard_password_wrong_pin_code">PIN كودى خاتا.</string>
+ <string name="keyguard_charged">توكلاندى</string>
+ <string name="keyguard_instructions_when_pattern_disabled">Menu نى بېسىپ قۇلۇپنى ئېچىڭ.</string>
+ <string name="keyguard_network_locked_message">تور قۇلۇپلانغان</string>
+ <string name="keyguard_missing_sim_message_short">SIM كارتا يوق</string>
+ <string name="keyguard_missing_sim_message" product="tablet">تاختا كومپيۇتېردا SIM كارتا يوق.</string>
+ <string name="keyguard_missing_sim_message" product="default">تېلېفوندا SIM كارتا يوق.</string>
+ <string name="keyguard_missing_sim_instructions">SIM كارتا قىستۇرۇڭ.</string>
+ <string name="keyguard_missing_sim_instructions_long">SIM كارتا يوقالغان ياكى ئوقۇغىلى بولمايدۇ. SIM كارتا قىستۇرۇڭ.</string>
+ <string name="keyguard_permanent_disabled_sim_message_short">SIM كارتىنى ئىشلەتكىلى بولمايدۇ.</string>
+ <string name="keyguard_permanent_disabled_sim_instructions">سىزنىڭ SIM كارتىڭىز مەڭگۈلۈك توختىتىلدى.\nسىمسىز تور مۇلازىمىتى تەمىنلىگۈچىڭىز بىلەن ئالاقە قىلىپ، يېڭىدىن بىر SIM كارتىغا ئېرىشىڭ.</string>
+ <string name="keyguard_sim_locked_message">SIM كارتا قۇلۇپلانغان.</string>
+ <string name="keyguard_sim_puk_locked_message">SIM كارتا PUK نۇمۇر ئارقىلىق قۇلۇپلانغان.</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message">SIM كارتا قۇلۇپىنى ئېچىۋاتىدۇ…</string>
+ <string name="keyguard_accessibility_pattern_unlock">ئەدىزەدە قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_pin_unlock">بۇ Pin دا قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_password_unlock">ئىمدا قۇلۇپ ئاچىدۇ.</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">ئەندىزە دائىرىسى.</string>
+ <string name="keyguard_accessibility_slide_area">سۈرۈش دائىرىسى</string>
+ <string name="keyboardview_keycode_delete">ئۆچۈر</string>
+ <string name="kg_forgot_pattern_button_text">ئەندىزە ئۇنتۇلغان</string>
+ <string name="kg_wrong_pattern">ئەندىزە خاتا</string>
+ <string name="kg_wrong_password">ئىم خاتا</string>
+ <string name="kg_wrong_pin">بۇ PIN خاتا</string>
+ <string name="kg_too_many_failed_attempts_countdown"><xliff:g id="NUMBER">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_pattern_instructions">قۇلۇپ ئاچىدىغان ئەندىزە سىزىڭ</string>
+ <string name="kg_sim_pin_instructions">كىرگۈزىدىغىنىڭىز SIM PIN</string>
+ <string name="kg_pin_instructions">كىرگۈزىدىغىنىڭىز PIN</string>
+ <string name="kg_password_instructions">ئىم كىرگۈزۈڭ</string>
+ <string name="kg_puk_enter_puk_hint">بۇ SIM كارتا توختىتىلغان. PUK كودى كىرگۈزۈلگەندىلا ئاندىن ئىشلەتكىلى بولىدۇ. مۇناسىۋەتلىك تەپسىلاتلار ئۈچۈن مۇلازىمەت تەمىنلىگۈچىڭىز بىلەن ئالاقە قىلىڭ.</string>
+ <string name="kg_puk_enter_pin_hint">لازىملىق PIN كودىنى كىرگۈزۈڭ</string>
+ <string name="kg_enter_confirm_pin_hint">لازىملىق PIN كودىنى جەزملەڭ</string>
+ <string name="kg_sim_unlock_progress_dialog_message">SIM كارتا قۇلۇپىنى ئېچىۋاتىدۇ…</string>
+ <string name="kg_invalid_sim_pin_hint">4-8 خانىلىق PIN نى كىرگۈزۈڭ.</string>
+ <string name="kg_invalid_sim_puk_hint">بۇ PUK كودىدا ئاز دېگەندە 8 ياكى ئۇنىڭدىن كۆپ سان بولىدۇ.</string>
+ <string name="kg_invalid_puk">توغرا PUK كودىنى قايتا كىرگۈزۈڭ. ئەگەر خاتا كىرگۈزۈشنىڭ قېتىم سانى بەك كۆپ بولۇپ كەتسە SIM كارتا مەڭگۈلۈك توختىتىلىدۇ.</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default">بۇ PIN كودى ماسلاشمىدى</string>
+ <string name="kg_login_too_many_attempts">ئەندىزىسىنى سىناش قېتىم سانى بەك كۆپ بولۇپ كەتتى</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message">سىز PIN نى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا كىرگۈزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_too_many_failed_password_attempts_dialog_message">سىز قۇلۇپ ئېچىش ئىمنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا كىرگۈزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز.\n\n <xliff:g id="NUMBER_1">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما تورخەت ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ.\n\nيەنە <xliff:g id="NUMBER_2">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default">سىز قۇلۇپ ئېچىش ئەندىزىسىنى <xliff:g id="NUMBER_0">%d</xliff:g> قېتىم خاتا سىزدىڭىز. ئەگەر <xliff:g id="NUMBER_1">%d</xliff:g> قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما تورخەت ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تېلېفون قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ.\n\nيەنە <xliff:g id="NUMBER_2">%d</xliff:g> سېكۇنتتىن كېيىن قايتا سىناڭ.</string>
+ <string name="kg_password_wrong_pin_code_pukked">SIM كارتا PIN كودى توغرا ئەمەس؛ ھازىر مۇلازىمەت سودىگىرىڭىز بىلەن ئالاقە قىلىپ ئۈسكۈنىڭىزنىڭ قۇلۇپىنى ئېچىڭ.</string>
+ <string name="kg_password_wrong_puk_code_dead">SIM كارتىنى ئىشلەتكىلى بولمايدۇ. مۇلازىمەت سودىگىرىڭىز بىلەن ئالاقە قىلىڭ.</string>
+ <string name="kg_password_pin_failed">SIM كارتا PIN مەشغۇلاتى مەغلۇپ بولدى!</string>
+ <string name="kg_password_puk_failed">SIM كارتا PUK مەشغۇلاتى مەغلۇپ بولدى!</string>
+ <string name="kg_pin_accepted">كود توغرا</string>
+ <string name="keyguard_carrier_default">مۇلازىمەت يوق.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-uk/cm_strings.xml b/packages/Keyguard/res/values-uk/cm_strings.xml
new file mode 100644
index 0000000..5c1883b
--- /dev/null
+++ b/packages/Keyguard/res/values-uk/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM-карта заблокована оператором</string>
+ <string name="lockscreen_sim_error_message_short">Невірна картка.</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Введіть PIN-код. У вас залишилася <xliff:g id="number">%d</xliff:g> спроба перед тим, як вам доведеться звернутися до оператора для розблокування.</item>
+ <item quantity="few">Введіть PIN-код. У вас залишилася <xliff:g id="number">%d</xliff:g> спроби перед тим, як вам доведеться звернутися до оператора для розблокування.</item>
+ <item quantity="other">Введіть PIN-код. У вас залишилася <xliff:g id="number">%d</xliff:g> спроб перед тим, як вам доведеться звернутися до оператора для розблокування.</item>
+ </plurals>
+</resources>
diff --git a/packages/Keyguard/res/values-vi/cm_strings.xml b/packages/Keyguard/res/values-vi/cm_strings.xml
new file mode 100644
index 0000000..12d4975
--- /dev/null
+++ b/packages/Keyguard/res/values-vi/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">Thẻ sim không hợp lệ.</string>
+</resources>
diff --git a/packages/Keyguard/res/values-zh-rCN/cm_strings.xml b/packages/Keyguard/res/values-zh-rCN/cm_strings.xml
new file mode 100644
index 0000000..56f8e18
--- /dev/null
+++ b/packages/Keyguard/res/values-zh-rCN/cm_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM 卡已被锁定</string>
+ <string name="lockscreen_sim_error_message_short">无效的 SIM 卡。</string>
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="other">输入 SIM 卡 PIN。您还有 <xliff:g id="number">%d</xliff:g> 次尝试机会;若超出此次数,则必须联系运营商以解锁 SIM 卡。</item>
+ </plurals>
+ <string name="kg_invalid_sim_length">错误:输入长度小于最小长度</string>
+</resources>
diff --git a/packages/Keyguard/res/values-zh-rHK/cm_strings.xml b/packages/Keyguard/res/values-zh-rHK/cm_strings.xml
new file mode 100644
index 0000000..765485f
--- /dev/null
+++ b/packages/Keyguard/res/values-zh-rHK/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lockscreen_sim_error_message_short">SIM 卡無效。</string>
+</resources>
diff --git a/packages/Keyguard/res/values-zh-rTW/cm_strings.xml b/packages/Keyguard/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 0000000..db6ee22
--- /dev/null
+++ b/packages/Keyguard/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keyguard_perso_locked_message">SIM/RUIM 卡已被鎖定</string>
+ <string name="lockscreen_sim_error_message_short">無效的 SIM 卡。</string>
+ <string name="kg_invalid_sim_length">錯誤:輸入少於最小長度</string>
+</resources>
diff --git a/packages/Keyguard/res/values/cm_colors.xml b/packages/Keyguard/res/values/cm_colors.xml
new file mode 100644
index 0000000..ffdc532
--- /dev/null
+++ b/packages/Keyguard/res/values/cm_colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<resources>
+
+ <color name="keyguard_sim_view_divider">#28FFFFFF</color>
+</resources>
diff --git a/packages/Keyguard/res/values/cm_strings.xml b/packages/Keyguard/res/values/cm_strings.xml
new file mode 100644
index 0000000..3276211
--- /dev/null
+++ b/packages/Keyguard/res/values/cm_strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- When the user inserts a sim card with some personalization enabled -->
+ <string name="keyguard_perso_locked_message">SIM card is Perso locked</string>
+
+ <!-- Shown in the lock screen when there is SIM card IO error. -->
+ <string name="lockscreen_sim_error_message_short">Invalid card.</string>
+
+ <!-- Instructions telling the user remaining times when enter SIM PIN view. -->
+ <plurals name="kg_password_default_pin_message">
+ <item quantity="one">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item>
+ <item quantity="other">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item>
+ </plurals>
+
+ <!-- Shown in the KeyguardSimPinView when entry length is too short. -->
+ <string name="kg_invalid_sim_length">Error: Input shorter than minimum length</string>
+</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
index 159ac4c..8dd56fa 100644
--- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java
+++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
@@ -39,12 +39,14 @@ import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.WirelessUtils;
+import android.telephony.TelephonyManager;
public class CarrierText extends TextView {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "CarrierText";
private static CharSequence mSeparator;
+ private static CharSequence mSubSeparator;
private final boolean mIsEmergencyCallCapable;
@@ -52,6 +54,8 @@ public class CarrierText extends TextView {
private WifiManager mWifiManager;
+ private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
+
private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onRefreshCarrierInfo() {
@@ -65,6 +69,22 @@ public class CarrierText extends TextView {
public void onStartedWakingUp() {
setSelected(true);
};
+
+ public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
+ if (slotId < 0) {
+ Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId);
+ return;
+ }
+
+ Log.d(TAG,"onSimStateChanged: " + getStatusForIccState(simState));
+ if (getStatusForIccState(simState) == StatusMode.SimIoError) {
+ mSimErrorState[slotId] = true;
+ updateCarrierText();
+ } else if (mSimErrorState[slotId]) {
+ mSimErrorState[slotId] = false;
+ updateCarrierText();
+ }
+ };
};
/**
* The status of this lock screen. Primarily used for widgets on LockScreen.
@@ -77,7 +97,8 @@ public class CarrierText extends TextView {
SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
SimLocked, // SIM card is currently locked
SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
- SimNotReady; // SIM is not ready yet. May never be on devices w/o a SIM.
+ SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
+ SimIoError; //The sim card is faulty
}
public CarrierText(Context context) {
@@ -101,6 +122,35 @@ public class CarrierText extends TextView {
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
+ /**
+ * Checks if there are faulty cards. Adds the text depending on the slot of the card
+ * @param text: current carrier text based on the sim state
+ * @param noSims: whether a valid sim card is inserted
+ * @return text
+ */
+ private CharSequence updateCarrierTextWithSimIoError(CharSequence text, boolean noSims) {
+ final CharSequence carrier = "";
+ CharSequence carrierTextForSimState = getCarrierTextForSimState(
+ IccCardConstants.State.CARD_IO_ERROR, carrier);
+ for (int index = 0; index < mSimErrorState.length; index++) {
+ if (mSimErrorState[index]) {
+ // In the case when no sim cards are detected but a faulty card is inserted
+ // overwrite the text and only show "Invalid card"
+ if (noSims) {
+ return concatenate(carrierTextForSimState,
+ getContext().getText(com.android.internal.R.string.emergency_calls_only));
+ } else if (index == 0) {
+ // prepend "Invalid card" when faulty card is inserted in slot 0
+ text = concatenate(carrierTextForSimState, text);
+ } else {
+ // concatenate "Invalid card" when faulty card is inserted in slot 1
+ text = concatenate(text, carrierTextForSimState);
+ }
+ }
+ }
+ return text;
+ }
+
protected void updateCarrierText() {
boolean allSimsMissing = true;
boolean anySimReadyAndInService = false;
@@ -119,7 +169,7 @@ public class CarrierText extends TextView {
}
if (carrierTextForSimState != null) {
allSimsMissing = false;
- displayText = concatenate(displayText, carrierTextForSimState);
+ displayText = concatenate(displayText, carrierTextForSimState, mSubSeparator);
}
if (simState == IccCardConstants.State.READY) {
ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
@@ -179,6 +229,7 @@ public class CarrierText extends TextView {
}
}
+ displayText = updateCarrierTextWithSimIoError(displayText, allSimsMissing);
// APM (airplane mode) != no carrier state. There are carrier services
// (e.g. WFC = Wi-Fi calling) which may operate in APM.
if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
@@ -192,6 +243,8 @@ public class CarrierText extends TextView {
super.onFinishInflate();
mSeparator = getResources().getString(
com.android.internal.R.string.kg_text_message_separator);
+ mSubSeparator = getResources().getString(
+ com.android.internal.R.string.kg_sub_separator);
boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
setSelected(shouldMarquee); // Allow marquee to work.
}
@@ -243,7 +296,7 @@ public class CarrierText extends TextView {
case NetworkLocked:
carrierText = makeCarrierStringOnEmergencyCapable(
- mContext.getText(R.string.keyguard_network_locked_message), text);
+ getContext().getText(R.string.keyguard_perso_locked_message), text);
break;
case SimMissing:
@@ -270,6 +323,11 @@ public class CarrierText extends TextView {
getContext().getText(R.string.keyguard_sim_puk_locked_message),
text);
break;
+ case SimIoError:
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ getContext().getText(R.string.lockscreen_sim_error_message_short),
+ text);
+ break;
}
return carrierText;
@@ -306,7 +364,7 @@ public class CarrierText extends TextView {
case ABSENT:
return StatusMode.SimMissing;
case NETWORK_LOCKED:
- return StatusMode.SimMissingLocked;
+ return StatusMode.NetworkLocked;
case NOT_READY:
return StatusMode.SimNotReady;
case PIN_REQUIRED:
@@ -319,15 +377,22 @@ public class CarrierText extends TextView {
return StatusMode.SimPermDisabled;
case UNKNOWN:
return StatusMode.SimMissing;
+ case CARD_IO_ERROR:
+ return StatusMode.SimIoError;
}
return StatusMode.SimMissing;
}
private static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
+ return concatenate(plmn, spn, mSeparator);
+ }
+
+ private static CharSequence concatenate(CharSequence plmn, CharSequence spn,
+ CharSequence separator) {
final boolean plmnValid = !TextUtils.isEmpty(plmn);
final boolean spnValid = !TextUtils.isEmpty(spn);
if (plmnValid && spnValid) {
- return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString();
+ return new StringBuilder().append(plmn).append(separator).append(spn).toString();
} else if (plmnValid) {
return plmn;
} else if (spnValid) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
index 4abb795..b909a60 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
@@ -19,16 +19,25 @@ package com.android.keyguard;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.RenderNode;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
+import android.widget.LinearLayout;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
+import cyanogenmod.providers.CMSettings;
+
/**
* Displays a PIN pad for unlocking.
*/
@@ -45,6 +54,8 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
private int mDisappearYTranslation;
private View[][] mViews;
+ private static List<Integer> sNumbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
+
public KeyguardPINView(Context context) {
this(context, null);
}
@@ -102,6 +113,33 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
new View[]{
null, mEcaView, null
}};
+
+ boolean scramblePin = (CMSettings.System.getInt(getContext().getContentResolver(),
+ CMSettings.System.LOCKSCREEN_PIN_SCRAMBLE_LAYOUT, 0) == 1);
+
+ if (scramblePin) {
+ Collections.shuffle(sNumbers);
+ // get all children who are NumPadKey's
+ LinearLayout container = (LinearLayout) findViewById(R.id.container);
+ List<NumPadKey> views = new ArrayList<NumPadKey>();
+ for (int i = 0; i < container.getChildCount(); i++) {
+ if (container.getChildAt(i) instanceof LinearLayout) {
+ LinearLayout nestedLayout = ((LinearLayout) container.getChildAt(i));
+ for (int j = 0; j < nestedLayout.getChildCount(); j++){
+ View view = nestedLayout.getChildAt(j);
+ if (view.getClass() == NumPadKey.class) {
+ views.add((NumPadKey) view);
+ }
+ }
+ }
+ }
+
+ // reset the digits in the views
+ for (int i = 0; i < sNumbers.size(); i++) {
+ NumPadKey view = views.get(i);
+ view.setDigit(sNumbers.get(i));
+ }
+ }
}
@Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 9a91ca4..e8dd871 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -132,10 +132,18 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView);
mLockPatternView.setSaveEnabled(false);
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
+ mLockPatternView.setLockPatternUtils(mLockPatternUtils);
+ mLockPatternView.setLockPatternSize(mLockPatternUtils.getLockPatternSize());
+
+ mLockPatternView.setVisibleDots(mLockPatternUtils.isVisibleDotsEnabled(
+ KeyguardUpdateMonitor.getCurrentUser()));
+ mLockPatternView.setShowErrorPath(mLockPatternUtils.isShowErrorPath(
+ KeyguardUpdateMonitor.getCurrentUser()));
// stealth mode will be the same for the life of this screen
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
KeyguardUpdateMonitor.getCurrentUser()));
+ setFocusableInTouchMode(true);
// vibrate mode will be the same for the life of this screen
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index 2033159..4d26adf 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -50,7 +50,8 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
private ProgressDialog mSimUnlockProgressDialog = null;
private CheckSimPin mCheckSimPinThread;
-
+ private boolean mShowDefaultMessage = true;
+ private int mRemainingAttempts = -1;
private AlertDialog mRemainingAttemptsDialog;
private int mSubId;
private ImageView mSimImageView;
@@ -74,25 +75,8 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
public void resetState() {
super.resetState();
if (DEBUG) Log.v(TAG, "Resetting state");
- KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
- mSubId = monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED);
- if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
- int count = TelephonyManager.getDefault().getSimCount();
- Resources rez = getResources();
- final String msg;
- int color = Color.WHITE;
- if (count < 2) {
- msg = rez.getString(R.string.kg_sim_pin_instructions);
- } else {
- SubscriptionInfo info = monitor.getSubscriptionInfoForSubId(mSubId);
- CharSequence displayName = info != null ? info.getDisplayName() : ""; // don't crash
- msg = rez.getString(R.string.kg_sim_pin_instructions_multi, displayName);
- if (info != null) {
- color = info.getIconTint();
- }
- }
- mSecurityMessageDisplay.setMessage(msg, true);
- mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+ if (mShowDefaultMessage) {
+ showDefaultMessage();
}
}
@@ -108,17 +92,19 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
return 0;
}
- private String getPinPasswordErrorMessage(int attemptsRemaining) {
+ private String getPinPasswordErrorMessage(int attemptsRemaining, boolean isDefault) {
String displayMessage;
-
+ int msgId;
if (attemptsRemaining == 0) {
displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked);
} else if (attemptsRemaining > 0) {
+ msgId = isDefault ? R.plurals.kg_password_default_pin_message :
+ R.plurals.kg_password_wrong_pin_code;
displayMessage = getContext().getResources()
- .getQuantityString(R.plurals.kg_password_wrong_pin_code, attemptsRemaining,
- attemptsRemaining);
+ .getQuantityString(msgId, attemptsRemaining, attemptsRemaining);
} else {
- displayMessage = getContext().getString(R.string.kg_password_pin_failed);
+ msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed;
+ displayMessage = getContext().getString(msgId);
}
if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
+ " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
@@ -150,6 +136,9 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ if (mShowDefaultMessage) {
+ showDefaultMessage();
+ }
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
}
@@ -228,7 +217,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
}
private Dialog getSimRemainingAttemptsDialog(int remaining) {
- String msg = getPinPasswordErrorMessage(remaining);
+ String msg = getPinPasswordErrorMessage(remaining, false);
if (mRemainingAttemptsDialog == null) {
Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage(msg);
@@ -249,7 +238,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
if (entry.length() < 4) {
// otherwise, display a message to the user, and don't submit.
- mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
+ mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_length, true);
resetPasswordText(true);
mCallback.userActivity();
return;
@@ -262,15 +251,20 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
void onSimCheckResponse(final int result, final int attemptsRemaining) {
post(new Runnable() {
public void run() {
+ mRemainingAttempts = attemptsRemaining;
if (mSimUnlockProgressDialog != null) {
mSimUnlockProgressDialog.hide();
}
resetPasswordText(true /* animate */);
if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
+ mRemainingAttempts = -1;
KeyguardUpdateMonitor.getInstance(getContext())
.reportSimUnlocked(mSubId);
- mCallback.dismiss(true);
+ if (mCallback != null) {
+ mCallback.dismiss(true);
+ }
} else {
+ mShowDefaultMessage = false;
if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
if (attemptsRemaining <= 2) {
// this is getting critical - show dialog
@@ -278,7 +272,8 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
} else {
// show message
mSecurityMessageDisplay.setMessage(
- getPinPasswordErrorMessage(attemptsRemaining), true);
+ getPinPasswordErrorMessage(
+ attemptsRemaining, false), true);
}
} else {
// "PIN operation failed!" - no idea what this was and no way to
@@ -309,5 +304,38 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
public boolean startDisappearAnimation(Runnable finishRunnable) {
return false;
}
+
+ private void showDefaultMessage() {
+ KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+ mSubId = monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED);
+ if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ return;
+ }
+ if (mRemainingAttempts >= 0) {
+ mSecurityMessageDisplay.setMessage(getPinPasswordErrorMessage(
+ mRemainingAttempts, true), true);
+ return;
+ } else {
+ mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
+ }
+
+ int count = TelephonyManager.getDefault().getSimCount();
+ Resources rez = getResources();
+ final String msg;
+ int color = Color.WHITE;
+ if (count < 2) {
+ msg = rez.getString(R.string.kg_sim_pin_instructions);
+ } else {
+ SubscriptionInfo info = monitor.getSubscriptionInfoForSubId(mSubId);
+ CharSequence displayName = info != null ? info.getDisplayName() : ""; // don't crash
+ msg = rez.getString(R.string.kg_sim_pin_instructions_multi, displayName);
+ if (info != null) {
+ color = info.getIconTint();
+ }
+ }
+ mSecurityMessageDisplay.setMessage(msg, true);
+ mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+
+ }
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index af88239..7ba952b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -50,6 +50,7 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
private ProgressDialog mSimUnlockProgressDialog = null;
private CheckSimPuk mCheckSimPukThread;
+ private boolean mShowDefaultMessage = true;
private String mPukText;
private String mPinText;
private StateMachine mStateMachine = new StateMachine();
@@ -133,7 +134,10 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
color = info.getIconTint();
}
}
- mSecurityMessageDisplay.setMessage(msg, true);
+ if (mShowDefaultMessage) {
+ mSecurityMessageDisplay.setMessage(msg, true);
+ }
+ mShowDefaultMessage = true;
mSimImageView.setImageTintList(ColorStateList.valueOf(color));
}
mPasswordEntry.requestFocus();
@@ -328,6 +332,7 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
.reportSimUnlocked(mSubId);
mCallback.dismiss(true);
} else {
+ mShowDefaultMessage = false;
if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
if (attemptsRemaining <= 2) {
// this is getting critical - show dialog
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index f95b0ae..adb5ae9 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,6 +26,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.AttributeSet;
@@ -229,10 +233,20 @@ public class KeyguardStatusView extends GridLayout {
: R.string.abbrev_wday_month_day_no_year);
final String clockView12Skel = res.getString(R.string.clock_12hr_format);
final String clockView24Skel = res.getString(R.string.clock_24hr_format);
- final String key = locale.toString() + dateViewSkel + clockView12Skel + clockView24Skel;
- if (key.equals(cacheKey)) return;
- dateView = DateFormat.getBestDateTimePattern(locale, dateViewSkel);
+ if (res.getBoolean(com.android.internal.R.bool.def_custom_dateformat)) {
+ final String dateformat = Settings.System.getString(context.getContentResolver(),
+ Settings.System.DATE_FORMAT);
+ dateView = dateformat.equals(dateView) ? dateView : dateformat;
+ } else {
+ final String key = locale.toString() + dateViewSkel + clockView12Skel
+ + clockView24Skel;
+ if (key.equals(cacheKey)) {
+ return;
+ }
+ dateView = DateFormat.getBestDateTimePattern(locale, dateViewSkel);
+ cacheKey = key;
+ }
clockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
// CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
@@ -247,7 +261,6 @@ public class KeyguardStatusView extends GridLayout {
clockView24 = clockView24.replace(':', '\uee01');
clockView12 = clockView12.replace(':', '\uee01');
- cacheKey = key;
}
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 57ee319..5e09729 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -772,11 +772,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
state = IccCardConstants.State.PIN_REQUIRED;
} else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
state = IccCardConstants.State.PUK_REQUIRED;
+ } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(lockedReason)) {
+ state = IccCardConstants.State.NETWORK_LOCKED;
} else {
state = IccCardConstants.State.UNKNOWN;
}
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
- state = IccCardConstants.State.NETWORK_LOCKED;
+ } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
+ state = IccCardConstants.State.CARD_IO_ERROR;
} else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
|| IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
// This is required because telephony doesn't return to "READY" after
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index ef8bb0b..839c165 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.os.PowerManager;
import android.os.SystemClock;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
@@ -29,6 +30,8 @@ import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
+import cyanogenmod.providers.CMSettings;
+
public class NumPadKey extends ViewGroup {
// list of "ABC", etc per digit, starting with '0'
static String sKlondike[];
@@ -73,7 +76,6 @@ public class NumPadKey extends ViewGroup {
public NumPadKey(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFocusable(true);
-
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey);
try {
@@ -88,7 +90,6 @@ public class NumPadKey extends ViewGroup {
setAccessibilityDelegate(new ObscureSpeechDelegate(context));
mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
-
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
@@ -98,32 +99,44 @@ public class NumPadKey extends ViewGroup {
mDigitText.setText(Integer.toString(mDigit));
mKlondikeText = (TextView) findViewById(R.id.klondike_text);
+ updateText();
+ setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
+ setContentDescription(mDigitText.getText().toString());
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ // Reset the "announced headset" flag when detached.
+ ObscureSpeechDelegate.sAnnouncedHeadset = false;
+ }
+
+ public void setDigit(int digit) {
+ mDigit = digit;
+ updateText();
+ }
+
+ private void updateText() {
+ boolean scramblePin = (CMSettings.System.getInt(getContext().getContentResolver(),
+ CMSettings.System.LOCKSCREEN_PIN_SCRAMBLE_LAYOUT, 0) == 1);
if (mDigit >= 0) {
+ mDigitText.setText(Integer.toString(mDigit));
if (sKlondike == null) {
sKlondike = getResources().getStringArray(R.array.lockscreen_num_pad_klondike);
}
if (sKlondike != null && sKlondike.length > mDigit) {
String klondike = sKlondike[mDigit];
final int len = klondike.length();
- if (len > 0) {
+ if (len > 0 || scramblePin) {
mKlondikeText.setText(klondike);
} else {
mKlondikeText.setVisibility(View.INVISIBLE);
}
}
}
-
- setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
- setContentDescription(mDigitText.getText().toString());
}
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- // Reset the "announced headset" flag when detached.
- ObscureSpeechDelegate.sAnnouncedHeadset = false;
- }
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
diff --git a/packages/PrintSpooler/res/values-ast-rES/strings.xml b/packages/PrintSpooler/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..68cc206
--- /dev/null
+++ b/packages/PrintSpooler/res/values-ast-rES/strings.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">Cola d\'impresión</string>
+ <string name="more_options_button">Más opciones</string>
+ <string name="label_destination">Destín</string>
+ <string name="label_copies">Copies</string>
+ <string name="label_copies_summary">Copies:</string>
+ <string name="label_paper_size">Tamañu papel</string>
+ <string name="label_paper_size_summary">Tamañu papel:</string>
+ <string name="label_color">Color</string>
+ <string name="label_orientation">Orientación</string>
+ <string name="label_pages">Páxines</string>
+ <string name="template_all_pages">Too <xliff:g id="page_count" example="100">%1$s</xliff:g></string>
+ <string name="template_page_range">Rangu de <xliff:g id="page_count" example="100">%1$s</xliff:g></string>
+ <string name="pages_range_example">ex. 1—5,8,11—13</string>
+ <string name="print_preview">Previsualizar impresión</string>
+ <string name="install_for_print_preview">Instalar visor PDF pa previsualizar</string>
+ <string name="printing_app_crashed">Falló l\'aplicación d\'impresión</string>
+ <string name="generating_print_job">Xenerando trabayu d\'impresión</string>
+ <string name="save_as_pdf">Guardar como PDF</string>
+ <string name="all_printers">Toles imprentadores&#8230;</string>
+ <string name="print_dialog">Cuadru de diálogu d\'impresión</string>
+ <string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
+ /<xliff:g id="page_count">%2$d</xliff:g></string>
+ <string name="page_description_template">Páxina <xliff:g id="current_page" example="1">%1$d</xliff:g>
+ de <xliff:g id="page_count" example="100">%2$d</xliff:g></string>
+ <string name="summary_template">Resume, copies <xliff:g id="copies" example="1">%1$s</xliff:g>,
+ tamañu papel <xliff:g id="paper_size" example="A4">%2$s</xliff:g></string>
+ <string name="expand_handle">Remanar espansión</string>
+ <string name="collapse_handle">Remanar contraición</string>
+ <string name="print_button">Imprentar</string>
+ <string name="savetopdf_button">Guardar a PDF</string>
+ <string name="print_options_expanded">Opciones d\'imprentación espandíes</string>
+ <string name="print_options_collapsed">Opciones d\'imprentación contrayíes</string>
+ <string name="search">Guetar</string>
+ <string name="all_printers_label">Toles imprentadores</string>
+ <string name="add_print_service_label">Amestar serviciu</string>
+ <string name="print_search_box_shown_utterance">Cuadru de gueta visible</string>
+ <string name="print_search_box_hidden_utterance">Cuadru de gueta anubríu</string>
+ <string name="print_add_printer">Amestar imprentadora</string>
+ <string name="print_select_printer">Esbillar imprentadora</string>
+ <string name="print_forget_printer">Esborrar imprentadora</string>
+ <string name="choose_print_service">Elexir serviciu d\'impresión</string>
+ <string name="print_searching_for_printers">Guetando imprentadores</string>
+ <string name="print_no_printers">Nun s\'atoparon imprentadores</string>
+ <string name="printing_notification_title_template">Imprentando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g></string>
+ <string name="cancelling_notification_title_template">Encaboxando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g></string>
+ <string name="failed_notification_title_template">Fallu d\'imprentadora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g></string>
+ <string name="blocked_notification_title_template">La imprentadora bloquió <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g></string>
+ <string name="cancel">Encaboxar</string>
+ <string name="restart">Reaniciar</string>
+ <string name="no_connection_to_printer">Nun hai conexón cola imprentadora</string>
+ <string name="reason_unknown">desconocíu</string>
+ <string name="printer_unavailable"><xliff:g id="print_job_name" example="Canon-123GHT">%1$s</xliff:g> – non disponible</string>
+ <string-array name="color_mode_labels">
+ <item>Blancu y prietu</item>
+ <item>Color</item>
+ </string-array>
+ <string-array name="orientation_labels">
+ <item>Retratu</item>
+ <item>Paisaxe</item>
+ </string-array>
+ <string name="print_write_error_message">Nun pudo escribise nel ficheru</string>
+ <string name="print_error_default_message">Nun funcionó. Inténtalo otra vegada.</string>
+ <string name="print_error_retry">Repitir</string>
+ <string name="print_error_printer_unavailable">La imprentadora nun ta disponible agora.</string>
+ <string name="print_preparing_preview">Preparando previsualización\u2026</string>
+</resources>
diff --git a/packages/PrintSpooler/res/values-ku/strings.xml b/packages/PrintSpooler/res/values-ku/strings.xml
new file mode 100644
index 0000000..f2b5439
--- /dev/null
+++ b/packages/PrintSpooler/res/values-ku/strings.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">بەڕێوەبەری چاپکەر</string>
+ <string name="more_options_button">بەربژاردەی زیاتر</string>
+ <string name="label_destination">ئامانج</string>
+ <string name="label_copies">لەبەرگرتنەوەکان</string>
+ <string name="label_copies_summary">لەبەرگرتنەوەکان:</string>
+ <string name="label_paper_size">قەبارەی کاغەز</string>
+ <string name="label_paper_size_summary">قەبارەی کاغەز:</string>
+ <string name="label_color">رەنگ</string>
+ <string name="label_orientation">باری پیشاندان</string>
+ <string name="label_pages">پەڕەکان</string>
+ <string name="template_all_pages">هەموو <xliff:g id="page_count" example="100">%1$s</xliff:g></string>
+ <string name="template_page_range">ڕێژەی <xliff:g id="page_count" example="100">%1$s</xliff:g></string>
+ <string name="pages_range_example">نموونە . 1—5,8,11—13</string>
+ <string name="print_preview">بینینی پێش چاپ</string>
+ <string name="install_for_print_preview">دامەزراندنی بینەری PDF بۆ پێشبینین</string>
+ <string name="printing_app_crashed">بەرنامەی چاپکردن تێکشکا</string>
+ <string name="generating_print_job">سازدانی ئەرکی چاپ</string>
+ <string name="save_as_pdf">پاشەکەوت بە PDF</string>
+ <string name="all_printers">هەموو چاپکەرەکان&#8230;</string>
+ <string name="print_dialog">دیالۆگی چاپ</string>
+ <string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
+        /<xliff:g id="page_count">%2$d</xliff:g></string>
+ <string name="page_description_template">پەڕە <xliff:g id="current_page" example="1">%1$d</xliff:g>
+        لە <xliff:g id="page_count" example="100">%2$d</xliff:g></string>
+ <string name="summary_template">کورتە, لەبەرگرتنەوە <xliff:g id="copies" example="1">%1$s</xliff:g>,
+        قەبارەی پەڕە <xliff:g id="paper_size" example="A4">%2$s</xliff:g></string>
+ <string name="expand_handle">بڵاوکردنەوەی دەست</string>
+ <string name="collapse_handle">دەست دەکەوێت</string>
+ <string name="print_button">چاپکردن</string>
+ <string name="savetopdf_button">پاشەکەوتبکە بۆ PDF</string>
+ <string name="print_options_expanded">هەڵبژاردەی لەبەرگرتنەوە بڵاوکرایەوە</string>
+ <string name="print_options_collapsed">هەڵبژادەکانی لەبەرگرتنەوەی دەستکەوت</string>
+ <string name="search">گەڕان</string>
+ <string name="all_printers_label">هەموو چاپکەرەکان</string>
+ <string name="add_print_service_label">زیادکردنی ڕاژە</string>
+ <string name="print_search_box_shown_utterance">سنووقی گەڕان پیشاندراوە</string>
+ <string name="print_search_box_hidden_utterance">سنووقی گەڕان شاراوەیە</string>
+ <string name="print_add_printer">چاپکەر زیاد بکە</string>
+ <string name="print_select_printer">چاپکەر دەستنیشان بکە</string>
+ <string name="print_forget_printer">چاپکەر لەیادکە</string>
+ <string name="choose_print_service">خزمەتگوزاریی چاپکردن هەڵبژێرە</string>
+ <string name="print_searching_for_printers">گەڕان بەدوای چاپکەردا</string>
+ <string name="print_no_printers">هیچ چاپکەرێک نەدۆزرایەوە</string>
+ <string name="printing_notification_title_template">چاپکردن <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <string name="cancelling_notification_title_template">هەڵوەشاندنەوە <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <string name="failed_notification_title_template">هەڵەی چاپکەر <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <string name="blocked_notification_title_template">چاپکەر بەستراوە <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <string name="cancel">هەڵوەشانەوە</string>
+ <string name="restart">دەستپێکردنەوە</string>
+ <string name="no_connection_to_printer">پەیوەست نییە بە چاپکەرەوە</string>
+ <string name="reason_unknown">نەناسراو</string>
+ <string name="printer_unavailable"><xliff:g id="print_job_name" example="Canon-123GHT">%1$s</xliff:g> – بەردەست نییە</string>
+ <string-array name="color_mode_labels">
+ <item>رەش وamp; سپی</item>
+ <item>ڕەنگ</item>
+ </string-array>
+ <string-array name="orientation_labels">
+ <item>وێنەی شێوە</item>
+ <item>وێنەی سروشت</item>
+ </string-array>
+ <string name="print_write_error_message">ناتوانرێت فایلێک بنوسرێت</string>
+ <string name="print_error_default_message">ببورە، ئەمە کاری نەکرد. دوبارە هەوڵبدەرەوە.</string>
+ <string name="print_error_retry">هەوڵدانەوە</string>
+ <string name="print_error_printer_unavailable">ئەم چاپکەرە لە کارانیە ئێستا.</string>
+ <string name="print_preparing_preview">پیشاندانی ڕێکخستن\u2026</string>
+</resources>
diff --git a/packages/PrintSpooler/res/values-lb/strings.xml b/packages/PrintSpooler/res/values-lb/strings.xml
new file mode 100644
index 0000000..765c41f
--- /dev/null
+++ b/packages/PrintSpooler/res/values-lb/strings.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">Drock-Tëschespäicher</string>
+ <string name="more_options_button">Méi Optiounen</string>
+ <string name="label_destination">Destinatioun</string>
+ <string name="label_copies">Kopien</string>
+ <string name="label_copies_summary">Kopien:</string>
+ <string name="label_paper_size">Pabeiersgréisst</string>
+ <string name="label_paper_size_summary">Pabeiersgréisst:</string>
+ <string name="label_color">Faarf</string>
+ <string name="label_orientation">Orientéierung</string>
+ <string name="label_pages">Säiten</string>
+ <string name="template_all_pages">All (<xliff:g id="page_count" example="100">%1$s</xliff:g>)</string>
+ <string name="template_page_range">Rei (<xliff:g id="page_count" example="100">%1$s</xliff:g>)</string>
+ <string name="pages_range_example">z. B. 1-5,8,11-13</string>
+ <string name="print_preview">Drockvirschau</string>
+ <string name="install_for_print_preview">Installéier e PDF-Programm fir eng Drockvirschau</string>
+ <string name="printing_app_crashed">D\'Drockapp ass ofgestierzt</string>
+ <string name="generating_print_job">Drockoptrag gëtt generéiert</string>
+ <string name="save_as_pdf">Als PDF späicheren</string>
+ <string name="all_printers">All d\'Drécker&#8230;</string>
+ <string name="print_dialog">Drockdialogfënster</string>
+ <string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g> / <xliff:g id="page_count">%2$d</xliff:g></string>
+ <string name="page_description_template">Säit <xliff:g id="current_page" example="1">%1$d</xliff:g> / <xliff:g id="page_count" example="100">%2$d</xliff:g></string>
+ <string name="summary_template">Resumé, <xliff:g id="copies" example="1">%1$s</xliff:g> Kopien, Pabeiersgréisst <xliff:g id="paper_size" example="A4">%2$s</xliff:g></string>
+ <string name="expand_handle">Steierelement fir d\'Ausklappen</string>
+ <string name="collapse_handle">Steierelement fir d\'Zesummeklappen</string>
+ <string name="print_button">Drécken</string>
+ <string name="savetopdf_button">Als PDF späicheren</string>
+ <string name="print_options_expanded">Drockoptiounen ausgeklappt</string>
+ <string name="print_options_collapsed">Drockoptiounen zesummegeklappt</string>
+ <string name="search">Sichen</string>
+ <string name="all_printers_label">All d\'Drécker</string>
+ <string name="add_print_service_label">Service dobäisetzen</string>
+ <string name="print_search_box_shown_utterance">Sichkëscht ugewisen</string>
+ <string name="print_search_box_hidden_utterance">Sichkëscht verstoppt</string>
+ <string name="print_add_printer">Drécker dobäisetzen</string>
+ <string name="print_select_printer">Drécker auswielen</string>
+ <string name="print_forget_printer">Drécker vergiessen</string>
+ <string name="choose_print_service">Drockservice auswielen</string>
+ <string name="print_searching_for_printers">Et gëtt no Drécker gesicht</string>
+ <string name="print_no_printers">Keen Drécker fonnt</string>
+ <string name="printing_notification_title_template"><xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g> gëtt gedréckt</string>
+ <string name="cancelling_notification_title_template"><xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g> gëtt ofgebrach</string>
+ <string name="failed_notification_title_template">Dréckerfeeler <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <string name="blocked_notification_title_template">Drécker blockéiert <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <string name="cancel">Ofbriechen</string>
+ <string name="restart">Nei starten</string>
+ <string name="no_connection_to_printer">Keng Connectioun mam Drécker</string>
+ <string name="reason_unknown">onbekannt</string>
+ <string name="printer_unavailable"><xliff:g id="print_job_name" example="Canon-123GHT">%1$s</xliff:g> – net verfügbar</string>
+ <string-array name="color_mode_labels">
+ <item>Schwaarz &amp; Wäiss</item>
+ <item>Faarf</item>
+ </string-array>
+ <string-array name="orientation_labels">
+ <item>Héichformat</item>
+ <item>Breetformat</item>
+ </string-array>
+ <string name="print_write_error_message">Feeler beim Schreiwen an de Fichier</string>
+ <string name="print_error_default_message">Dat ass leider net gaangen. Probéier nees.</string>
+ <string name="print_error_retry">Nees probéieren</string>
+ <string name="print_error_printer_unavailable">Den Drécker ass momentan net disponibel.</string>
+ <string name="print_preparing_preview">Virschau gëtt preparéiert\u2026</string>
+</resources>
diff --git a/packages/PrintSpooler/res/values-ug/strings.xml b/packages/PrintSpooler/res/values-ug/strings.xml
new file mode 100644
index 0000000..0097d00
--- /dev/null
+++ b/packages/PrintSpooler/res/values-ug/strings.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">بېسىشنى بىر تەرەپ قىلىش مۇلازىمىتى</string>
+ <string name="label_destination">نىشان</string>
+ <string name="label_copies">نۇسخا</string>
+ <string name="label_color">رەڭ</string>
+ <string name="label_orientation">يۆنىلىش</string>
+ <string name="pages_range_example">مەسىلەن: 1–5,8,11–13</string>
+ <string name="print_preview">بېسىشنى ئالدىن كۆزەت</string>
+ <string name="install_for_print_preview">ئالدىن كۆزىتىش ئۈچۈن PDF كۆرگۈچ ئورنىتىدۇ</string>
+ <string name="printing_app_crashed">باسىدىغان ئەپ يىمىرىلدى</string>
+ <string name="generating_print_job">بېسىش ۋەزىپىسى قۇرۇۋاتىدۇ</string>
+ <string name="save_as_pdf">PDF سۈپىتىدە ساقلا</string>
+ <string name="all_printers">بارلىق پرىنتېرلار&#8230;</string>
+ <string name="print_dialog">بېسىش سۆزلەشكۈ</string>
+ <string name="print_button">باس</string>
+ <string name="search">ئىزدە</string>
+ <string name="all_printers_label">بارلىق پرىنتېرلار</string>
+ <string name="add_print_service_label">مۇلازىمەت قوش</string>
+ <string name="print_search_box_shown_utterance">ئىزدەش قۇتىسى كۆرۈندى</string>
+ <string name="print_search_box_hidden_utterance">ئىزدەش قۇتىسى يوشۇرۇلدى</string>
+ <string name="print_add_printer">پرىنتېر قوش</string>
+ <string name="print_select_printer">پىرىنتېرنى تاللاڭ</string>
+ <string name="print_forget_printer">پىرىنتېرنى ئەستە تۇتما</string>
+ <string name="choose_print_service">بېسىش مۇلازىمىتىنى تاللاڭ</string>
+ <string name="print_searching_for_printers">پرىنتېرلارنى ئىزدەۋاتىدۇ</string>
+ <string name="print_no_printers">پرىنتېر تېپىلمىدى</string>
+ <string name="printing_notification_title_template">بېسىۋاتقىنى <xliff:g id="PRINT_JOB_NAME">%s</xliff:g></string>
+ <string name="cancelling_notification_title_template">بىكار قىلىۋاتقىنى <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g></string>
+ <string name="failed_notification_title_template">پىرىنتېر <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> نى بېسىۋاتقاندا خاتالىق كۆرۈلدى</string>
+ <string name="blocked_notification_title_template">پىرىنتېر <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> نى بېسىشنى توستى</string>
+ <string name="cancel">ۋاز كەچ</string>
+ <string name="restart">قايتا قوزغات</string>
+ <string name="no_connection_to_printer">پرىنتېر بىلەن باغلانمىدى</string>
+ <string name="reason_unknown">يوچۇن</string>
+ <string name="printer_unavailable"><xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ئىشلەتكىلى بولمايدۇ</string>
+ <string-array name="color_mode_labels">
+ <item>ئاق&amp;قارا</item>
+ <item>رەڭ</item>
+ </string-array>
+ <string-array name="orientation_labels">
+ <item>بويىغا</item>
+ <item>توغرىسىغا</item>
+ </string-array>
+</resources>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/arrays.xml b/packages/PrintSpooler/res/values-zh-rCN/arrays.xml
new file mode 100644
index 0000000..4fc75db
--- /dev/null
+++ b/packages/PrintSpooler/res/values-zh-rCN/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+ <string-array name="pdf_printer_media_sizes" translatable="false">
+ <item>ROC_8K</item>
+ <item>ROC_16K</item>
+ <item>PRC_1</item>
+ <item>PRC_2</item>
+ <item>PRC_3</item>
+ <item>PRC_4</item>
+ <item>PRC_5</item>
+ <item>PRC_6</item>
+ <item>PRC_7</item>
+ <item>PRC_8</item>
+ <item>PRC_9</item>
+ <item>PRC_10</item>
+ <item>PRC_16K</item>
+ <item>OM_PA_KAI</item>
+ <item>OM_DAI_PA_KAI</item>
+ <item>OM_JUURO_KU_KAI</item>
+ </string-array>
+
+</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
index 7db2074..11a9a0e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
@@ -56,6 +56,7 @@ public final class PdfManipulationService extends Service {
private static final int MILS_PER_INCH = 1000;
private static final int POINTS_IN_INCH = 72;
+ private final Object mLock = new Object();
@Override
public IBinder onBind(Intent intent) {
@@ -74,8 +75,6 @@ public final class PdfManipulationService extends Service {
}
private final class PdfRendererImpl extends IPdfRenderer.Stub {
- private final Object mLock = new Object();
-
private Bitmap mBitmap;
private PdfRenderer mRenderer;
@@ -209,8 +208,6 @@ public final class PdfManipulationService extends Service {
}
private final class PdfEditorImpl extends IPdfEditor.Stub {
- private final Object mLock = new Object();
-
private PdfEditor mEditor;
@Override
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index e8a5e43..1fb84b4 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -371,6 +371,22 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
@Override
+ protected void onDestroy() {
+ if (mState != STATE_INITIALIZING) {
+ mPrintPreviewController.destroy(new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ });
+ } else {
+ finish();
+ }
+
+ super.onDestroy();
+ }
+
+ @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
event.startTracking();
diff --git a/packages/SettingsLib/res/drawable-hdpi/activities_icon.png b/packages/SettingsLib/res/drawable-hdpi/activities_icon.png
new file mode 100644
index 0000000..d4fb5cb
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/activities_icon.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png
index 2d9b75e..eebbe00 100644
--- a/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png
+++ b/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png
index b6ebe34..92d7e51 100644
--- a/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png
+++ b/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png
index 8b67b91..95f90bac 100644
--- a/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png
+++ b/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/activities_icon.png b/packages/SettingsLib/res/drawable-mdpi/activities_icon.png
new file mode 100644
index 0000000..db3f889
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/activities_icon.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/activities_icon.png b/packages/SettingsLib/res/drawable-xhdpi/activities_icon.png
new file mode 100644
index 0000000..b649acb
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/activities_icon.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/activities_icon.png b/packages/SettingsLib/res/drawable-xxhdpi/activities_icon.png
new file mode 100644
index 0000000..295bba3
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/activities_icon.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/activities_icon.png b/packages/SettingsLib/res/drawable-xxxhdpi/activities_icon.png
new file mode 100644
index 0000000..0b05aef
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/activities_icon.png
Binary files differ
diff --git a/packages/SettingsLib/res/values-af/cm_strings.xml b/packages/SettingsLib/res/values-af/cm_strings.xml
new file mode 100644
index 0000000..8481dda
--- /dev/null
+++ b/packages/SettingsLib/res/values-af/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Programme</string>
+ <string name="picker_activities">Aktiwiteite</string>
+ <string name="select_custom_app_title">Kies persoonlike program</string>
+ <string name="select_custom_activity_title">Kies persoonlike aktiwiteit</string>
+ <string name="lockscreen_targets_message">Slotskerm kortpaaie</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-be/cm_strings.xml b/packages/SettingsLib/res/values-be/cm_strings.xml
new file mode 100644
index 0000000..138b12d
--- /dev/null
+++ b/packages/SettingsLib/res/values-be/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Дадаткі</string>
+ <string name="picker_activities">Дзеянні</string>
+ <string name="select_custom_app_title">Выбар дадатку</string>
+ <string name="select_custom_activity_title">Выбар дзеяння</string>
+ <string name="lockscreen_targets_message">Значыкі экрану блакавання</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-bg/cm_strings.xml b/packages/SettingsLib/res/values-bg/cm_strings.xml
new file mode 100644
index 0000000..7160cc2
--- /dev/null
+++ b/packages/SettingsLib/res/values-bg/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Приложения</string>
+ <string name="picker_activities">Дейности</string>
+ <string name="select_custom_app_title">Изберете приложение</string>
+ <string name="select_custom_activity_title">Изберете потребителска дейност</string>
+ <string name="lockscreen_targets_message">Преки пътища на заключен екран</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ca/cm_strings.xml b/packages/SettingsLib/res/values-ca/cm_strings.xml
new file mode 100644
index 0000000..50933db
--- /dev/null
+++ b/packages/SettingsLib/res/values-ca/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplicacions</string>
+ <string name="picker_activities">Activitats</string>
+ <string name="select_custom_app_title">Selecciona una aplicació personalitzada</string>
+ <string name="select_custom_activity_title">Selecciona una activitat personalitzada</string>
+ <string name="lockscreen_targets_message">Dreceres de la pantalla de bloqueig</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-cs/cm_strings.xml b/packages/SettingsLib/res/values-cs/cm_strings.xml
new file mode 100644
index 0000000..faccd6f
--- /dev/null
+++ b/packages/SettingsLib/res/values-cs/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplikace</string>
+ <string name="picker_activities">Aktivity</string>
+ <string name="select_custom_app_title">Zvolte vlastní aplikaci</string>
+ <string name="select_custom_activity_title">Zvolte vlastní aktivitu</string>
+ <string name="lockscreen_targets_message">Ikony zámku obrazovky</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-da/cm_strings.xml b/packages/SettingsLib/res/values-da/cm_strings.xml
new file mode 100644
index 0000000..0d86cdb
--- /dev/null
+++ b/packages/SettingsLib/res/values-da/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Aktiviteter</string>
+ <string name="select_custom_app_title">Vælg brugerdefineret app</string>
+ <string name="select_custom_activity_title">Vælg brugerdefineret aktivitet</string>
+ <string name="lockscreen_targets_message">Genveje på låseskærm</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-de/cm_strings.xml b/packages/SettingsLib/res/values-de/cm_strings.xml
new file mode 100644
index 0000000..3227f21
--- /dev/null
+++ b/packages/SettingsLib/res/values-de/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Aktivitäten</string>
+ <string name="select_custom_app_title">Benutzerdefinierte Anwendung auswählen</string>
+ <string name="select_custom_activity_title">Benutzerdefinierte Aktivität auswählen</string>
+ <string name="lockscreen_targets_message">Sperrbildschirm-Verknüpfungen</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-el/cm_strings.xml b/packages/SettingsLib/res/values-el/cm_strings.xml
new file mode 100644
index 0000000..f622a7f
--- /dev/null
+++ b/packages/SettingsLib/res/values-el/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Εφαρμογές</string>
+ <string name="picker_activities">Δραστηριότητες</string>
+ <string name="select_custom_app_title">Επιλέξτε προσαρμοσμένη εφαρμογή</string>
+ <string name="select_custom_activity_title">Επιλέξτε προσαρμοσμένη δραστηριότητα</string>
+ <string name="lockscreen_targets_message">Συντομεύσεις οθόνης κλειδώματος</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/cm_strings.xml b/packages/SettingsLib/res/values-en-rIN/cm_strings.xml
new file mode 100644
index 0000000..b311b85
--- /dev/null
+++ b/packages/SettingsLib/res/values-en-rIN/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Activities</string>
+ <string name="select_custom_app_title">Select custom app</string>
+ <string name="select_custom_activity_title">Select custom activity</string>
+ <string name="lockscreen_targets_message">Lock screen shortcuts</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-eu-rES/cm_strings.xml b/packages/SettingsLib/res/values-eu-rES/cm_strings.xml
new file mode 100644
index 0000000..6f1cec3
--- /dev/null
+++ b/packages/SettingsLib/res/values-eu-rES/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplikazioak</string>
+ <string name="picker_activities">Aktibitateak</string>
+ <string name="select_custom_app_title">Hautatu aplikazio pertsonalizatua</string>
+ <string name="select_custom_activity_title">Hautatu aktibitate pertsonalizatua</string>
+ <string name="lockscreen_targets_message">Blokeo-pantailako lasterbideak</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-fi/cm_strings.xml b/packages/SettingsLib/res/values-fi/cm_strings.xml
new file mode 100644
index 0000000..fb10ac5
--- /dev/null
+++ b/packages/SettingsLib/res/values-fi/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Sovellukset</string>
+ <string name="picker_activities">Aktiviteetit</string>
+ <string name="select_custom_app_title">Valitse oma sovellus</string>
+ <string name="select_custom_activity_title">Valitse oma aktiviteetti</string>
+ <string name="lockscreen_targets_message">Lukitusnäytön pikakuvakkeet</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-fr/cm_strings.xml b/packages/SettingsLib/res/values-fr/cm_strings.xml
new file mode 100644
index 0000000..7cd934f
--- /dev/null
+++ b/packages/SettingsLib/res/values-fr/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Applications</string>
+ <string name="picker_activities">Activités</string>
+ <string name="select_custom_app_title">Sélectionner une application personnalisée</string>
+ <string name="select_custom_activity_title">Sélectionner une activité personnalisée</string>
+ <string name="lockscreen_targets_message">Raccourcis de l\'écran de verrouillage</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/cm_strings.xml b/packages/SettingsLib/res/values-gl-rES/cm_strings.xml
new file mode 100644
index 0000000..a98f4e9
--- /dev/null
+++ b/packages/SettingsLib/res/values-gl-rES/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplicacións</string>
+ <string name="picker_activities">Actividades</string>
+ <string name="select_custom_app_title">Seleccionar aplicación personalizada</string>
+ <string name="select_custom_activity_title">Seleccionar actividade personalizada</string>
+ <string name="lockscreen_targets_message">Atallos da pantalla de bloqueo</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-hr/cm_strings.xml b/packages/SettingsLib/res/values-hr/cm_strings.xml
new file mode 100644
index 0000000..dbf9958
--- /dev/null
+++ b/packages/SettingsLib/res/values-hr/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplikacije</string>
+ <string name="picker_activities">Aktivnosti</string>
+ <string name="select_custom_app_title">Odaberite aplikaciju</string>
+ <string name="select_custom_activity_title">Odaberite prilagođenu aktivnost</string>
+ <string name="lockscreen_targets_message">Prečaci zaključanog zaslona</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-hu/cm_strings.xml b/packages/SettingsLib/res/values-hu/cm_strings.xml
new file mode 100644
index 0000000..b2e364f
--- /dev/null
+++ b/packages/SettingsLib/res/values-hu/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Alkalmazások</string>
+ <string name="picker_activities">Tevékenységek</string>
+ <string name="select_custom_app_title">Válassz egyedi alkalmazást</string>
+ <string name="select_custom_activity_title">Válassz egyedi tevékenységet</string>
+ <string name="lockscreen_targets_message">Zárképernyő hivatkozások</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-it/cm_strings.xml b/packages/SettingsLib/res/values-it/cm_strings.xml
new file mode 100644
index 0000000..e7cc83a
--- /dev/null
+++ b/packages/SettingsLib/res/values-it/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">App</string>
+ <string name="picker_activities">Attività</string>
+ <string name="select_custom_app_title">Seleziona app personalizzata</string>
+ <string name="select_custom_activity_title">Seleziona attività personalizzata</string>
+ <string name="lockscreen_targets_message">Scorciatoie schermata di sblocco</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-iw/cm_strings.xml b/packages/SettingsLib/res/values-iw/cm_strings.xml
new file mode 100644
index 0000000..36ca0d2
--- /dev/null
+++ b/packages/SettingsLib/res/values-iw/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">יישומים</string>
+ <string name="picker_activities">פעילויות</string>
+ <string name="select_custom_app_title">בחר יישום מותאם אישית</string>
+ <string name="select_custom_activity_title">בחר פעילות מותאמת אישית</string>
+ <string name="lockscreen_targets_message">קיצורי דרך במסך הנעילה</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ja/cm_strings.xml b/packages/SettingsLib/res/values-ja/cm_strings.xml
new file mode 100644
index 0000000..7a75cb0
--- /dev/null
+++ b/packages/SettingsLib/res/values-ja/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">アプリ</string>
+ <string name="picker_activities">アクティビティ</string>
+ <string name="select_custom_app_title">カスタムのアプリを選択</string>
+ <string name="select_custom_activity_title">カスタムのアクティビティを選択</string>
+ <string name="lockscreen_targets_message">ロック画面のショートカット</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ko/cm_strings.xml b/packages/SettingsLib/res/values-ko/cm_strings.xml
new file mode 100644
index 0000000..9669798
--- /dev/null
+++ b/packages/SettingsLib/res/values-ko/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">애플리케이션</string>
+ <string name="picker_activities">액티비티</string>
+ <string name="select_custom_app_title">사용자 정의 앱 선택</string>
+ <string name="select_custom_activity_title">사용자 정의 액티비티 선택</string>
+ <string name="lockscreen_targets_message">잠금 화면 바로 가기</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-lb/cm_strings.xml b/packages/SettingsLib/res/values-lb/cm_strings.xml
new file mode 100644
index 0000000..84a7011
--- /dev/null
+++ b/packages/SettingsLib/res/values-lb/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Appen</string>
+ <string name="picker_activities">Aktivitéiten</string>
+ <string name="select_custom_app_title">Eegen App auswielen</string>
+ <string name="select_custom_activity_title">Eegen Aktivitéit auswielen</string>
+ <string name="lockscreen_targets_message">Spärschierm-Ofkierzungen</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-nb/cm_strings.xml b/packages/SettingsLib/res/values-nb/cm_strings.xml
new file mode 100644
index 0000000..e55d4a1
--- /dev/null
+++ b/packages/SettingsLib/res/values-nb/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Aktiviteter</string>
+ <string name="select_custom_app_title">Velg egendefinert app</string>
+ <string name="select_custom_activity_title">Velg egendefinert aktivitet</string>
+ <string name="lockscreen_targets_message">Låseskjermsnarveier</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-nl/cm_strings.xml b/packages/SettingsLib/res/values-nl/cm_strings.xml
new file mode 100644
index 0000000..7dec7e0
--- /dev/null
+++ b/packages/SettingsLib/res/values-nl/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Activiteiten</string>
+ <string name="select_custom_app_title">Aangepaste app kiezen</string>
+ <string name="select_custom_activity_title">Aangepaste activiteit kiezen</string>
+ <string name="lockscreen_targets_message">Snelkoppelingen vergrendelingsscherm</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-pl/cm_strings.xml b/packages/SettingsLib/res/values-pl/cm_strings.xml
new file mode 100644
index 0000000..ba5c4f9
--- /dev/null
+++ b/packages/SettingsLib/res/values-pl/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplikacje</string>
+ <string name="picker_activities">Aktywności</string>
+ <string name="select_custom_app_title">Wskaż aplikację</string>
+ <string name="select_custom_activity_title">Wskaż aktywność</string>
+ <string name="lockscreen_targets_message">Skróty ekranu blokady</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/cm_strings.xml b/packages/SettingsLib/res/values-pt-rBR/cm_strings.xml
new file mode 100644
index 0000000..29ecbff
--- /dev/null
+++ b/packages/SettingsLib/res/values-pt-rBR/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Atividades</string>
+ <string name="select_custom_app_title">Selecione o app personalizado</string>
+ <string name="select_custom_activity_title">Selecione a atividade personalizada</string>
+ <string name="lockscreen_targets_message">Atalhos da tela de bloqueio</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/cm_strings.xml b/packages/SettingsLib/res/values-pt-rPT/cm_strings.xml
new file mode 100644
index 0000000..84f31d2
--- /dev/null
+++ b/packages/SettingsLib/res/values-pt-rPT/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplicações</string>
+ <string name="picker_activities">Atividades</string>
+ <string name="select_custom_app_title">Selecione uma aplicação personalizada</string>
+ <string name="select_custom_activity_title">Selecione uma atividade personalizada</string>
+ <string name="lockscreen_targets_message">Atalhos do ecrã de bloqueio</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ro/cm_strings.xml b/packages/SettingsLib/res/values-ro/cm_strings.xml
new file mode 100644
index 0000000..26f8836
--- /dev/null
+++ b/packages/SettingsLib/res/values-ro/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplicații</string>
+ <string name="picker_activities">Activități</string>
+ <string name="select_custom_app_title">Selectați aplicație personalizată</string>
+ <string name="select_custom_activity_title">Selectați activitate personalizată</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ru/cm_strings.xml b/packages/SettingsLib/res/values-ru/cm_strings.xml
new file mode 100644
index 0000000..b3a4c86
--- /dev/null
+++ b/packages/SettingsLib/res/values-ru/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Приложения</string>
+ <string name="picker_activities">Действия</string>
+ <string name="select_custom_app_title">Выбор приложения</string>
+ <string name="select_custom_activity_title">Выбор действия</string>
+ <string name="lockscreen_targets_message">Ярлыки экрана блокировки</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-sl/cm_strings.xml b/packages/SettingsLib/res/values-sl/cm_strings.xml
new file mode 100644
index 0000000..4a66c17
--- /dev/null
+++ b/packages/SettingsLib/res/values-sl/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Aplikacije</string>
+ <string name="picker_activities">Dejavnosti</string>
+ <string name="select_custom_app_title">Izberite aplikacijo po meri</string>
+ <string name="select_custom_activity_title">Izberite dejavnost po meri</string>
+ <string name="lockscreen_targets_message">Bližnjice zaslona za zaklepanje</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-sr/cm_strings.xml b/packages/SettingsLib/res/values-sr/cm_strings.xml
new file mode 100644
index 0000000..8078426
--- /dev/null
+++ b/packages/SettingsLib/res/values-sr/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Апликације</string>
+ <string name="picker_activities">Активности</string>
+ <string name="select_custom_app_title">Изабери прилагођену апликацију</string>
+ <string name="select_custom_activity_title">Изабери прилагођену активност</string>
+ <string name="lockscreen_targets_message">Пречица закључаног екрана</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-sv/cm_strings.xml b/packages/SettingsLib/res/values-sv/cm_strings.xml
new file mode 100644
index 0000000..15ad908
--- /dev/null
+++ b/packages/SettingsLib/res/values-sv/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Appar</string>
+ <string name="picker_activities">Aktiviteter</string>
+ <string name="select_custom_app_title">Välj anpassad app</string>
+ <string name="select_custom_activity_title">Välj anpassad aktivitet</string>
+ <string name="lockscreen_targets_message">Genvägar på låsskärm</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-uk/cm_strings.xml b/packages/SettingsLib/res/values-uk/cm_strings.xml
new file mode 100644
index 0000000..00f95a7
--- /dev/null
+++ b/packages/SettingsLib/res/values-uk/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Додатки</string>
+ <string name="picker_activities">Дії</string>
+ <string name="select_custom_app_title">Вибрати власну програму</string>
+ <string name="select_custom_activity_title">Вибрати власну дію</string>
+ <string name="lockscreen_targets_message">Ярлики екрану блокування</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/cm_strings.xml b/packages/SettingsLib/res/values-zh-rCN/cm_strings.xml
new file mode 100644
index 0000000..7fbfad4
--- /dev/null
+++ b/packages/SettingsLib/res/values-zh-rCN/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">应用</string>
+ <string name="picker_activities">活动</string>
+ <string name="select_custom_app_title">选择自定义应用</string>
+ <string name="select_custom_activity_title">选择自定义活动</string>
+ <string name="lockscreen_targets_message">锁屏快捷方式</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/cm_strings.xml b/packages/SettingsLib/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 0000000..478d992
--- /dev/null
+++ b/packages/SettingsLib/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">應用程式</string>
+ <string name="picker_activities">活動</string>
+ <string name="select_custom_app_title">選取自訂應用程式</string>
+ <string name="select_custom_activity_title">選取自訂活動</string>
+ <string name="lockscreen_targets_message">鎖定畫面捷徑</string>
+</resources>
diff --git a/packages/SettingsLib/res/values/cm_dimens.xml b/packages/SettingsLib/res/values/cm_dimens.xml
new file mode 100644
index 0000000..0ab24d0
--- /dev/null
+++ b/packages/SettingsLib/res/values/cm_dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The CyanogenMod 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
+ -->
+<resources>
+ <dimen name="shortcut_picker_left_padding">40dip</dimen>
+</resources>
diff --git a/packages/SettingsLib/res/values/cm_strings.xml b/packages/SettingsLib/res/values/cm_strings.xml
new file mode 100644
index 0000000..a8348b4
--- /dev/null
+++ b/packages/SettingsLib/res/values/cm_strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2015 The CyanogenMod 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="profile_applist_title">Apps</string>
+ <string name="picker_activities">Activities</string>
+ <string name="select_custom_app_title">Select custom app</string>
+ <string name="select_custom_activity_title">Select custom activity</string>
+ <string name="lockscreen_targets_message">Lock screen shortcuts</string>
+</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 9b1f103..bc1f16d 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -123,6 +123,8 @@
<string name="bluetooth_profile_map">Message Access</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the SAP profile (sharing SIM card). -->
<string name="bluetooth_profile_sap">SIM Access</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the dun profile. -->
+ <string name="bluetooth_profile_dun">Dial-up Network Access</string>
<!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. -->
<string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
@@ -142,6 +144,8 @@
<string name="bluetooth_pan_user_profile_summary_connected">Connected to device for Internet access</string>
<!-- Bluetooth settings. Connection options screen. The summary for the checkbox preference when PAN is connected (NAP role). [CHAR LIMIT=25]-->
<string name="bluetooth_pan_nap_profile_summary_connected">Sharing local Internet connection with device</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the DUN checkbox preference when DUN is connected. -->
+ <string name="bluetooth_dun_profile_summary_connected">Connected to Dun Server</string>
<!-- Bluetooth settings. Connection options screen. The summary
for the PAN checkbox preference that describes how checking it
@@ -161,6 +165,8 @@
for the HID checkbox preference that describes how checking it
will set the HID profile as preferred. -->
<string name="bluetooth_hid_profile_summary_use_for">Use for input</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the dun checkbox preference that describes how checking it will set the dun profile as preferred. -->
+ <string name="bluetooth_dun_profile_summary_use_for">Use for Dial-up Network access</string>
<!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] -->
<string name="bluetooth_pairing_accept">Pair</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 9608daa..873d392 100755..100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -116,7 +116,11 @@ public final class A2dpProfile implements LocalBluetoothProfile {
List<BluetoothDevice> sinks = getConnectedDevices();
if (sinks != null) {
for (BluetoothDevice sink : sinks) {
- mService.disconnect(sink);
+ if (sink.equals(device)) {
+ // Connect to same device, Ignore it
+ Log.d(TAG,"Not disconnecting device = " + sink);
+ return true;
+ }
}
}
return mService.connect(device);
@@ -124,18 +128,36 @@ public final class A2dpProfile implements LocalBluetoothProfile {
public boolean disconnect(BluetoothDevice device) {
if (mService == null) return false;
- // Downgrade priority as user is disconnecting the headset.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if (!deviceList.isEmpty()) {
+ for (BluetoothDevice dev : deviceList) {
+ if (dev.equals(device)) {
+ if (V) Log.d(TAG,"Downgrade priority as user" +
+ "is disconnecting the headset");
+ // Downgrade priority as user is disconnecting the headset.
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ }
+ }
}
- return mService.disconnect(device);
+ return false;
}
public int getConnectionStatus(BluetoothDevice device) {
if (mService == null) {
return BluetoothProfile.STATE_DISCONNECTED;
}
- return mService.getConnectionState(device);
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if (!deviceList.isEmpty()) {
+ for (BluetoothDevice dev : deviceList) {
+ if (dev.equals(device)) {
+ return mService.getConnectionState(device);
+ }
+ }
+ }
+ return BluetoothProfile.STATE_DISCONNECTED;
}
public boolean isPreferred(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
new file mode 100755
index 0000000..fd76d81
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dpSink;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+final class A2dpSinkProfile implements LocalBluetoothProfile {
+ private static final String TAG = "A2dpSinkProfile";
+ private static boolean V = true;
+
+ private BluetoothA2dpSink mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+
+ static final ParcelUuid[] SRC_UUIDS = {
+ BluetoothUuid.AudioSource,
+ BluetoothUuid.AdvAudioDist,
+ };
+
+ static final String NAME = "A2DPSink";
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 5;
+
+ // These callbacks run on the main thread.
+ private final class A2dpSinkServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothA2dpSink) proxy;
+ // We just bound to the service, so refresh the UI for any connected A2DP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "A2dpSinkProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(A2dpSinkProfile.this, BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ A2dpSinkProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new A2dpSinkServiceListener(),
+ BluetoothProfile.A2DP_SINK);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> srcs = getConnectedDevices();
+ if (srcs != null) {
+ for (BluetoothDevice src : srcs) {
+ if (src.equals(device)) {
+ // Connect to same device, Ignore it
+ Log.d(TAG,"Ignoring Connect");
+ return true;
+ }
+ }
+ for (BluetoothDevice src : srcs) {
+ mService.disconnect(src);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ // Downgrade priority as user is disconnecting the headset.
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ boolean isA2dpPlaying() {
+ if (mService == null) return false;
+ List<BluetoothDevice> srcs = mService.getConnectedDevices();
+ if (!srcs.isEmpty()) {
+ if (mService.isA2dpPlaying(srcs.get(0))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ // we need to have same string in UI for even SINK Media Audio.
+ return R.string.bluetooth_profile_a2dp;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_a2dp_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_a2dp_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_headphones_a2dp;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP_SINK,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up A2DP proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
index 8dec86a..0bd8dbd 100644..100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
@@ -112,11 +112,15 @@ public final class BluetoothDeviceFilter {
if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS)) {
return true;
}
+ if (BluetoothUuid.containsAnyUuid(uuids, A2dpSinkProfile.SRC_UUIDS)) {
+ return true;
+ }
if (BluetoothUuid.containsAnyUuid(uuids, HeadsetProfile.UUIDS)) {
return true;
}
} else if (btClass != null) {
if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
+ btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP_SINK) ||
btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4bcbea7..8dc48b3 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -196,6 +196,8 @@ public final class BluetoothEventManager {
cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ cachedDevice);
+ // callback to UI to create Preference for new device
+ dispatchDeviceAdded(cachedDevice);
}
cachedDevice.setRssi(rssi);
cachedDevice.setBtClass(btClass);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index d994841..f7b1cee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -135,6 +135,8 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
if (newProfileState == BluetoothProfile.STATE_CONNECTED) {
if (profile instanceof MapProfile) {
profile.setPreferred(mDevice, true);
+ mRemovedProfiles.remove(profile);
+ mProfiles.add(profile);
} else if (!mProfiles.contains(profile)) {
mRemovedProfiles.remove(profile);
mProfiles.add(profile);
@@ -147,6 +149,8 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
} else if (profile instanceof MapProfile &&
newProfileState == BluetoothProfile.STATE_DISCONNECTED) {
profile.setPreferred(mDevice, false);
+ mProfiles.remove(profile);
+ mRemovedProfiles.add(profile);
} else if (mLocalNapRoleConnected && profile instanceof PanProfile &&
((PanProfile) profile).isLocalRoleNap(mDevice) &&
newProfileState == BluetoothProfile.STATE_DISCONNECTED) {
@@ -521,7 +525,29 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
* Refreshes the UI when framework alerts us of a UUID change.
*/
void onUuidChanged() {
+ Log.d(TAG, " onUuidChanged, mProfile Size " + mProfiles.size());
+ List<LocalBluetoothProfile> mPrevProfiles =
+ new ArrayList<LocalBluetoothProfile>();
+ mPrevProfiles.clear();
+ mPrevProfiles.addAll(mProfiles);
updateProfiles();
+ /*
+ * Check if new profiles are added
+ */
+ if ((mPrevProfiles.containsAll(mProfiles)) && (!mPrevProfiles.isEmpty())) {
+ Log.d(TAG,"UUID not udpated, returning");
+ mProfiles.clear();
+ mProfiles.addAll(mPrevProfiles);
+ return;
+ }
+ for (int i = 0; i<mProfiles.size(); ++i) {
+ if (!mPrevProfiles.contains(mProfiles.get(i))) {
+ mPrevProfiles.add(mProfiles.get(i));
+ }
+ }
+ mProfiles.clear();
+ mProfiles.addAll(mPrevProfiles);
+
ParcelUuid[] uuids = mDevice.getUuids();
long timeout = MAX_UUID_DELAY_FOR_AUTO_CONNECT;
@@ -851,7 +877,8 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
case BluetoothProfile.STATE_DISCONNECTED:
if (profile.isProfileReady()) {
- if (profile instanceof A2dpProfile) {
+ if ((profile instanceof A2dpProfile)||
+ (profile instanceof A2dpSinkProfile)){
a2dpNotConnected = true;
} else if (profile instanceof HeadsetProfile) {
headsetNotConnected = true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java
new file mode 100644
index 0000000..3c72927
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java
@@ -0,0 +1,162 @@
+/*
+*Copyright (c) 2013, 2015, The Linux Foundation. All rights reserved.
+*
+*Redistribution and use in source and binary forms, with or without
+*modification, are permitted provided that the following conditions are
+*met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothDun;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.util.Log;
+import java.util.HashMap;
+import java.util.List;
+
+import com.android.settingslib.R;
+
+/**
+ * DunServerProfile handles Bluetooth DUN server profile.
+ */
+final class DunServerProfile implements LocalBluetoothProfile {
+ private static final String TAG = "DunServerProfile";
+ private static boolean V = true;
+
+ private BluetoothDun mService;
+ private boolean mIsProfileReady;
+
+ static final String NAME = "DUN Server";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 11;
+
+ // These callbacks run on the main thread.
+ private final class DunServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothDun) proxy;
+ mIsProfileReady = true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady = false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ DunServerProfile(Context context) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ adapter.getProfileProxy(context, new DunServiceListener(),
+ BluetoothProfile.DUN);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return false;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ return false;
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ return true;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ return -1;
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ // ignore: isPreferred is always true for DUN
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_dun;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_dun_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_dun_profile_summary_connected;
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_network_pan;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy
+ (BluetoothProfile.DUN, mService);
+ mService = null;
+ } catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up DUN proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index f935f31..9c5abf3 100644..100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -162,6 +162,10 @@ public final class LocalBluetoothAdapter {
if (a2dp != null && a2dp.isA2dpPlaying()) {
return;
}
+ A2dpSinkProfile a2dpSink = mProfileManager.getA2dpSinkProfile();
+ if ((a2dpSink != null) && (a2dpSink.isA2dpPlaying())){
+ return;
+ }
}
if (mAdapter.startDiscovery()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 8f5e1f1..3876468 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -17,11 +17,14 @@
package com.android.settingslib.bluetooth;
import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothDun;
+import android.bluetooth.BluetoothPbap;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -32,6 +35,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import android.os.SystemProperties;
/**
* LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
@@ -73,11 +77,13 @@ public final class LocalBluetoothProfileManager {
private final BluetoothEventManager mEventManager;
private A2dpProfile mA2dpProfile;
+ private A2dpSinkProfile mA2dpSinkProfile;
private HeadsetProfile mHeadsetProfile;
private MapProfile mMapProfile;
private final HidProfile mHidProfile;
private OppProfile mOppProfile;
private final PanProfile mPanProfile;
+ private DunServerProfile mDunProfile;
private final PbapServerProfile mPbapProfile;
/**
@@ -121,9 +127,17 @@ public final class LocalBluetoothProfileManager {
addProfile(mMapProfile, MapProfile.NAME,
BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
- //Create PBAP server profile, but do not add it to list of profiles
- // as we do not need to monitor the profile as part of profile list
+ // enable DUN only if the property is set
+ if (SystemProperties.getBoolean("ro.bluetooth.dun", false) == true) {
+ mDunProfile = new DunServerProfile(context);
+ addProfile(mDunProfile, DunServerProfile.NAME,
+ BluetoothDun.ACTION_CONNECTION_STATE_CHANGED);
+ }
+
+ //Create PBAP server profile
mPbapProfile = new PbapServerProfile(context);
+ addProfile(mPbapProfile, PbapServerProfile.NAME,
+ BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
}
@@ -136,10 +150,10 @@ public final class LocalBluetoothProfileManager {
* @param uuids
*/
void updateLocalProfiles(ParcelUuid[] uuids) {
- // A2DP
+ // A2DP SRC
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) {
if (mA2dpProfile == null) {
- if(DEBUG) Log.d(TAG, "Adding local A2DP profile");
+ if(DEBUG) Log.d(TAG, "Adding local A2DP SRC profile");
mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
addProfile(mA2dpProfile, A2dpProfile.NAME,
BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
@@ -148,6 +162,17 @@ public final class LocalBluetoothProfileManager {
Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
}
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
+ if (mA2dpSinkProfile == null) {
+ if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
+ mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
+ BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
+ }
+ } else if (mA2dpSinkProfile != null) {
+ Log.w(TAG, "Warning: A2DP Sink profile was previously added but the UUID is now missing.");
+ }
+
// Headset / Handsfree
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) {
@@ -288,6 +313,10 @@ public final class LocalBluetoothProfileManager {
if (profile != null) {
return profile.isProfileReady();
}
+ profile = mA2dpSinkProfile;
+ if (profile != null) {
+ return profile.isProfileReady();
+ }
return false;
}
@@ -295,6 +324,13 @@ public final class LocalBluetoothProfileManager {
return mA2dpProfile;
}
+ A2dpSinkProfile getA2dpSinkProfile() {
+ if ((mA2dpSinkProfile != null)&&(mA2dpSinkProfile.isProfileReady()))
+ return mA2dpSinkProfile;
+ else
+ return null;
+ }
+
public HeadsetProfile getHeadsetProfile() {
return mHeadsetProfile;
}
@@ -345,6 +381,12 @@ public final class LocalBluetoothProfileManager {
removedProfiles.remove(mA2dpProfile);
}
+ if (BluetoothUuid.containsAnyUuid(uuids, A2dpSinkProfile.SRC_UUIDS) &&
+ mA2dpSinkProfile != null) {
+ profiles.add(mA2dpSinkProfile);
+ removedProfiles.remove(mA2dpSinkProfile);
+ }
+
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush) &&
mOppProfile != null) {
profiles.add(mOppProfile);
@@ -372,6 +414,13 @@ public final class LocalBluetoothProfileManager {
removedProfiles.remove(mMapProfile);
mMapProfile.setPreferred(device, true);
}
+
+ if ((mPbapProfile != null) &&
+ (mPbapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) {
+ profiles.add(mPbapProfile);
+ removedProfiles.remove(mPbapProfile);
+ mPbapProfile.setPreferred(device, true);
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
index 9e76933..fea7b34 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
@@ -88,8 +88,13 @@ public final class PbapServerProfile implements LocalBluetoothProfile {
}
public boolean disconnect(BluetoothDevice device) {
- if (mService == null) return false;
- return mService.disconnect();
+ if (mService == null || device == null) return false;
+
+ if (getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)
+ return mService.disconnect();
+
+ Log.d(TAG, "pbap server not connected to " + device.getAddress());
+ return false;
}
public int getConnectionStatus(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/cm/ShortcutPickHelper.java b/packages/SettingsLib/src/com/android/settingslib/cm/ShortcutPickHelper.java
new file mode 100644
index 0000000..a18a7e9
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/cm/ShortcutPickHelper.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2011 The CyanogenMod 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.settingslib.cm;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.Intent.ShortcutIconResource;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+
+import com.android.settingslib.R;
+import com.android.settingslib.cm.ShortcutPickHelper.AppExpandableAdapter.GroupInfo;
+
+public class ShortcutPickHelper {
+
+ private Activity mParent;
+ private AlertDialog mAlertDialog;
+ private OnPickListener mListener;
+ private PackageManager mPackageManager;
+ private static final int REQUEST_PICK_SHORTCUT = 100;
+ private static final int REQUEST_PICK_APPLICATION = 101;
+ private static final int REQUEST_CREATE_SHORTCUT = 102;
+ private int lastFragmentId;
+
+ public interface OnPickListener {
+ void shortcutPicked(String uri, String friendlyName, boolean isApplication);
+ }
+
+ public ShortcutPickHelper(Activity parent, OnPickListener listener) {
+ mParent = parent;
+ mPackageManager = mParent.getPackageManager();
+ mListener = listener;
+ }
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ switch (requestCode) {
+ case REQUEST_PICK_APPLICATION:
+ completeSetCustomApp(data);
+ break;
+ case REQUEST_CREATE_SHORTCUT:
+ completeSetCustomShortcut(data);
+ break;
+ case REQUEST_PICK_SHORTCUT:
+ processShortcut(data, REQUEST_PICK_APPLICATION, REQUEST_CREATE_SHORTCUT);
+ break;
+ }
+ } else {
+ mListener.shortcutPicked(null, null, false);
+ }
+ }
+
+ public void pickShortcut(String[] names, ShortcutIconResource[] icons, int fragmentId) {
+ Bundle bundle = new Bundle();
+
+ ArrayList<String> shortcutNames = new ArrayList<String>();
+ if (names != null) {
+ for (String s : names) {
+ shortcutNames.add(s);
+ }
+ }
+ shortcutNames.add(mParent.getString(R.string.profile_applist_title));
+ shortcutNames.add(mParent.getString(R.string.picker_activities));
+ bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
+
+ ArrayList<ShortcutIconResource> shortcutIcons = new ArrayList<ShortcutIconResource>();
+ if (icons != null) {
+ for (ShortcutIconResource s : icons) {
+ shortcutIcons.add(s);
+ }
+ }
+ shortcutIcons.add(ShortcutIconResource.fromContext(mParent, android.R.drawable.sym_def_app_icon));
+ shortcutIcons.add(ShortcutIconResource.fromContext(mParent, R.drawable.activities_icon));
+ bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);
+
+ Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
+ pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT));
+ pickIntent.putExtra(Intent.EXTRA_TITLE, mParent.getText(R.string.select_custom_app_title));
+ pickIntent.putExtras(bundle);
+ lastFragmentId = fragmentId;
+ startFragmentOrActivity(pickIntent, REQUEST_PICK_SHORTCUT);
+ }
+
+ private void startFragmentOrActivity(Intent pickIntent, int requestCode) {
+ if (lastFragmentId == 0) {
+ mParent.startActivityForResult(pickIntent, requestCode);
+ } else {
+ Fragment cFrag = mParent.getFragmentManager().findFragmentById(lastFragmentId);
+ if (cFrag != null) {
+ mParent.startActivityFromFragment(cFrag, pickIntent, requestCode);
+ }
+ }
+ }
+
+ private void processShortcut(final Intent intent, int requestCodeApplication, int requestCodeShortcut) {
+ // Handle case where user selected "Applications"
+ String applicationName = mParent.getString(R.string.profile_applist_title);
+ String application2name = mParent.getString(R.string.picker_activities);
+ String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+ if (applicationName != null && applicationName.equals(shortcutName)) {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
+ pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
+ startFragmentOrActivity(pickIntent, requestCodeApplication);
+ } else if (application2name != null && application2name.equals(shortcutName)){
+ final List<PackageInfo> pInfos = mPackageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES);
+ ExpandableListView appListView = new ExpandableListView(mParent);
+ AppExpandableAdapter appAdapter = new AppExpandableAdapter(pInfos, mParent);
+ appListView.setAdapter(appAdapter);
+ appListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
+ @Override
+ public boolean onChildClick(ExpandableListView parent, View v,
+ int groupPosition, int childPosition, long id) {
+ Intent shortIntent = new Intent(Intent.ACTION_MAIN);
+ String pkgName = ((GroupInfo)parent.getExpandableListAdapter().getGroup(groupPosition))
+ .info.packageName;
+ String actName = ((GroupInfo)parent.getExpandableListAdapter().getGroup(groupPosition))
+ .info.activities[childPosition].name;
+ shortIntent.setClassName(pkgName, actName);
+ completeSetCustomApp(shortIntent);
+ mAlertDialog.dismiss();
+ return true;
+ }
+ });
+ Builder builder = new Builder(mParent);
+ builder.setView(appListView);
+ mAlertDialog = builder.create();
+ mAlertDialog.setTitle(mParent.getString(R.string.select_custom_activity_title));
+ mAlertDialog.show();
+ mAlertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ mListener.shortcutPicked(null, null, false);
+ }
+ });
+ } else {
+ startFragmentOrActivity(intent, requestCodeShortcut);
+ }
+ }
+
+ public class AppExpandableAdapter extends BaseExpandableListAdapter {
+
+ ArrayList<GroupInfo> allList = new ArrayList<GroupInfo>();
+ final int groupPadding;
+
+ public class LabelCompare implements Comparator<GroupInfo>{
+ @Override
+ public int compare(GroupInfo item1, GroupInfo item2) {
+ String rank1 = item1.label.toLowerCase();
+ String rank2 = item2.label.toLowerCase();
+ int result = rank1.compareTo(rank2);
+ if(result == 0) {
+ return 0;
+ } else if(result < 0) {
+ return -1;
+ } else {
+ return +1;
+ }
+ }
+ }
+
+ class GroupInfo {
+ String label;
+ PackageInfo info;
+ GroupInfo (String l, PackageInfo p) {
+ label = l;
+ info = p;
+ }
+ }
+
+ public AppExpandableAdapter(List<PackageInfo> pInfos, Context context) {
+ for (PackageInfo i : pInfos) {
+ allList.add(new GroupInfo(i.applicationInfo.loadLabel(mPackageManager).toString(), i));
+ }
+ Collections.sort(allList, new LabelCompare());
+ groupPadding = context.getResources().getDimensionPixelSize(R.dimen.shortcut_picker_left_padding);
+ }
+
+ public String getChild(int groupPosition, int childPosition) {
+ return allList.get(groupPosition).info.activities[childPosition].name;
+ }
+
+ public long getChildId(int groupPosition, int childPosition) {
+ return childPosition;
+ }
+
+ public int getChildrenCount(int groupPosition) {
+ if (allList.get(groupPosition).info.activities != null) {
+ return allList.get(groupPosition).info.activities.length;
+ } else {
+ return 0;
+ }
+ }
+
+
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+ View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = View.inflate(mParent, android.R.layout.simple_list_item_1, null);
+ convertView.setPadding(groupPadding, 0, 0, 0);
+
+ }
+ TextView textView = (TextView)convertView.findViewById(android.R.id.text1);
+ textView.setText(getChild(groupPosition, childPosition).replaceFirst(allList.get(groupPosition).info.packageName + ".", ""));
+ return convertView;
+ }
+
+ public GroupInfo getGroup(int groupPosition) {
+ return allList.get(groupPosition);
+ }
+
+ public int getGroupCount() {
+ return allList.size();
+ }
+
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+ ViewGroup parent) {
+ if (convertView == null) {
+ convertView = View.inflate(mParent, android.R.layout.simple_list_item_1, null);
+ convertView.setPadding(groupPadding, 0, 0, 0);
+ }
+ TextView textView = (TextView)convertView.findViewById(android.R.id.text1);
+ textView.setText(getGroup(groupPosition).label);
+ return convertView;
+ }
+
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ }
+
+ private void completeSetCustomApp(Intent data) {
+ mListener.shortcutPicked(data.toUri(0), getFriendlyActivityName(data, false, mPackageManager), true);
+ }
+
+ private void completeSetCustomShortcut(Intent data) {
+ Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+ /* preserve shortcut name, we want to restore it later */
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
+ String appUri = intent.toUri(0);
+ appUri = appUri.replaceAll("com.android.contacts.action.QUICK_CONTACT", "android.intent.action.VIEW");
+ mListener.shortcutPicked(appUri, getFriendlyShortcutName(intent, mPackageManager), false);
+ }
+
+ private static String getFriendlyActivityName(Intent intent, boolean labelOnly, PackageManager packageManager) {
+ ActivityInfo ai = intent.resolveActivityInfo(packageManager, PackageManager.GET_ACTIVITIES);
+ String friendlyName = null;
+ if (ai != null) {
+ friendlyName = ai.loadLabel(packageManager).toString();
+ if (friendlyName == null && !labelOnly) {
+ friendlyName = ai.name;
+ }
+ }
+ return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0);
+ }
+
+ private static String getFriendlyShortcutName(Intent intent, PackageManager packageManager) {
+ String activityName = getFriendlyActivityName(intent, true, packageManager);
+ String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+
+ if (activityName != null && name != null) {
+ return activityName + ": " + name;
+ }
+ return name != null ? name : intent.toUri(0);
+ }
+
+ public static String getFriendlyNameForUri(String uri, PackageManager packageManager) {
+ if (uri == null) {
+ return null;
+ }
+
+ try {
+ Intent intent = Intent.parseUri(uri, 0);
+ if (Intent.ACTION_MAIN.equals(intent.getAction())) {
+ return getFriendlyActivityName(intent, false, packageManager);
+ }
+ return getFriendlyShortcutName(intent, packageManager);
+ } catch (URISyntaxException e) {
+ }
+
+ return uri;
+ }
+} \ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 632a867..f8bcc27 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -124,6 +124,8 @@ public class AccessPoint implements Comparable<AccessPoint> {
private Object mTag;
+ public boolean foundInScanResult = false;
+
public AccessPoint(Context context, Bundle savedState) {
mContext = context;
mConfig = savedState.getParcelable(KEY_CONFIG);
@@ -336,6 +338,10 @@ public class AccessPoint implements Comparable<AccessPoint> {
return str;
}
+ public int getNetworkId() {
+ return networkId;
+ }
+
public String getConfigName() {
if (mConfig != null && mConfig.isPasspoint()) {
return mConfig.providerFriendlyName;
@@ -640,12 +646,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
} else if (config != null) {
return matches(config);
}
- else {
- // Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID.
- // (Note that we only do this if the WifiConfiguration explicitly equals INVALID).
- // TODO: Handle hex string SSIDs.
- return ssid.equals(removeDoubleQuotes(info.getSSID()));
- }
+ return false;
}
public boolean isSaved() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index c28288e..fe8f757 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -180,7 +180,9 @@ public class WifiTracker {
if (mWifiManager.isWifiEnabled()) {
mScanner.resume();
}
- mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ if (!mWorkHandler.hasMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS)) {
+ mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ }
}
/**
@@ -320,6 +322,7 @@ public class WifiTracker {
continue;
}
AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
+ accessPoint.foundInScanResult = false;
if (mLastInfo != null && mLastNetworkInfo != null) {
if (config.isPasspoint() == false) {
accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
@@ -352,6 +355,7 @@ public class WifiTracker {
boolean found = false;
for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
if (accessPoint.update(result)) {
+ accessPoint.foundInScanResult = true;
found = true;
break;
}
@@ -505,7 +509,9 @@ public class WifiTracker {
} else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) ||
WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) ||
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
- mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ if (!mWorkHandler.hasMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS)) {
+ mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ }
} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
@@ -513,7 +519,9 @@ public class WifiTracker {
mMainHandler.sendEmptyMessage(MainHandler.MSG_CONNECTED_CHANGED);
- mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ if (!mWorkHandler.hasMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS)) {
+ mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ }
mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
.sendToTarget();
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
index 2b833b2..9c7bcb3 100644
--- a/packages/SettingsProvider/Android.mk
+++ b/packages/SettingsProvider/Android.mk
@@ -7,7 +7,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) \
src/com/android/providers/settings/EventLogTags.logtags
LOCAL_JAVA_LIBRARIES := telephony-common ims-common
-
+LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.sdk
LOCAL_PACKAGE_NAME := SettingsProvider
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SettingsProvider/res/mipmap-hdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/mipmap-hdpi/ic_launcher_settings.png
index a8ccc89..252e6b4 100644
--- a/packages/SettingsProvider/res/mipmap-hdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/mipmap-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/mipmap-mdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/mipmap-mdpi/ic_launcher_settings.png
index 69709a8..d2ecee9 100644
--- a/packages/SettingsProvider/res/mipmap-mdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/mipmap-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/mipmap-xhdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/mipmap-xhdpi/ic_launcher_settings.png
index c3adce61..fa8c813 100644
--- a/packages/SettingsProvider/res/mipmap-xhdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/mipmap-xhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/mipmap-xxhdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/mipmap-xxhdpi/ic_launcher_settings.png
index 52fe978..3fa69e9 100644
--- a/packages/SettingsProvider/res/mipmap-xxhdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/mipmap-xxhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/mipmap-xxxhdpi/ic_launcher_settings.png b/packages/SettingsProvider/res/mipmap-xxxhdpi/ic_launcher_settings.png
index 6b92795..72946b7 100644
--- a/packages/SettingsProvider/res/mipmap-xxxhdpi/ic_launcher_settings.png
+++ b/packages/SettingsProvider/res/mipmap-xxxhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/res/values-ast-rES/strings.xml b/packages/SettingsProvider/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..e4b0106
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ast-rES/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources>
+ <string name="app_label">Axustes d\'almacenamientu</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-be/strings.xml b/packages/SettingsProvider/res/values-be/strings.xml
new file mode 100644
index 0000000..2c3d4d7
--- /dev/null
+++ b/packages/SettingsProvider/res/values-be/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources>
+ <string name="app_label">Захоўванне налад</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ku/strings.xml b/packages/SettingsProvider/res/values-ku/strings.xml
new file mode 100644
index 0000000..097b8b7
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ku/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources>
+ <string name="app_label">ڕێکخستنی بیرگە</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-lb/strings.xml b/packages/SettingsProvider/res/values-lb/strings.xml
new file mode 100644
index 0000000..c55b311
--- /dev/null
+++ b/packages/SettingsProvider/res/values-lb/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources>
+ <string name="app_label">Astellungsspäicher</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ug/strings.xml b/packages/SettingsProvider/res/values-ug/strings.xml
new file mode 100644
index 0000000..28b9541
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ug/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources>
+ <string name="app_label">ساقلىغۇچ تەڭشىكى</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values/customize.xml b/packages/SettingsProvider/res/values/customize.xml
new file mode 100644
index 0000000..9085d2d
--- /dev/null
+++ b/packages/SettingsProvider/res/values/customize.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2014, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<resources>
+
+ <!-- Time format,default vlaue is 24 : 24 format,other value is 12 format -->
+ <string name="def_time_format" translatable="false"></string>
+
+ <!-- Date format,yyyy-MM-dd: 2013/07/30; MM-dd-yyyy:07/30/2013; dd-MM-yyyy:30/07/2013 -->
+ <string name="def_date_format" translatable="false"></string>
+
+ <!--
+ Default Input Method, its value is from inputmethod's package name and main class name
+ such as "com.android.inputmethod.pinyin/.PinyinIME"
+ -->
+ <string name="def_input_method" translatable="false"></string>
+
+ <!-- Default for Settings.Global.DATA_ROAMING -->
+ <bool name="def_enable_data_roaming">false</bool>
+
+ <!-- Default for Settings.Global.MOBILE_DATA -->
+ <bool name="def_enable_mobile_data">true</bool>
+
+ <!--
+ Default Enable InputMethods, its value is from inputmethod's package name and main class name
+ such as "com.android.inputmethod.pinyin/.PinyinIME" ;This is a string
+ containing the IDs of all enabled input methods, each ID separated by ':'.
+ -->
+ <string name="def_enable_input_methods" translatable="false"></string>
+
+ <!-- enable accessiblity or not,1:enable;0:disable -->
+ <integer name="def_enable_accessiblity" translatable="false">0</integer>
+
+ <!-- for enable accessiblity services,split by ":" ,example "com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService" -->
+ <string name="def_enable_accessiblity_services" translatable="false"></string>
+
+</resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index ef32c19..76b7d6f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -29,12 +29,20 @@
<bool name="def_auto_time">true</bool>
<bool name="def_auto_time_zone">true</bool>
<bool name="def_accelerometer_rotation">true</bool>
+ <!-- Bitmask of allowed display rotation angles:
+ ROTATION_0_MODE: 1
+ ROTATION_90_MODE: 2
+ ROTATION_180_MODE: 4
+ ROTATION_270_MODE: 8
+ Default to 0, 90, 270. -->
+ <integer name="def_accelerometer_rotation_angles">11</integer>
<!-- Default screen brightness, from 0 to 255. 102 is 40%. -->
<integer name="def_screen_brightness">102</integer>
<bool name="def_screen_brightness_automatic_mode">false</bool>
<fraction name="def_window_animation_scale">100%</fraction>
<fraction name="def_window_transition_scale">100%</fraction>
<bool name="def_haptic_feedback">true</bool>
+ <bool name="def_dozeEnabledByDefault">false</bool>
<bool name="def_bluetooth_on">false</bool>
<bool name="def_wifi_display_on">false</bool>
@@ -178,6 +186,9 @@
>0 is milliseconds of screen-off time after which battery sounds will not play -->
<integer name="def_low_battery_sound_timeout">0</integer>
+ <!-- Default for Settings.System.VIBRATE_WHEN_RINGING enabled -->
+ <bool name="def_vibrate_when_ringing_enabled">false</bool>
+
<!-- Initial value for the Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS setting,
which is a comma separated list of packages that no longer need confirmation
for immersive mode.
@@ -193,6 +204,9 @@
<!-- Default for Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS -->
<bool name="def_lock_screen_allow_private_notifications">true</bool>
+ <!-- Default for Settings.Global.SEND_ACTION_APP_ERROR -->
+ <integer name="def_send_action_app_error">0</integer>
+
<!-- Default for Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, 1==on -->
<integer name="def_heads_up_enabled">1</integer>
@@ -213,4 +227,13 @@
<!-- Default for Settings.Secure.NFC_PAYMENT_COMPONENT -->
<string name="def_nfc_payment_component"></string>
+
+ <!-- Default for Settings.System.STATUS_BAR_NOTIF_COUNT. -->
+ <integer name="def_notif_count">0</integer>
+
+ <!-- Default protected sms originating address values of Settings.Secure.PROTECTED_SMS_ADDRESSES -->
+ <string-array name="def_protected_sms_list_values"></string-array>
+
+ <!-- Default for Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED -->
+ <integer name="def_captive_portal_detection_enabled" translatable="false">1</integer>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5a14967..f5f8ce6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.res.ThemeConfig;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -40,6 +41,7 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -51,11 +53,13 @@ import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
+import cyanogenmod.providers.CMSettings;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -76,11 +80,16 @@ class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "SettingsProvider";
private static final String DATABASE_NAME = "settings.db";
+ private static final int TYPE_NONE = -1;
+
// Please, please please. If you update the database version, check to make sure the
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 118;
+ private static final int DATABASE_VERSION = 125;
+
+ //Maximum number of phones
+ private static final int MAX_PHONE_COUNT = 3;
private Context mContext;
private int mUserHandle;
@@ -717,6 +726,10 @@ class DatabaseHelper extends SQLiteOpenHelper {
Secure.LOCK_PATTERN_ENABLED,
Secure.LOCK_PATTERN_VISIBLE,
Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+ CMSettings.Secure.LOCK_PASS_TO_SECURITY_VIEW,
+ Secure.LOCK_PATTERN_SIZE,
+ Secure.LOCK_DOTS_VISIBLE,
+ Secure.LOCK_SHOW_ERROR_PATH,
"lockscreen.password_type",
"lockscreen.lockoutattemptdeadline",
"lockscreen.patterneverchosen",
@@ -1388,6 +1401,7 @@ class DatabaseHelper extends SQLiteOpenHelper {
if (upgradeVersion == 88) {
if (mUserHandle == UserHandle.USER_OWNER) {
db.beginTransaction();
+ SQLiteStatement stmt = null;
try {
String[] settingsToMove = {
Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
@@ -1407,7 +1421,6 @@ class DatabaseHelper extends SQLiteOpenHelper {
Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
Settings.Global.CONNECTIVITY_CHANGE_DELAY,
- Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED,
Settings.Global.CAPTIVE_PORTAL_SERVER,
Settings.Global.NSD_ON,
Settings.Global.SET_INSTALL_LOCATION,
@@ -1423,9 +1436,16 @@ class DatabaseHelper extends SQLiteOpenHelper {
Settings.Global.DEFAULT_DNS_SERVER,
};
moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+
+ stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+ + " VALUES(?,?);");
+ loadIntegerSetting(stmt, Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED,
+ R.integer.def_captive_portal_detection_enabled);
+ stmt.close();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
+ if (stmt != null) stmt.close();
}
}
upgradeVersion = 89;
@@ -1871,9 +1891,34 @@ class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 113;
}
- // We skipped 114 to handle a merge conflict with the introduction of theater mode.
+ // We skipped 114 to handle a merge conflict with the introduction of theater mode. Except
+ // in CM we didn't, soooooo...
+ if (upgradeVersion < 114) {
+ // Artificially bump our upgrade version to handle
+ // migration path from cm-11.0 to cm-12.0
+ // without this, heads up would never work if
+ // a user did not wipe data
+ /** CM-13, this option was moved to CMSettings, artificially bump, skip default load.**/
+// upgradeHeadsUpSettingFromNone(db);
+// upgradeDeviceNameFromNone(db);
+
+ // Removal of back/recents is no longer supported
+ // due to pinned apps
+ db.beginTransaction();
+ try {
+ db.execSQL("DELETE FROM system WHERE name='"
+ + CMSettings.System.NAV_BUTTONS + "'");
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ upgradeVersion = 114;
+ }
if (upgradeVersion < 115) {
+ moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE,
+ new String[] { CMSettings.Secure.STATS_COLLECTION }, true);
if (mUserHandle == UserHandle.USER_OWNER) {
db.beginTransaction();
SQLiteStatement stmt = null;
@@ -1892,6 +1937,8 @@ class DatabaseHelper extends SQLiteOpenHelper {
}
if (upgradeVersion < 116) {
+ moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE,
+ new String[]{Settings.Secure.VOLUME_LINK_NOTIFICATION}, true);
if (mUserHandle == UserHandle.USER_OWNER) {
db.beginTransaction();
SQLiteStatement stmt = null;
@@ -1920,10 +1967,44 @@ class DatabaseHelper extends SQLiteOpenHelper {
} finally {
db.endTransaction();
}
+
+ // CM11 used "holo" as a system default theme. For CM12 and up its been
+ // switched to "system". So change all "holo" references in themeConfig to "system"
+ final String NAME_THEME_CONFIG = "themeConfig";
+ Cursor c = null;
+ try {
+ String[] projection = new String[]{"value"};
+ String selection = "name=?";
+ String[] selectionArgs = new String[] { NAME_THEME_CONFIG };
+ c = db.query(TABLE_SECURE, projection, selection,
+ selectionArgs, null, null, null);
+ if (c != null && c.moveToFirst()) {
+ String jsonConfig = c.getString(0);
+ if (jsonConfig != null) {
+ jsonConfig = jsonConfig.replace(
+ "\"holo\"", '"' + ThemeConfig.SYSTEM_DEFAULT + '"');
+
+ // Now update the entry
+ SQLiteStatement stmt = db.compileStatement(
+ "UPDATE " + TABLE_SECURE + " SET value = ? "
+ + " WHERE name = ?");
+ stmt.bindString(1, jsonConfig);
+ stmt.bindString(2, NAME_THEME_CONFIG);
+ stmt.execute();
+ }
+ }
+ } finally {
+ if (c != null) c.close();
+ }
upgradeVersion = 117;
}
if (upgradeVersion < 118) {
+ String[] settingsToMove = new String[] {
+ CMSettings.Secure.QS_SHOW_BRIGHTNESS_SLIDER,
+ };
+ moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE,
+ settingsToMove, true);
// Reset rotation-lock-for-accessibility on upgrade, since it now hides the display
// setting.
db.beginTransaction();
@@ -1940,6 +2021,110 @@ class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 118;
}
+ /** CM-13 CHANGES -- THIS IS TO SUPPORT LEGACY UPGRADES, DO NOT ADD ANY NEW DEFAULTS HERE
+ * INSTEAD UTILIZE THE CMSETTINGS PROVIDER
+ */
+ if (upgradeVersion == 119) {
+ /** CM-13, this option was moved to CMSettings, artificially bump, skip default load.**/
+// db.beginTransaction();
+// SQLiteStatement stmt = null;
+// try {
+// stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value) VALUES(?,?);");
+// loadDefaultThemeSettings(stmt);
+// db.setTransactionSuccessful();
+// } finally {
+// db.endTransaction();
+// if (stmt != null) stmt.close();
+// }
+ upgradeVersion = 120;
+ }
+
+ if (upgradeVersion < 121) {
+ String[] settingsToMove = CMSettings.Secure.NAVIGATION_RING_TARGETS;
+
+ moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE,
+ settingsToMove, true);
+ upgradeVersion = 121;
+ }
+
+ if (upgradeVersion < 122) {
+ /** CM-13, this option was moved to CMSettings, artificially bump, skip default load.**/
+// db.beginTransaction();
+// SQLiteStatement stmt = null;
+// try {
+// stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+// + " VALUES(?,?);");
+// loadBooleanSetting(stmt, CMSettings.Secure.ADVANCED_MODE,
+// com.android.internal.R.bool.config_advancedSettingsMode);
+// db.setTransactionSuccessful();
+// } finally {
+// db.endTransaction();
+// if (stmt != null) stmt.close();
+// }
+ upgradeVersion = 122;
+ }
+
+ if (upgradeVersion < 123) {
+ // only the owner has access to global table, so we need to check that here
+ if (mUserHandle == UserHandle.USER_OWNER) {
+ String[] globalToSecure = new String[] { CMSettings.Secure.POWER_MENU_ACTIONS };
+
+ moveSettingsToNewTable(db, TABLE_GLOBAL, TABLE_SECURE, globalToSecure, true);
+ }
+
+ String[] systemToSecure = new String[] {
+ CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR,
+ CMSettings.Secure.KEYBOARD_BRIGHTNESS,
+ CMSettings.Secure.BUTTON_BRIGHTNESS,
+ CMSettings.Secure.BUTTON_BACKLIGHT_TIMEOUT
+ };
+ moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, systemToSecure, true);
+
+ upgradeVersion = 123;
+ }
+
+ if (upgradeVersion < 124) {
+ // Migrate from cm-12.0 if there is no entry from cm-11.0
+ /** CM-13, this option was moved to CMSettings, artificially bump, skip default load.**/
+// db.beginTransaction();
+// SQLiteStatement stmt = null;
+// try {
+// stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+// + " VALUES(?,?);");
+// int quickPulldown = getIntValueFromSystem(db,
+// CMSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN,
+// R.integer.def_qs_quick_pulldown);
+// loadSetting(stmt, CMSettings.System.QS_QUICK_PULLDOWN, quickPulldown);
+// db.setTransactionSuccessful();
+// } finally {
+// db.endTransaction();
+// if (stmt != null) stmt.close();
+// }
+ upgradeVersion = 124;
+ }
+
+ if (upgradeVersion < 125) {
+ // Force enable advanced settings if the overlay defaults to true
+ /** CM-13, this option was moved to CMSettings, artificially bump, skip default load.**/
+// if (mContext.getResources().getBoolean(
+// com.android.internal.R.bool.config_advancedSettingsMode)) {
+// db.beginTransaction();
+// SQLiteStatement stmt = null;
+// try {
+// stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
+// + " VALUES(?,?);");
+// loadBooleanSetting(stmt, CMSettings.Secure.ADVANCED_MODE,
+// com.android.internal.R.bool.config_advancedSettingsMode);
+// db.setTransactionSuccessful();
+// } finally {
+// db.endTransaction();
+// if (stmt != null) stmt.close();
+// }
+// }
+ upgradeVersion = 125;
+ }
+ /** END CM-13 CHANGES */
+
/*
* IMPORTANT: Do not add any more upgrade steps here as the global,
* secure, and system settings are no longer stored in a database
@@ -2065,7 +2250,7 @@ class DatabaseHelper extends SQLiteOpenHelper {
try {
LockPatternUtils lpu = new LockPatternUtils(mContext);
List<LockPatternView.Cell> cellPattern =
- LockPatternUtils.stringToPattern(lockPattern);
+ LockPatternUtils.stringToPattern(lockPattern, lpu.getLockPatternSize());
lpu.saveLockPattern(cellPattern, null, UserHandle.USER_OWNER);
} catch (IllegalArgumentException e) {
// Don't want corrupted lock pattern to hang the reboot process
@@ -2334,12 +2519,26 @@ class DatabaseHelper extends SQLiteOpenHelper {
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ " VALUES(?,?);");
- loadSetting(stmt, Settings.System.VIBRATE_WHEN_RINGING, vibrateWhenRinging ? 1 : 0);
+ if (mContext.getResources().getBoolean(R.bool.def_vibrate_when_ringing_enabled)) {
+ loadSetting(stmt, Settings.System.VIBRATE_WHEN_RINGING, 1);
+ } else {
+ loadSetting(stmt, Settings.System.VIBRATE_WHEN_RINGING, vibrateWhenRinging ? 1 : 0);
+ }
} finally {
if (stmt != null) stmt.close();
}
}
+ private void loadProtectedSmsSetting(SQLiteStatement stmt) {
+ String[] regAddresses = mContext.getResources()
+ .getStringArray(R.array.def_protected_sms_list_values);
+ if (regAddresses.length > 0) {
+ loadSetting(stmt,
+ Settings.Secure.PROTECTED_SMS_ADDRESSES,
+ TextUtils.join("|", regAddresses));
+ }
+ }
+
private void loadSettings(SQLiteDatabase db) {
loadSystemSettings(db);
loadSecureSettings(db);
@@ -2380,6 +2579,9 @@ class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
R.bool.def_accelerometer_rotation);
+ loadIntegerSetting(stmt, Settings.System.ACCELEROMETER_ROTATION_ANGLES,
+ R.integer.def_accelerometer_rotation_angles);
+
loadDefaultHapticSettings(stmt);
loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
@@ -2397,6 +2599,17 @@ class DatabaseHelper extends SQLiteOpenHelper {
*
* See: SettingsProvider.UpgradeController#onUpgradeLocked
*/
+
+ //LEGACY CAF CHANGES
+ if (!TextUtils.isEmpty(mContext.getResources().getString(R.string.def_time_format))) {
+ loadStringSetting(stmt, Settings.System.TIME_12_24,
+ R.string.def_time_format);
+ }
+
+ if (!TextUtils.isEmpty(mContext.getResources().getString(R.string.def_date_format))) {
+ loadStringSetting(stmt, Settings.System.DATE_FORMAT,
+ R.string.def_date_format);
+ }
} finally {
if (stmt != null) stmt.close();
}
@@ -2446,7 +2659,7 @@ class DatabaseHelper extends SQLiteOpenHelper {
// Allow mock locations default, based on build
loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
- "1".equals(SystemProperties.get("ro.allow.mock.location")) ? 1 : 0);
+ "1".equals(SystemProperties.get("persist.env.c.allow.enable")) ? 1 : 0);
loadSecure35Settings(stmt);
@@ -2497,6 +2710,8 @@ class DatabaseHelper extends SQLiteOpenHelper {
com.android.internal.R.string.config_dreamsDefaultComponent);
loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
com.android.internal.R.string.config_dreamsDefaultComponent);
+ loadBooleanSetting(stmt, Settings.Secure.DOZE_ENABLED,
+ R.bool.def_dozeEnabledByDefault);
loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
R.bool.def_accessibility_display_magnification_enabled);
@@ -2536,6 +2751,24 @@ class DatabaseHelper extends SQLiteOpenHelper {
*
* See: SettingsProvider.UpgradeController#onUpgradeLocked
*/
+
+ //LEGACY CAF CHANGES
+ if (!TextUtils.isEmpty(mContext.getResources().getString(R.string.def_input_method))) {
+ loadStringSetting(stmt, Settings.Secure.DEFAULT_INPUT_METHOD,
+ R.string.def_input_method);
+ }
+
+ if (!TextUtils.isEmpty(mContext.getResources().getString(
+ R.string.def_enable_input_methods))) {
+ loadStringSetting(stmt, Settings.Secure.ENABLED_INPUT_METHODS,
+ R.string.def_enable_input_methods);
+ }
+
+ // for accessibility enabled
+ loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_ENABLED,
+ R.integer.def_enable_accessiblity);
+ loadStringSetting(stmt, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ R.string.def_enable_accessiblity_services);
} finally {
if (stmt != null) stmt.close();
}
@@ -2606,10 +2839,8 @@ class DatabaseHelper extends SQLiteOpenHelper {
RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
// Data roaming default, based on build
- loadSetting(stmt, Settings.Global.DATA_ROAMING,
- "true".equalsIgnoreCase(
- SystemProperties.get("ro.com.android.dataroaming",
- "false")) ? 1 : 0);
+ loadBooleanSetting(stmt, Settings.Global.DATA_ROAMING,
+ R.bool.def_enable_data_roaming);
loadBooleanSetting(stmt, Settings.Global.DEVICE_PROVISIONED,
R.bool.def_device_provisioned);
@@ -2629,10 +2860,20 @@ class DatabaseHelper extends SQLiteOpenHelper {
}
// Mobile Data default, based on build
- loadSetting(stmt, Settings.Global.MOBILE_DATA,
- "true".equalsIgnoreCase(
- SystemProperties.get("ro.com.android.mobiledata",
- "true")) ? 1 : 0);
+ loadBooleanSetting(stmt, Settings.Global.MOBILE_DATA,
+ R.bool.def_enable_mobile_data);
+
+ int phoneCount = TelephonyManager.getDefault().getPhoneCount();
+ // SUB specific flags for Multisim devices
+ for (int phoneId = 0; phoneId < MAX_PHONE_COUNT; phoneId++) {
+ // Mobile Data default, based on build
+ loadBooleanSetting(stmt, Settings.Global.MOBILE_DATA + phoneId,
+ R.bool.def_enable_mobile_data);
+
+ // Data roaming default, based on build
+ loadBooleanSetting(stmt, Settings.Global.DATA_ROAMING + phoneId,
+ R.bool.def_enable_data_roaming);
+ }
loadBooleanSetting(stmt, Settings.Global.NETSTATS_ENABLED,
R.bool.def_netstats_enabled);
@@ -2668,6 +2909,8 @@ class DatabaseHelper extends SQLiteOpenHelper {
R.string.def_car_undock_sound);
loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
R.string.def_wireless_charging_started_sound);
+ loadIntegerSetting(stmt, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED,
+ R.integer.def_dock_audio_media_enabled);
loadIntegerSetting(stmt, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED,
R.integer.def_dock_audio_media_enabled);
@@ -2684,13 +2927,36 @@ class DatabaseHelper extends SQLiteOpenHelper {
// Set the preferred network mode to target desired value or Default
// value defined in RILConstants
- int type;
- type = RILConstants.PREFERRED_NETWORK_MODE;
- loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type);
+ final String defVal = SystemProperties.get("ro.telephony.default_network", "");
+ final String[] defNetworkSettings = defVal.split(",");
+ final String[] networkSettings = new String[phoneCount];
+ boolean error = defNetworkSettings.length != phoneCount;
+
+ for (int i = 0; i < phoneCount; i++) {
+ if (i < defNetworkSettings.length) {
+ try {
+ networkSettings[i] = String.valueOf(
+ Integer.parseInt(defNetworkSettings[i]));
+ } catch (NumberFormatException ex) {
+ networkSettings[i] = String.valueOf(RILConstants.PREFERRED_NETWORK_MODE);
+ error = true;
+ }
+ } else {
+ networkSettings[i] = String.valueOf(RILConstants.PREFERRED_NETWORK_MODE);
+ error = true;
+ }
+ }
+
+ if (error) {
+ Log.w(TAG, "Invalid ro.telephony.default_network: " + defVal);
+ }
+
+ loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, TextUtils.join(",",
+ networkSettings));
// Set the preferred cdma subscription source to target desired value or default
// value defined in CdmaSubscriptionSourceManager
- type = SystemProperties.getInt("ro.telephony.default_cdma_sub",
+ int type = SystemProperties.getInt("ro.telephony.default_cdma_sub",
CdmaSubscriptionSourceManager.PREFERRED_CDMA_SUBSCRIPTION);
loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type);
@@ -2705,11 +2971,13 @@ class DatabaseHelper extends SQLiteOpenHelper {
loadSetting(stmt, Settings.Global.DEVICE_NAME, getDefaultDeviceName());
+ loadIntegerSetting(stmt, Settings.Global.SEND_ACTION_APP_ERROR,
+ R.integer.def_send_action_app_error);
+
loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED,
R.bool.def_guest_user_enabled);
loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED,
ImsConfig.FeatureValueConstants.ON);
-
/*
* IMPORTANT: Do not add any more upgrade steps here as the global,
* secure, and system settings are no longer stored in a database
@@ -2717,6 +2985,8 @@ class DatabaseHelper extends SQLiteOpenHelper {
*
* See: SettingsProvider.UpgradeController#onUpgradeLocked
*/
+ loadIntegerSetting(stmt, Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED,
+ R.integer.def_captive_portal_detection_enabled);
} finally {
if (stmt != null) stmt.close();
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 2e96f18..ffe7623 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -36,8 +36,10 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
+import cyanogenmod.providers.CMSettings;
import libcore.io.IoUtils;
import java.io.BufferedOutputStream;
@@ -261,13 +263,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
// Now build the canonical config key paralleling the WifiConfiguration semantics
final String key;
if (types.get(KeyMgmt.WPA_PSK)) {
- key = bareSsid + KeyMgmt.strings[KeyMgmt.WPA_PSK];
+ key = bareSsid + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK];
} else if (types.get(KeyMgmt.WPA_EAP) || types.get(KeyMgmt.IEEE8021X)) {
- key = bareSsid + KeyMgmt.strings[KeyMgmt.WPA_EAP];
+ key = bareSsid + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP];
} else if (hasWepKey) {
- key = bareSsid + "WEP"; // hardcoded this way in WifiConfiguration
+ key = bareSsid + "-WEP"; // hardcoded this way in WifiConfiguration
} else {
- key = bareSsid + KeyMgmt.strings[KeyMgmt.NONE];
+ key = bareSsid + "-" + KeyMgmt.strings[KeyMgmt.NONE];
}
return key;
}
@@ -902,6 +904,37 @@ public class SettingsBackupAgent extends BackupAgentHelper {
Log.d(TAG, "Restored setting: " + destination + " : "+ key + "=" + value);
}
}
+
+ restoreCMSetting(cachedEntries);
+ }
+
+ private void restoreCMSetting(Map<String, String> cachedEntries) {
+ ContentValues cmSettingsValues = new ContentValues();
+ ContentResolver cr = getContentResolver();
+ for (String key : cachedEntries.keySet()) {
+ Uri uri = null;
+ if (ArrayUtils.contains(CMSettings.System.LEGACY_SYSTEM_SETTINGS, key)) {
+ uri = CMSettings.System.CONTENT_URI;
+ } else if (ArrayUtils.contains(CMSettings.Secure.LEGACY_SECURE_SETTINGS, key)) {
+ uri = CMSettings.Secure.CONTENT_URI;
+ } else if (ArrayUtils.contains(CMSettings.Global.LEGACY_GLOBAL_SETTINGS, key)) {
+ uri = CMSettings.Global.CONTENT_URI;
+ }
+ if (uri != null) {
+ String value = cachedEntries.get(key);
+ cmSettingsValues.clear();
+ cmSettingsValues.put(Settings.NameValueTable.NAME, key);
+ cmSettingsValues.put(Settings.NameValueTable.VALUE, value);
+ try {
+ cr.insert(uri, cmSettingsValues);
+ if (DEBUG) {
+ Log.d(TAG, "Restored cm setting: " + key + " : " + key + "=" + value);
+ }
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed to migrate " + key + " due to " + e.toString());
+ }
+ }
+ }
}
/**
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index aa00f7d..5c871ca 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -22,10 +22,12 @@ import android.app.AppOpsManager;
import android.app.backup.BackupManager;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -50,6 +52,7 @@ import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
+import android.preference.PreferenceManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -72,7 +75,9 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+import com.android.providers.settings.SettingsState.BaseSetting;
import com.android.providers.settings.SettingsState.Setting;
+import cyanogenmod.providers.CMSettings;
/**
* <p>
@@ -124,6 +129,8 @@ public class SettingsProvider extends ContentProvider {
private static final String TABLE_BOOKMARKS = "bookmarks";
private static final String TABLE_ANDROID_METADATA = "android_metadata";
+ private static final String HAS_REPLAYED_DEFAULTS_FROM_L = "has_replayed_defaults_from_L";
+
// The set of removed legacy tables.
private static final Set<String> REMOVED_LEGACY_TABLES = new ArraySet<>();
static {
@@ -226,17 +233,17 @@ public class SettingsProvider extends ContentProvider {
final int requestingUserId = getRequestingUserId(args);
switch (method) {
case Settings.CALL_METHOD_GET_GLOBAL: {
- Setting setting = getGlobalSetting(name);
+ BaseSetting setting = getGlobalSetting(name);
return packageValueForCallResult(setting);
}
case Settings.CALL_METHOD_GET_SECURE: {
- Setting setting = getSecureSetting(name, requestingUserId);
+ BaseSetting setting = getSecureSetting(name, requestingUserId);
return packageValueForCallResult(setting);
}
case Settings.CALL_METHOD_GET_SYSTEM: {
- Setting setting = getSystemSetting(name, requestingUserId);
+ BaseSetting setting = getSystemSetting(name, requestingUserId);
return packageValueForCallResult(setting);
}
@@ -294,7 +301,10 @@ public class SettingsProvider extends ContentProvider {
switch (args.table) {
case TABLE_GLOBAL: {
if (args.name != null) {
- Setting setting = getGlobalSetting(args.name);
+ BaseSetting setting = getGlobalSetting(args.name);
+ if (CMSettings.Global.shouldInterceptSystemProvider(args.name)) {
+ return forwardedQuery(setting, normalizedProjection, args.table);
+ }
return packageSettingForQuery(setting, normalizedProjection);
} else {
return getAllGlobalSettings(projection);
@@ -304,7 +314,10 @@ public class SettingsProvider extends ContentProvider {
case TABLE_SECURE: {
final int userId = UserHandle.getCallingUserId();
if (args.name != null) {
- Setting setting = getSecureSetting(args.name, userId);
+ BaseSetting setting = getSecureSetting(args.name, userId);
+ if (CMSettings.Secure.shouldInterceptSystemProvider(args.name)) {
+ return forwardedQuery(setting, normalizedProjection, args.table);
+ }
return packageSettingForQuery(setting, normalizedProjection);
} else {
return getAllSecureSettings(userId, projection);
@@ -314,7 +327,10 @@ public class SettingsProvider extends ContentProvider {
case TABLE_SYSTEM: {
final int userId = UserHandle.getCallingUserId();
if (args.name != null) {
- Setting setting = getSystemSetting(args.name, userId);
+ BaseSetting setting = getSystemSetting(args.name, userId);
+ if (CMSettings.System.shouldInterceptSystemProvider(args.name)) {
+ return forwardedQuery(setting, normalizedProjection, args.table);
+ }
return packageSettingForQuery(setting, normalizedProjection);
} else {
return getAllSystemSettings(userId, projection);
@@ -604,16 +620,32 @@ public class SettingsProvider extends ContentProvider {
}
}
- private Setting getGlobalSetting(String name) {
+ private BaseSetting getGlobalSetting(String name) {
if (DEBUG) {
Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
}
// Get the value.
+ BaseSetting setting;
synchronized (mLock) {
- return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
+ setting = mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
UserHandle.USER_OWNER, name);
}
+
+ // If CMSettingsProvider owns this key, override the value
+ if (CMSettings.Global.shouldInterceptSystemProvider(name)) {
+ final ContentResolver cr = getContext().getContentResolver();
+ final String value = CMSettings.Global.
+ getStringForUser(cr, name, UserHandle.USER_OWNER);
+
+ if (setting == null) {
+ setting = new BaseSetting(name, value, null);
+ } else {
+ setting.update(value, null);
+ }
+ }
+
+ return setting;
}
private boolean updateGlobalSetting(String name, String value, int requestingUserId) {
@@ -650,6 +682,20 @@ public class SettingsProvider extends ContentProvider {
return false;
}
+ // If CMSettingsProvider wants to own this key, let it.
+ if (CMSettings.Global.shouldInterceptSystemProvider(name)) {
+ switch (operation) {
+ case MUTATION_OPERATION_INSERT:
+ case MUTATION_OPERATION_UPDATE:
+ final ContentResolver cr = getContext().getContentResolver();
+ return CMSettings.Global.putStringForUser(cr, name, value,
+ UserHandle.USER_OWNER);
+ case MUTATION_OPERATION_DELETE:
+ // unsupported
+ return false;
+ }
+ }
+
// Perform the mutation.
synchronized (mLock) {
switch (operation) {
@@ -713,7 +759,7 @@ public class SettingsProvider extends ContentProvider {
}
}
- private Setting getSecureSetting(String name, int requestingUserId) {
+ private BaseSetting getSecureSetting(String name, int requestingUserId) {
if (DEBUG) {
Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
}
@@ -730,10 +776,25 @@ public class SettingsProvider extends ContentProvider {
}
// Get the value.
+ BaseSetting setting;
synchronized (mLock) {
- return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ setting = mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
owningUserId, name);
}
+
+ // If CMSettingsProvider owns this key, override the value
+ if (CMSettings.Secure.shouldInterceptSystemProvider(name)) {
+ final ContentResolver cr = getContext().getContentResolver();
+ final String value = CMSettings.Secure.getStringForUser(cr, name, owningUserId);
+
+ if (setting == null) {
+ setting = new BaseSetting(name, value, null);
+ } else {
+ setting.update(value, null);
+ }
+ }
+
+ return setting;
}
private boolean insertSecureSetting(String name, String value, int requestingUserId) {
@@ -788,6 +849,19 @@ public class SettingsProvider extends ContentProvider {
return updateLocationProvidersAllowedLocked(value, owningUserId);
}
+ // If CMSettingsProvider wants to own this key, let it.
+ if (CMSettings.Secure.shouldInterceptSystemProvider(name)) {
+ switch (operation) {
+ case MUTATION_OPERATION_INSERT:
+ case MUTATION_OPERATION_UPDATE:
+ final ContentResolver cr = getContext().getContentResolver();
+ return CMSettings.Secure.putStringForUser(cr, name, value, owningUserId);
+ case MUTATION_OPERATION_DELETE:
+ // unsupported
+ return false;
+ }
+ }
+
// Mutate the value.
synchronized (mLock) {
switch (operation) {
@@ -847,7 +921,7 @@ public class SettingsProvider extends ContentProvider {
}
}
- private Setting getSystemSetting(String name, int requestingUserId) {
+ private BaseSetting getSystemSetting(String name, int requestingUserId) {
if (DEBUG) {
Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")");
}
@@ -859,10 +933,25 @@ public class SettingsProvider extends ContentProvider {
final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
// Get the value.
+ BaseSetting setting;
synchronized (mLock) {
- return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
+ setting = mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
owningUserId, name);
}
+
+ // If CMSettingsProvider owns this key, override the value
+ if (CMSettings.System.shouldInterceptSystemProvider(name)) {
+ final ContentResolver cr = getContext().getContentResolver();
+ final String value = CMSettings.System.getStringForUser(cr, name, owningUserId);
+
+ if (setting == null) {
+ setting = new BaseSetting(name, value, null);
+ } else {
+ setting.update(value, null);
+ }
+ }
+
+ return setting;
}
private boolean insertSystemSetting(String name, String value, int requestingUserId) {
@@ -916,6 +1005,19 @@ public class SettingsProvider extends ContentProvider {
return false;
}
+ // If CMSettingsProvider wants to own this key, let it.
+ if (CMSettings.System.shouldInterceptSystemProvider(name)) {
+ switch (operation) {
+ case MUTATION_OPERATION_INSERT:
+ case MUTATION_OPERATION_UPDATE:
+ final ContentResolver cr = getContext().getContentResolver();
+ return CMSettings.System.putStringForUser(cr, name, value, owningUserId);
+ case MUTATION_OPERATION_DELETE:
+ // unsupported
+ return false;
+ }
+ }
+
// Mutate the value.
synchronized (mLock) {
switch (operation) {
@@ -1010,6 +1112,11 @@ public class SettingsProvider extends ContentProvider {
return;
}
+ if (CMSettings.System.shouldInterceptSystemProvider(name)) {
+ // this setting will be forwarded to CMSettingsProvider
+ return;
+ }
+
switch (operation) {
case MUTATION_OPERATION_INSERT:
// Insert updates.
@@ -1107,7 +1214,7 @@ public class SettingsProvider extends ContentProvider {
// skip prefix
value = value.substring(1);
- Setting settingValue = getSecureSetting(
+ BaseSetting settingValue = getSecureSetting(
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
@@ -1187,7 +1294,7 @@ public class SettingsProvider extends ContentProvider {
"get/set setting for user", null);
}
- private static Bundle packageValueForCallResult(Setting setting) {
+ private static Bundle packageValueForCallResult(BaseSetting setting) {
if (setting == null) {
return NULL_SETTING;
}
@@ -1215,7 +1322,31 @@ public class SettingsProvider extends ContentProvider {
throw new IllegalArgumentException("Invalid URI:" + uri);
}
- private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) {
+ private MatrixCursor forwardedQuery(BaseSetting setting, String[] projection, String table) {
+ if (setting == null) {
+ return new MatrixCursor(projection, 0);
+ }
+ MatrixCursor cursor = new MatrixCursor(projection, 1);
+ switch (table) {
+ case TABLE_SYSTEM:
+ setting.update(CMSettings.System.getString(getContext().getContentResolver(),
+ setting.getName()), setting.getPackageName());
+ break;
+ case TABLE_GLOBAL:
+ setting.update(CMSettings.Global.getString(getContext().getContentResolver(),
+ setting.getName()), setting.getPackageName());
+ break;
+ case TABLE_SECURE:
+ setting.update(CMSettings.Secure.getString(getContext().getContentResolver(),
+ setting.getName()), setting.getPackageName());
+ break;
+
+ }
+ appendSettingToCursor(cursor, setting);
+ return cursor;
+ }
+
+ private static MatrixCursor packageSettingForQuery(BaseSetting setting, String[] projection) {
if (setting == null) {
return new MatrixCursor(projection, 0);
}
@@ -1240,7 +1371,7 @@ public class SettingsProvider extends ContentProvider {
return projection;
}
- private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
+ private static void appendSettingToCursor(MatrixCursor cursor, BaseSetting setting) {
final int columnCount = cursor.getColumnCount();
String[] values = new String[columnCount];
@@ -1856,6 +1987,10 @@ public class SettingsProvider extends ContentProvider {
private final class UpgradeController {
private static final int SETTINGS_VERSION = 123;
+ /**
+ * This is the 12.1 database version (DO NOT INCREMENT)
+ */
+ private static final int CM_SETTINGS_DB_VERSION = 125;
private final int mUserId;
@@ -1869,11 +2004,27 @@ public class SettingsProvider extends ContentProvider {
SettingsRegistry.SETTINGS_TYPE_SECURE, mUserId);
// Try an update from the current state.
- final int oldVersion = secureSettings.getVersionLocked();
+ final int oldVersion = secureSettings.getVersionLocked(); //125
final int newVersion = SETTINGS_VERSION;
// If up do date - done.
- if (oldVersion == newVersion) {
+ //
+ // CYANOGENMOD
+ // We moved our settings out to another settings provider (CMSettingsProvider)
+ // however, we still have a problem of being a few versions ahead of AOSP.
+ // We could approach this in the manner we have previously, and bump the version
+ // to replay the defaults for specific os upgrade changes and have that maintenance
+ // overhead forever OR we can take the approach below:
+ //
+ // Logic as follows:
+ // Until version 125 of this "DATABASE"
+ // force replay AOSP defaults as they get introduced
+ // once 125 is hit, we never have to maintain this again.
+ if ((oldVersion == newVersion || oldVersion == CM_SETTINGS_DB_VERSION)) {
+ if (oldVersion == CM_SETTINGS_DB_VERSION && !hasReplayedDefaultsFromL()) {
+ forceReplayAOSPDefaults(mUserId);
+ setDefaultsReplayedFromLFlag();
+ }
return;
}
@@ -1913,6 +2064,18 @@ public class SettingsProvider extends ContentProvider {
systemSettings.setVersionLocked(newVersion);
}
+ private boolean hasReplayedDefaultsFromL() {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(getContext());
+ return sharedPreferences.getBoolean(HAS_REPLAYED_DEFAULTS_FROM_L, false);
+ }
+
+ private void setDefaultsReplayedFromLFlag() {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(getContext());
+ sharedPreferences.edit().putBoolean(HAS_REPLAYED_DEFAULTS_FROM_L, true).apply();
+ }
+
private SettingsState getGlobalSettingsLocked() {
return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
}
@@ -2022,6 +2185,42 @@ public class SettingsProvider extends ContentProvider {
// Return the current version.
return currentVersion;
}
+
+ private void forceReplayAOSPDefaults(int userId) {
+ // v119: Reset zen + ringer mode.
+ if (userId == UserHandle.USER_OWNER) {
+ final SettingsState globalSettings = getGlobalSettingsLocked();
+ globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
+ Integer.toString(Settings.Global.ZEN_MODE_OFF),
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER,
+ Integer.toString(AudioManager.RINGER_MODE_NORMAL),
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ // v120: Add double tap to wake setting.
+ SettingsState secureSettings = getSecureSettingsLocked(userId);
+ secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE,
+ getContext().getResources().getBoolean(
+ R.bool.def_double_tap_to_wake) ? "1" : "0",
+ SettingsState.SYSTEM_PACKAGE_NAME);
+
+ // Version 122: allow OEMs to set a default payment component in resources.
+ // Note that we only write the default if no default has been set;
+ // if there is, we just leave the default at whatever it currently is.
+ String defaultComponent = (getContext().getResources().getString(
+ R.string.def_nfc_payment_component));
+ Setting currentSetting = secureSettings.getSettingLocked(
+ Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
+ if (defaultComponent != null && !defaultComponent.isEmpty() &&
+ currentSetting == null) {
+ secureSettings.insertSettingLocked(
+ Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
+ defaultComponent,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 95d7772..8a25c65 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -552,22 +552,21 @@ final class SettingsState {
}
}
- public final class Setting {
- private String name;
- private String value;
- private String packageName;
- private String id;
+ public static class BaseSetting {
+ protected String name;
+ protected String value;
+ protected String packageName;
+ protected String id;
- public Setting(String name, String value, String packageName) {
- init(name, value, packageName, String.valueOf(mNextId++));
+ protected BaseSetting() {
+ // for sub classes
}
- public Setting(String name, String value, String packageName, String id) {
- mNextId = Math.max(mNextId, Long.valueOf(id) + 1);
- init(name, value, packageName, id);
+ public BaseSetting(String name, String value, String packageName) {
+ init(name, value, packageName, null);
}
- private void init(String name, String value, String packageName, String id) {
+ protected void init(String name, String value, String packageName, String id) {
this.name = name;
this.value = value;
this.packageName = packageName;
@@ -596,6 +595,33 @@ final class SettingsState {
}
this.value = value;
this.packageName = packageName;
+ return true;
+ }
+ }
+
+ public final class Setting extends BaseSetting {
+
+ public Setting(String name, String value, String packageName) {
+ init(name, value, packageName, String.valueOf(mNextId++));
+ }
+
+ public Setting(String name, String value, String packageName, String id) {
+ mNextId = Math.max(mNextId, Long.valueOf(id) + 1);
+ init(name, value, packageName, id);
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public boolean update(String value, String packageName) {
+ if (Objects.equal(value, this.value)) {
+ return false;
+ }
+ this.value = value;
+ this.packageName = packageName;
this.id = String.valueOf(mNextId++);
return true;
}
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
index e453cf5..2cd1f29 100644
--- a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
@@ -76,7 +76,7 @@ public class SharedStorageAgent extends FullBackupAgent {
if (slash > 0) {
try {
int i = Integer.parseInt(relpath.substring(0, slash));
- if (i <= mVolumes.length) {
+ if (i < mVolumes.length) {
outFile = new File(mVolumes[i].getPath(), relpath.substring(slash + 1));
if (DEBUG) Slog.i(TAG, " => " + outFile.getAbsolutePath());
} else {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index b9daf59..3c90414 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -48,6 +48,8 @@
<uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="cyanogenmod.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="cyanogenmod.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<!-- Development tool permissions granted to the shell. -->
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
@@ -98,7 +100,6 @@
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<uses-permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"/>
- <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.CHANGE_APP_IDLE_STATE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS" />
@@ -107,6 +108,7 @@
<uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
<uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
+ <uses-permission android:name="cyanogenmod.permission.ACCESS_THEME_MANAGER" />
<application android:label="@string/app_label">
<provider
@@ -142,6 +144,7 @@
android:name=".BugreportReceiver"
android:permission="android.permission.DUMP">
<intent-filter>
+ <action android:name="android.intent.action.BUGREPORT_STARTED" />
<action android:name="android.intent.action.BUGREPORT_FINISHED" />
</intent-filter>
</receiver>
diff --git a/packages/Shell/res/values-ast-rES/strings.xml b/packages/Shell/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..0590fbb
--- /dev/null
+++ b/packages/Shell/res/values-ast-rES/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Shell</string>
+ <string name="bugreport_finished_title">Informe de fallu capturáu</string>
+ <string name="bugreport_finished_text" product="watch">Esliza a esquierda pa compartir l\'informe de fallu</string>
+ <string name="bugreport_finished_text" product="default">Toca pa compartir l\'informe de fallu</string>
+ <string name="bugreport_confirm">Los informes de fallos contienen datos de los distintos ficheros de rexistru del sistema, incluyida información personal y privada. Comparte los informes de fallos namái con aplicaciones y usuarios nos que confíes.</string>
+ <string name="bugreport_confirm_repeat">Amosar esti mensaxe la próxima vegada</string>
+</resources>
diff --git a/packages/Shell/res/values-be/strings.xml b/packages/Shell/res/values-be/strings.xml
new file mode 100644
index 0000000..3b598d4
--- /dev/null
+++ b/packages/Shell/res/values-be/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Абалонка</string>
+ <string name="bugreport_finished_title">Справаздача пра збой захавана</string>
+ <string name="bugreport_finished_text" product="watch">Правядзіце пальцам налева, каб падзяліцца сваёй справаздачай пра збой</string>
+ <string name="bugreport_finished_text" product="default">Націсніце, каб падзяліцца сваёй справаздачай пра збой</string>
+ <string name="bugreport_confirm">Справаздача пра памылку ўтрымлівае дадзеныя з файлаў сістэмнай гiсторыi, у тым ліку персанальную і прыватную інфармацыю. Дзялiцеся справаздачамi пра памылкі толькi з праверанымi карыстальнiкамi i праграмамі.</string>
+ <string name="bugreport_confirm_repeat"> Паказваць гэта паведамленне у наступны раз</string>
+</resources>
diff --git a/packages/Shell/res/values-ku/strings.xml b/packages/Shell/res/values-ku/strings.xml
new file mode 100644
index 0000000..191c498
--- /dev/null
+++ b/packages/Shell/res/values-ku/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">توێکڵ</string>
+ <string name="bugreport_finished_title">ڕاپۆرتی کەموکورتیەکان وێنەگیرا</string>
+ <string name="bugreport_finished_text" product="default">ده‌ستی لێده‌ بۆ په‌رشکردنی ڕاپۆرتی که‌موکوڕییه‌کانت</string>
+ <string name="bugreport_confirm">ڕاپۆرتى که‌موکوڕییه‌کان داتا له‌ خۆ ده‌گرێت لە تۆمارى سيستم فايلی جۆراوجۆره‌وه‌، هەروەك زانياريى تايبەت و كەسى. تۆماری که‌موکوڕییه‌کان ته‌نها له‌گه‌ڵ ئه‌و که‌س و به‌رنامانه‌دا په‌رش بکه‌ که‌ متمانه‌ت پێیانه‌.</string>
+ <string name="bugreport_confirm_repeat">جاری داهاتوو ئه‌م په‌یامه‌ پیشان بده‌</string>
+</resources>
diff --git a/packages/Shell/res/values-lb/strings.xml b/packages/Shell/res/values-lb/strings.xml
new file mode 100644
index 0000000..54cd3d8
--- /dev/null
+++ b/packages/Shell/res/values-lb/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Shell</string>
+ <string name="bugreport_finished_title">Feelerbericht opgefaangen</string>
+ <string name="bugreport_finished_text" product="watch">No lénks wësche fir de Feelerbericht ze deelen</string>
+ <string name="bugreport_finished_text" product="default">Drécken, fir de Feelerbericht ze deelen</string>
+ <string name="bugreport_confirm">Feelerberichter hunn Daten aus de verschiddene Protokollfichiere vum System, dorënner perséinlech a privat Informatiounen. Deel just Feelerberichter mat Appen a Leit deenen s du traus.</string>
+ <string name="bugreport_confirm_repeat">Weis dëse Message déi nächst Kéier un</string>
+</resources>
diff --git a/packages/Shell/res/values-ug/strings.xml b/packages/Shell/res/values-ug/strings.xml
new file mode 100644
index 0000000..eee708f
--- /dev/null
+++ b/packages/Shell/res/values-ug/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+ <string name="app_label">Shell</string>
+ <string name="bugreport_finished_title">خاتالىق دوكلاتى تۇتۇلدى</string>
+ <string name="bugreport_finished_text" product="default">چېكىپلا خاتالىق دوكلاتىنى ھەمبەھىرلىيەلەيسىز</string>
+ <string name="bugreport_confirm">خاتالىق دوكلاتىدىكى سانلىق مەلۇماتلار سىستېمىنىڭ ھەر قايسى خاتىرە ھۆججەتلىرىدىن كەلگەن بولۇپ، ئۇنىڭدا شەخسىي ئۇچۇر ۋە شەخسىيەت ئۇچۇرلىرى بار. پەقەت سىز ئىشىنىدىغان ئەپ ۋە ئىشلەتكۈچى بىلەنلا خاتالىق دوكلاتىنى ھەمبەھىرلىنىڭ.</string>
+ <string name="bugreport_confirm_repeat">بۇ ئۇچۇرنى كېيىنكى قېتىم كۆرسەت</string>
+</resources>
diff --git a/packages/Shell/res/values/cm_strings.xml b/packages/Shell/res/values/cm_strings.xml
new file mode 100644
index 0000000..0d81dd6
--- /dev/null
+++ b/packages/Shell/res/values/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The CyanogenMod 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.
+-->
+<resources>
+ <!-- Text to let user know a bug report is currently being collected -->
+ <string name="notification_bug_report_active_title">Collecting bug report\u2026</string>
+ <string name="notification_bug_report_active_text">Please wait a few minutes</string>
+</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index d83b516..6e39111 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -65,6 +65,8 @@ public class BugreportReceiver extends BroadcastReceiver {
private static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
private static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
+ public static final String ACTION_BUGREPORT_STARTED = "android.intent.action.BUGREPORT_STARTED";
+
/**
* Always keep the newest 8 bugreport files; 4 reports and 4 screenshots are
* roughly 17MB of disk space.
@@ -79,6 +81,19 @@ public class BugreportReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final Configuration conf = context.getResources().getConfiguration();
+ if (ACTION_BUGREPORT_STARTED.equals(intent.getAction())) {
+ Notification.Builder builder = new Notification.Builder(context)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setOngoing(true)
+ .setProgress(0, 0, true)
+ .setContentTitle(context
+ .getString(R.string.notification_bug_report_active_title))
+ .setContentText(context
+ .getString(R.string.notification_bug_report_active_text));
+ NotificationManager.from(context).notify(TAG, 0, builder.build());
+ return;
+ }
+
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 51fea2a..d9c9a3a 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,8 +6,13 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/systemui/EventLogTags.logtags
-LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
+LOCAL_STATIC_JAVA_LIBRARIES := Keyguard \
+ org.cyanogenmod.platform.internal \
+ android-support-v7-palette \
+ android-support-v4
+
LOCAL_JAVA_LIBRARIES := telephony-common
+LOCAL_FULL_LIBS_MANIFEST_FILES := $(LOCAL_PATH)/AndroidManifest_cm.xml
LOCAL_PACKAGE_NAME := SystemUI
LOCAL_CERTIFICATE := platform
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 80f4d4c..52cb1d9 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -41,7 +41,6 @@
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
@@ -50,6 +49,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_BLUETOOTH_AVRCP_CT_DATA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
@@ -135,6 +135,15 @@
android:protectionLevel="signature" />
<uses-permission android:name="com.android.systemui.permission.SELF" />
+ <!-- LiveDisplay -->
+ <uses-permission android:name="android.permission.HARDWARE_ABSTRACTION_ACCESS" />
+
+ <!-- Weather -->
+ <uses-permission android:name="com.cyanogenmod.lockclock.permission.READ_WEATHER" />
+
+ <!-- blur surface -->
+ <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
@@ -397,6 +406,20 @@
</intent-filter>
</activity>
+ <activity
+ android:name=".settings.NotificationBrightnessDialog"
+ android:label="@string/quick_settings_brightness_dialog_title"
+ android:theme="@android:style/Theme.DeviceDefault.Dialog"
+ android:finishOnCloseSystemDialogs="true"
+ android:launchMode="singleInstance"
+ android:excludeFromRecents="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.SHOW_NOTIFICATION_BRIGHTNESS_DIALOG" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<!-- Doze with notifications, run in main sysui process for every user -->
<service
android:name=".doze.DozeService"
@@ -411,5 +434,6 @@
<action android:name="com.android.systemui.action.CLEAR_TUNER" />
</intent-filter>
</receiver>
+
</application>
</manifest>
diff --git a/packages/SystemUI/AndroidManifest_cm.xml b/packages/SystemUI/AndroidManifest_cm.xml
new file mode 100644
index 0000000..c84910d
--- /dev/null
+++ b/packages/SystemUI/AndroidManifest_cm.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2015 The CyanogenMod Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui">
+
+ <uses-permission android:name="cyanogenmod.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="cyanogenmod.permission.WRITE_SECURE_SETTINGS" />
+ <!-- Quick Settings Tile Listener -->
+ <uses-permission android:name="cyanogenmod.permission.BIND_CUSTOM_TILE_LISTENER_SERVICE"/>
+
+ <!-- Development shortcut -->
+ <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
+ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
+
+ <!-- Sync tile -->
+ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
+
+ <!-- Publish dynamic tiles -->
+ <uses-permission android:name="cyanogenmod.permission.PUBLISH_CUSTOM_TILE" />
+
+ <uses-permission android:name="cyanogenmod.permission.HARDWARE_ABSTRACTION_ACCESS" />
+
+ <!-- Visualizer -->
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <!-- Performance Manager -->
+ <uses-permission android:name="cyanogenmod.permission.PERFORMANCE_ACCESS" />
+
+ <application>
+ <provider android:name=".cm.SpamMessageProvider"
+ android:permission="android.permission.INTERACT_ACROSS_USERS_FULL"
+ android:exported="true"
+ android:authorities="com.cyanogenmod.spam" />
+
+ <activity
+ android:name=".cm.LockscreenShortcutsActivity"
+ android:icon="@drawable/tuner"
+ android:label="@string/lockscreen_targets_message"
+ android:theme="@android:style/Theme.Material.Settings"
+ android:process=":cmsettings"
+ android:exported="true" />
+
+ <activity android:name=".tuner.TunerActivity$DemoModeActivity"
+ android:icon="@drawable/tuner"
+ android:theme="@android:style/Theme.Material.Settings"
+ android:label="@string/demo_mode"
+ android:process=":tuner"
+ android:exported="true"
+ android:permission="android.permission.STATUS_BAR" />
+
+ <activity android:name=".tuner.TunerActivity$StatusBarIconActivity"
+ android:icon="@drawable/tuner"
+ android:theme="@android:style/Theme.Material.Settings"
+ android:label="@string/status_bar"
+ android:process=":tuner"
+ android:exported="true"
+ android:permission="android.permission.STATUS_BAR" />
+ </application>
+</manifest>
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_longtomed.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_longtomed.xml
new file mode 100644
index 0000000..1479734
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_longtomed.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="250"
+android:propertyName="rotation"
+android:valueFrom="-180"
+android:valueTo="-90"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_longtoshort.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_longtoshort.xml
new file mode 100644
index 0000000..4bc7324
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_longtoshort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="400"
+android:propertyName="rotation"
+android:valueFrom="-180"
+android:valueTo="0"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort.xml
new file mode 100644
index 0000000..ea2e135
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="400"
+android:propertyName="rotation"
+android:valueFrom="-90"
+android:valueTo="0"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort_reverse.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort_reverse.xml
new file mode 100644
index 0000000..4b252cb
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_medtoshort_reverse.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="250"
+android:propertyName="rotation"
+android:valueFrom="-90"
+android:valueTo="0"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_shorttolong.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_shorttolong.xml
new file mode 100644
index 0000000..72103e4
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_shorttolong.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="400"
+android:propertyName="rotation"
+android:valueFrom="0"
+android:valueTo="-180"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_staymed.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_staymed.xml
new file mode 100644
index 0000000..186179c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_staymed.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="250"
+android:propertyName="rotation"
+android:valueFrom="-90"
+android:valueTo="-90"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_tolong.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_tolong.xml
new file mode 100644
index 0000000..6fa46e9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_tolong.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="250"
+android:propertyName="rotation"
+android:valueFrom="-90"
+android:valueTo="-180"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_screen_timeout_tomed.xml b/packages/SystemUI/res/anim/ic_qs_screen_timeout_tomed.xml
new file mode 100644
index 0000000..7ee79ba
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_screen_timeout_tomed.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+
+android:duration="250"
+android:propertyName="rotation"
+android:valueFrom="0"
+android:valueTo="-90"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_cross_anim.xml b/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_cross_anim.xml
new file mode 100755
index 0000000..4e5fbe5
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_cross_anim.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+<objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M 4.4 3 L 4.7 3.3"
+ android:valueTo="M 4.4 3 L 21 19.6"
+ android:valueType="pathType"
+ android:interpolator="@interpolator/ic_hotspot_disable_cross_1_pathdata_interpolator" />
+<objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_mask_anim.xml b/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_mask_anim.xml
new file mode 100755
index 0000000..977caec
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_mask_anim.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+<objectAnimator
+ android:duration="350"
+ android:propertyName="pathData"
+ android:valueFrom="M24,24H0V0h1.4l2.9,3l1.4-1.4L4.2,0H24V24z"
+ android:valueTo="M24,24H0V0h1.4l19.8,19.8l1.4-1.4L4.2,0H24V24z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_root_anim.xml b/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_root_anim.xml
new file mode 100755
index 0000000..4e63d73
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_qs_tile_delete_disable_root_anim.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+<objectAnimator
+ android:duration="350"
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.3"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_mini_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_mini_settings.png
new file mode 100755
index 0000000..4759a1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_mini_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
index a93916f..5bde6ef 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add.png
new file mode 100644
index 0000000..66e0c12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_land.png
new file mode 100644
index 0000000..63da6d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_side.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_side.png
new file mode 100644
index 0000000..956ebe4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_add_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_side.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_side.png
new file mode 100644
index 0000000..0d12637
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_left.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_left.png
new file mode 100755
index 0000000..ad9ae23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_right.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_right.png
new file mode 100755
index 0000000..5324ad9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_right.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big.png
new file mode 100644
index 0000000..5b30293
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big_land.png
new file mode 100644
index 0000000..99413a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_big_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_side.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_side.png
new file mode 100644
index 0000000..24ad426
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search.png
new file mode 100644
index 0000000..b31c2c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_land.png
new file mode 100644
index 0000000..5ad767c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_side.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_side.png
new file mode 100644
index 0000000..f8e9b08
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_search_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_image.png
deleted file mode 100644
index 7b0fcc7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.png
deleted file mode 100644
index 73e9c96..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_mini_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_mini_settings.png
new file mode 100755
index 0000000..878169b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_mini_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
index 7ae6079..c8c8102 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add.png
new file mode 100644
index 0000000..cf9fda6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_land.png
new file mode 100644
index 0000000..ec8dfa4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_side.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_side.png
new file mode 100644
index 0000000..6231b21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_add_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_side.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_side.png
new file mode 100644
index 0000000..5854b38
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_left.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_left.png
new file mode 100755
index 0000000..1f08402
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_right.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_right.png
new file mode 100755
index 0000000..7626499
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_right.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big.png
new file mode 100644
index 0000000..c2dd22b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big_land.png
new file mode 100644
index 0000000..4345844
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_big_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_side.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_side.png
new file mode 100644
index 0000000..286bd00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search.png
new file mode 100644
index 0000000..885c130
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_land.png
new file mode 100644
index 0000000..2487dfb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_side.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_side.png
new file mode 100644
index 0000000..0ff41f5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_search_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_image.png
deleted file mode 100644
index a02e21c..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.png
deleted file mode 100644
index 4af2617..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_mini_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_mini_settings.png
new file mode 100755
index 0000000..84807e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_mini_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-xhdpi/ic_notification_overlay.9.png
index aae807b..77eeda1 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add.png
new file mode 100644
index 0000000..75ba404
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_land.png
new file mode 100644
index 0000000..30f4415
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_side.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_side.png
new file mode 100644
index 0000000..916fe9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_add_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_side.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_side.png
new file mode 100644
index 0000000..7504d32
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_left.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_left.png
new file mode 100755
index 0000000..4183e20
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_right.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_right.png
new file mode 100755
index 0000000..ab1c7b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_right.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big.png
new file mode 100644
index 0000000..83f8d78
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big_land.png
new file mode 100644
index 0000000..fe74ae9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_big_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_side.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_side.png
new file mode 100644
index 0000000..db596cc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search.png
new file mode 100644
index 0000000..007faa3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_land.png
new file mode 100644
index 0000000..e997c37
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_side.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_side.png
new file mode 100644
index 0000000..69f1a0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_search_side.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_image.png
deleted file mode 100644
index 24bdbb6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.png
deleted file mode 100644
index 6ecd2d3..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_mini_settings.png b/packages/SystemUI/res/drawable-xxhdpi/ic_mini_settings.png
new file mode 100755
index 0000000..78bbc25
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_mini_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notification_overlay.9.png
index fa7de0e..ea09774 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add.png
new file mode 100644
index 0000000..af182a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add_land.png
new file mode 100644
index 0000000..cb601f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_add_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_left.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_left.png
new file mode 100644
index 0000000..08cbeef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_right.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_right.png
new file mode 100644
index 0000000..db4e888
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_ime_right.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big.png
new file mode 100644
index 0000000..9664962
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big_land.png
new file mode 100644
index 0000000..bb677dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_big_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search.png
new file mode 100644
index 0000000..9fcc72d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search_land.png
new file mode 100644
index 0000000..b2ae541
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_search_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.png
deleted file mode 100644
index 5e733ef..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.png
deleted file mode 100644
index ecc2c83..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_mini_settings.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_mini_settings.png
new file mode 100755
index 0000000..6a6536e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_mini_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/cid.xml b/packages/SystemUI/res/drawable/cid.xml
new file mode 100644
index 0000000..614a050
--- /dev/null
+++ b/packages/SystemUI/res/drawable/cid.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <group>
+ <path
+ android:name="torso"
+ android:pathData="M35.616,28.128l-4.185-11.17c-0.37-0.966-1.233-1.561-2.11-1.862c-0.638-0.219-1.94-0.47-4.366-0.59h-1.91 c-2.427,0.12-3.729,0.371-4.367,0.59c-0.877,0.301-1.74,0.896-2.11,1.862l-4.185,11.17c-0.496,1.122,0.396,1.59,1.148,1.385 c0.809-0.221,1.518-0.506,2.084-1.866c0.309-0.742,2.818-7.124,2.818-7.124l-1.542,27.45c0,0,0.603,0,2.095,0 c0.967,0,2.209-1.01,2.419-3.358l0.931-12.818h0.709h0.104h0.562h0.241h0.005h0.085h0.005h0.241h0.562h0.104h0.709l0.931,12.818 c0.21,2.348,1.452,3.358,2.419,3.358c1.492,0,2.095,0,2.095,0l-1.542-27.45c0,0,2.509,6.382,2.818,7.124 c0.566,1.36,1.275,1.645,2.084,1.866C35.221,29.718,36.112,29.25,35.616,28.128Z M24,25.331c-1.817,0-3.295-1.478-3.295-3.295 c0-1.817,1.478-3.295,3.295-3.295c1.817,0,3.295,1.478,3.295,3.295C27.295,23.853,25.817,25.331,24,25.331z M26.616,22.036 c0,1.443-1.174,2.616-2.616,2.616c-1.443,0-2.616-1.174-2.616-2.616c0-1.442,1.174-2.616,2.616-2.616 C25.442,19.42,26.616,20.593,26.616,22.036z"
+ android:fillColor="#FFFFFF" />
+ <path
+ android:name="head"
+ android:pathData="M29.081,3.012l0.962-2.35c0.096-0.235-0.016-0.503-0.251-0.599c-0.235-0.096-0.503,0.016-0.599,0.251l-0.997,2.435 c-1.1-0.252-2.503-0.348-4.18-0.348v0.006h0V2.4c-0.219,0-0.432,0.002-0.642,0.006h-0.001c-1.396,0.023-2.581,0.124-3.537,0.343 l-0.997-2.435c-0.096-0.235-0.364-0.347-0.599-0.251c-0.235,0.096-0.347,0.364-0.251,0.599l0.962,2.35 c-1.277,0.483-1.955,1.3-1.955,2.612v2.752V9.09v0.784c0,2.411,2.284,3.151,6.377,3.218v0.004h0.254 c0.128,0.001,0.258,0.002,0.389,0.002v-0.002h0v0.002c0.131,0,0.261-0.001,0.389-0.002h0.018c4.242-0.042,6.613-0.764,6.613-3.221 V9.09V8.376V5.624C31.037,4.311,30.358,3.495,29.081,3.012Z M20.407,9.78c-1.16,0-2.1-0.94-2.1-2.1c0-1.16,0.94-2.1,2.1-2.1 c1.16,0,2.1,0.94,2.1,2.1C22.507,8.84,21.567,9.78,20.407,9.78z M24.237,11.303h-0.443c-0.326,0-0.591-0.264-0.591-0.591 c0-0.012,0.003-0.024,0.004-0.036h1.617c0.001,0.012,0.004,0.023,0.004,0.036C24.828,11.039,24.563,11.303,24.237,11.303z M27.625,9.78c-1.16,0-2.1-0.94-2.1-2.1c0-1.16,0.94-2.1,2.1-2.1c1.16,0,2.1,0.94,2.1,2.1C29.724,8.84,28.784,9.78,27.625,9.78z"
+ android:fillColor="#FFFFFF" />
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_dynamic_qs_adb.xml b/packages/SystemUI/res/drawable/ic_dynamic_qs_adb.xml
new file mode 100644
index 0000000..6b33a66
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dynamic_qs_adb.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M 37.727707,9.975208 L 40.285946,3.7258741 C 40.541238,3.1009409
+40.243401,2.3882503 39.618464,2.1329586 38.993529,1.8776669 38.28084,2.1755027
+38.025548,2.8004407 L 35.374234,9.275815 C 32.449014,8.605674 28.718028,8.350381
+24.258396,8.350381 l 0,0.01596 0,0 0,-0.01862 c -0.582384,0 -1.148814,0.0053
+-1.707266,0.01596 l -0.0027,0 c -3.712371,0.06116 -6.863631,0.329751
+-9.405913,0.912136 L 10.491243,2.8004407 C 10.235951,2.1755075
+9.5232609,1.8776669 8.8983273,2.1329586 8.2733938,2.3882503 7.9755532,3.1009409
+8.2308452,3.7258741 L 10.789084,9.975208 c -3.3959157,1.284439
+-5.1989153,3.45708 -5.1989153,6.94607 l 0,7.31837 0,1.898735 0,2.084884 c
+0,6.411552 6.0738233,8.379428 16.9583033,8.557599 l 0,0.01064 0.67546,0 c
+0.340389,0.0027 0.686097,0.0053 1.034464,0.0053 l 0,-0.0053 0,0 0,0.0053 c
+0.348368,0 0.694075,-0.0027 1.034465,-0.0053 l 0.04786,0 c 11.280713,-0.11169
+17.585893,-2.031699 17.585893,-8.565578 l 0,-2.087543 0,-1.898735 0,-7.31837 C
+42.929314,13.429631 41.123615,11.259649 37.7277,9.975211 Z M 14.661013,27.973293
+c -3.084777,0 -5.5845131,-2.499733 -5.5845131,-5.584512 0,-3.084778
+2.4997361,-5.584511 5.5845131,-5.584511 3.084778,0 5.584512,2.499733
+5.584512,5.584511 0,3.084779 -2.499734,5.584512 -5.584512,5.584512 z m
+10.185086,4.050102 -1.178065,0 c -0.86693,0 -1.571642,-0.702054
+-1.571642,-1.571642 0,-0.03192 0.008,-0.06382 0.01064,-0.09573 l 4.300073,0 c
+0.0027,0.03192 0.01064,0.06116 0.01064,0.09573 0,0.869588 -0.704712,1.571642
+-1.571641,1.571642 z m 9.00968,-4.050102 c -3.084778,0 -5.584512,-2.499733
+-5.584512,-5.584512 0,-3.084778 2.499734,-5.584511 5.584512,-5.584511 3.084777,0
+5.584512,2.499733 5.584512,5.584511 -0.0027,3.084779 -2.502394,5.584512
+-5.584512,5.584512 z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeWidth="16"
+ android:strokeLineJoin="round"
+ android:strokeLineCap="round"
+ android:pathData="M 23.2448199 33.152538 L 24.8907709 33.152538 Q 25.9999988 33.152538
+25.9999988 34.2617659 L 25.9999988 44.6534791 Q 25.9999988 45.762707 24.8907709 45.762707
+L 23.2448199 45.762707 Q 22.135592 45.762707 22.135592 44.6534791 L 22.135592 34.2617659
+Q 22.135592 33.152538 23.2448199 33.152538 Z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_dynamic_qs_ime_selector.xml b/packages/SystemUI/res/drawable/ic_dynamic_qs_ime_selector.xml
new file mode 100644
index 0000000..07ee10a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dynamic_qs_ime_selector.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M40 10H8c-2.21 0-3.98 1.79-3.98 4L4 34c0 2.21 1.79 4 4 4h32c2.21 0 4-1.79
+4-4V14c0-2.21-1.79-4-4-4zm-18 6h4v4h-4v-4zm0 6h4v4h-4v-4zm-6-6h4v4h-4v-4zm0
+6h4v4h-4v-4zm-2 4h-4v-4h4v4zm0-6h-4v-4h4v4zm18
+14H16v-4h16v4zm0-8h-4v-4h4v4zm0-6h-4v-4h4v4zm6 6h-4v-4h4v4zm0-6h-4v-4h4v4z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_dynamic_qs_next_alarm.xml b/packages/SystemUI/res/drawable/ic_dynamic_qs_next_alarm.xml
new file mode 100644
index 0000000..184d407
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dynamic_qs_next_alarm.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M44 11.44l-9.19-7.71-2.57 3.06 9.19 7.71L44 11.44zM15.76 6.78l-2.57-3.06L4
+11.43l2.57 3.06 9.19-7.71zM25 16h-3v12l9.49 5.71L33
+31.24l-8-4.74V16zm-1.01-8C14.04 8 6 16.06 6 26s8.04 18 17.99 18S42 35.94 42 26
+33.94 8 23.99 8zM24 40c-7.73 0-14-6.27-14-14s6.27-14 14-14 14 6.27 14 14-6.26
+14-14 14z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_dynamic_qs_su.xml b/packages/SystemUI/res/drawable/ic_dynamic_qs_su.xml
new file mode 100644
index 0000000..5d582d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dynamic_qs_su.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeWidth="1"
+ android:pathData="M 28.79,43.78 L 22.26,43.78 31.33,3.52 37.88,3.52 Z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeWidth="1"
+ android:pathData="M 15.46,43.78 L 8.54,43.78 17.69,3.52 24.41,3.52 Z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeWidth="1"
+ android:pathData="M 7.53,15.86 L 43.53,15.86 43.53,20.34 7.53,20.34 Z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeWidth="1"
+ android:pathData="M 4.68,28.68 L 41.69,28.68 41.69,33.15 4.68,33.15 Z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_livedisplay_auto.xml b/packages/SystemUI/res/drawable/ic_livedisplay_auto.xml
new file mode 100644
index 0000000..39d1f8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_livedisplay_auto.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,5v14H5V5H19
+M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3L19,3z
+M10.7,13.3h2.6L12,9.2L10.7,13.3z
+M14.6,17l-0.8-2.2h-3.6L9.4,17H7.3l3.6-10h2.2l3.6,10H14.6z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_livedisplay_day.xml b/packages/SystemUI/res/drawable/ic_livedisplay_day.xml
new file mode 100644
index 0000000..f454d81
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_livedisplay_day.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,5v14H5V5H19
+M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3L19,3z
+M14,12c0,1.1-0.9,2-2,2s-2-0.9-2-2s0.9-2,2-2S14,10.9,14,12z
+M16,13.7l1.7-1.7L16,10.3V8h-2.3L12,6.3L10.3,8H8v2.3L6.3,12L8,13.7
+V16h2.3l1.7,1.7l1.7-1.7H16V13.7z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_livedisplay_night.xml b/packages/SystemUI/res/drawable/ic_livedisplay_night.xml
new file mode 100644
index 0000000..88a6764
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_livedisplay_night.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M15.5,15.5c0.4-0.4,0.7-0.8,0.9-1.2c-1.9,1-4.3,0.7-5.8-0.9s-1.9-4-0.9-5.8C9.2,7.8,8.8,8.1,8.5,8.5
+c-2,2-2,5.1,0,7.1S13.6,17.5,15.5,15.5z M19,5v14H5V5H19
+M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5
+C21,3.9,20.1,3,19,3L19,3z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_livedisplay_off.xml b/packages/SystemUI/res/drawable/ic_livedisplay_off.xml
new file mode 100644
index 0000000..fb68c00
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_livedisplay_off.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M2.7,2.7L1.3,4.1L3,5.8V19c0,1.1,0.9,2,2,2h13.2l1.7,1.7l1.4-1.4L2.7,2.7z
+M5,19V7.8l2.8,2.8L6.3,12L8,13.7 V16h2.3l1.7,1.7l1.4-1.4l2.8,2.8H5z
+M7.8,5l-2-2H19c1.1,0,2,0.9,2,2v13.2l-2-2V5H7.8z
+M16,8v2.3l1.7,1.7l-1.4,1.4l-5.7-5.7L12,6.3 L13.7,8H16z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_livedisplay_outdoor.xml b/packages/SystemUI/res/drawable/ic_livedisplay_outdoor.xml
new file mode 100644
index 0000000..66ead51
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_livedisplay_outdoor.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z
+M19,19H5V5h14V19z M14,12.3l-2.8,3.5l-2-2.4L6.5,17h11L14,12.3z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_lockscreen_shortcuts_blank.xml b/packages/SystemUI/res/drawable/ic_lockscreen_shortcuts_blank.xml
new file mode 100644
index 0000000..1debdda
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lockscreen_shortcuts_blank.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/keyguard_affordance_icon_width"
+ android:height="@dimen/keyguard_affordance_icon_height"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#666666"
+ android:pathData="M14 10h4V6h-4v4zm0 16h4v-4h-4v4zm0 16h4v-4h-4v4zm8-8h4v-4h-4v4zm0 8h4v-4h-4v4zM6
+42h4v-4H6v4zm0-8h4v-4H6v4zm0-8h4v-4H6v4zm0-8h4v-4H6v4zm0-8h4V6H6v4zm16
+16h4v-4h-4v4zm16 8h4v-4h-4v4zm0-8h4v-4h-4v4zm0 16h4v-4h-4v4zm0-24h4v-4h-4v4zm-16
+0h4v-4h-4v4zM38 6v4h4V6h-4zm-16 4h4V6h-4v4zm8
+32h4v-4h-4v4zm0-16h4v-4h-4v4zm0-16h4V6h-4v4z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ambientdisplay_off.xml b/packages/SystemUI/res/drawable/ic_qs_ambientdisplay_off.xml
new file mode 100644
index 0000000..e8b999d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_ambientdisplay_off.xml
@@ -0,0 +1,58 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="64"
+ android:viewportHeight="64">
+
+ <group
+ android:translateY="-988.583">
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M14.9929
+1051.24c-0.860426-0.1558-1.60181-0.6484-2.08043-1.3823-0.191527-0.2937-0.318133-0.5822-0.424976-0.9684l-0.07925-0.2865-0.0077-21.1653-0.0077-21.1652-5.65481-5.6547c-3.75978-3.75965-5.65481-5.67485-5.65481-5.71485
+0-0.039 0.455164-0.5152 1.31263-1.3725 1.14594-1.1458 1.32404-1.3124
+1.40251-1.3124 0.07978 0 3.23905 3.1492 28.1024 28.0124 22.4142 22.4142 28.0125
+28.0275 28.0125 28.0876 0 0.1096-2.59052 2.6999-2.70019 2.6999-0.0594
+0-0.66925-0.5944-2.93987-2.8651l-2.86494-2.8651-0.0162 1.6726-0.0162
+1.6726-0.0793 0.2911c-0.30675 1.127-1.135 1.9557-2.26722 2.2684l-0.29117
+0.08-16.755 0.01c-14.361
+0-16.7886-0.001-16.9903-0.038zm29.8303-12.2447v-0.2925l-5.22747-5.2275-5.22747-5.2275h-6.00753-6.00753l-0.00079-0.6975-0.00078-0.6975
+1.09505-1.08 1.09504-1.08 0.0351-2.175c0.0201-1.2482 0.0254-2.5792
+0.0124-3.1234l-0.0227-0.9485-2.86164-2.8615-2.86164-2.8615v13.2824 13.2825h12.99
+12.99v-0.2925zm-13.44-7.2523c-0.53478-0.1072-1.03604-0.424-1.36654-0.8636-0.30042-0.3997-0.45617-0.8284-0.48472-1.3341l-0.0174-0.3075h1.93454c1.06399
+0 2.13918 0.01 2.38931 0.02l0.45477 0.02v0.1413c0 0.222-0.0844 0.6501-0.17092
+0.8667-0.30319 0.7593-0.93372 1.2975-1.70726 1.4573-0.26299 0.054-0.76232
+0.055-1.03182
+0.0006zm16.6574-0.5628-3.21745-3.2175v-13.5675-13.5674h-12.99-12.99v0.51c0
+0.509-0.00012 0.51-0.0675 0.51-0.0496
+0-0.90464-0.8371-3.225-3.15755l-3.15745-3.1575v-1.4258c0-0.7988 0.01359-1.5341
+0.03091-1.6722 0.161018-1.2841 1.06546-2.3221
+2.32624-2.6698l0.297859-0.082h16.845 16.845l0.29117 0.08c1.13269 0.3129 1.95549
+1.1357 2.26839 2.2684l0.0804 0.2912 0.008 21.0374 0.008 21.0375h-0.0677c-0.0498
+0-0.91619-0.8486-3.28515-3.2176zm-14.04-14.0399c-3.73959-3.7397-5.07747-5.0954-5.07747-5.145
+0-0.037 0.004-0.067 0.008-0.067s0.27081-0.095 0.59194-0.21c0.32114-0.1155
+0.58578-0.21 0.5881-0.21 0.002 0 0.0113-0.1857 0.02-0.4125 0.0255-0.6681
+0.17539-1.0612 0.54652-1.4337 0.34072-0.342 0.70204-0.4938 1.17524-0.4938
+0.48816 0 0.81887 0.1266 1.1524 0.4412 0.24603 0.2321 0.38341 0.4468 0.49534
+0.774 0.0706 0.2064 0.0839 0.3013 0.0959 0.6823 0.0107 0.3401 0.0231 0.4425
+0.0537 0.4425 0.0218 0 0.30704 0.096 0.63378 0.2132 1.18372 0.4249 2.01459
+0.9295 2.74561 1.6675 0.50334 0.5081 0.83969 0.9774 1.15692 1.6143 0.51647
+1.0368 0.81228 2.2666 0.93638 3.8931 0.0267 0.35 0.0876 2.4717 0.0896 3.1193
+0.00057 0.1902-0.004 0.2025-0.0669 0.2025-0.0498 0-1.40242-1.3349-5.145-5.0775z" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_ambientdisplay_on.xml b/packages/SystemUI/res/drawable/ic_qs_ambientdisplay_on.xml
new file mode 100644
index 0000000..96eb36c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_ambientdisplay_on.xml
@@ -0,0 +1,51 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="64"
+ android:viewportHeight="64">
+
+ <group
+ android:translateY="-988.583">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M15.0133
+1051.24c-1.3615-0.2479-2.37425-1.2789-2.57968-2.6262-0.06554-0.4298-0.06571-55.8484-0.00018-56.28
+0.09875-0.65024 0.367851-1.20544 0.812983-1.6773 0.402211-0.42637
+0.920053-0.7356 1.49909-0.8952l0.299302-0.0825h16.845 16.845l0.291174
+0.0804c1.24697 0.34447 2.13039 1.32473 2.32019 2.57456 0.06515 0.42898 0.06541
+55.8484 0.0003 56.28-0.188067 1.2461-1.07608 2.2305-2.32306 2.5752l-0.288567
+0.08h-16.755c-13.5267 0-16.7958
+0-16.9665-0.034zm29.8065-31.1862v-19.23h-12.99-12.99v19.23 19.23h12.99
+12.99v-19.23zm-13.459
+11.687c-1.03547-0.2354-1.77837-1.1208-1.83292-2.1845l-0.01654-0.3225h1.87175c1.02946
+0 2.10645 0.01 2.3933 0.02l0.521553 0.02-0.01945 0.253c-0.02847 0.3705-0.09559
+0.6134-0.267159 0.9672-0.135477 0.2794-0.18522 0.3474-0.439626 0.6013-0.31197
+0.3114-0.571617 0.4707-0.976866 0.5995-0.269196 0.085-0.949163 0.111-1.23404
+0.046zm-9.04096-4.1842v-0.6872l1.10534-1.0831 1.10534-1.0831
+0.02483-1.2072c0.01366-0.664 0.02781-2.213 0.03145-3.4422 0.007-2.3727
+0.01776-2.5909 0.162279-3.3 0.234013-1.1483 0.861931-2.2993 1.7263-3.1643
+0.762874-0.7634 1.91951-1.4813 3.00204-1.8633 0.262572-0.093 0.512691-0.1813
+0.555819-0.1969l0.07842-0.029 0.01577-0.426c0.01284-0.3469 0.03018-0.4706
+0.09332-0.666 0.197394-0.6109 0.642609-1.0525 1.21018-1.2004 0.365688-0.095
+0.860153-0.043 1.2089 0.1282 0.234414 0.1149 0.589851 0.4783 0.725931 0.7422
+0.171483 0.3325 0.207933 0.491 0.225975 0.9825 0.01148 0.3126 0.02671 0.4425
+0.0519 0.4425 0.01961 0 0.2844 0.088 0.588423 0.1954 2.74734 0.9715 4.21726
+2.7794 4.71985 5.805 0.171696 1.0336 0.211308 1.7926 0.259098 4.9646l0.03345
+2.22 1.10911 1.095 1.1091 1.095-0.0014 0.6825-0.0014 0.6825h-9.57-9.57v-0.6872z" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml
new file mode 100644
index 0000000..0301872
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M16.67,4H15V2H9V4H7.33A1.33,1.33 0 0,0 6,5.33V20.67C6,21.4 6.6,22 7.33,22H16.67A1.33,1.33 0 0,0 18,20.67V5.33C18,4.6 17.4,4 16.67,4Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml
new file mode 100644
index 0000000..0e11796
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M16.67,4C17.4,4 18,4.6 18,5.33V20.67A1.33,1.33 0 0,1 16.67,22H7.33C6.6,22 6,21.4 6,20.67V5.33A1.33,1.33 0 0,1 7.33,4H9V2H15V4H16.67M16,14V12H13V9H11V12H8V14H11V17H13V14H16Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_caffeine_off.xml b/packages/SystemUI/res/drawable/ic_qs_caffeine_off.xml
new file mode 100644
index 0000000..59d52e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_caffeine_off.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_caffeine_on.xml b/packages/SystemUI/res/drawable/ic_qs_caffeine_on.xml
new file mode 100644
index 0000000..48b6773
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_caffeine_on.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_compass_off.xml b/packages/SystemUI/res/drawable/ic_qs_compass_off.xml
new file mode 100644
index 0000000..e1ebfec
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_compass_off.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M42,39.2L8.8,6L6,8.8l9.8,9.8l-1.5,3.7c-0.4,1-0.4,2.2,0,3.3l7.8,19.1c0.7,1.7,3.1,1.7,3.8,0l4.6-11.3
+l8.6,8.6L42,39.2Z
+M24,28c-2.2,0-4-1.8-4-4c0-0.4,0.1-0.7,0.1-1l4.9,4.9C24.7,27.9,24.4,28,24,28z
+M33.8,25.3L19.1,10.7l3-7.4
+c0.7-1.7,3.1-1.7,3.8,0l7.8,19.1C34.1,23.3,34.1,24.4,33.8,25.3z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_compass_on.xml b/packages/SystemUI/res/drawable/ic_qs_compass_on.xml
new file mode 100644
index 0000000..f66f64c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_compass_on.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M25.9,3.3l7.8,19.1c0.4,1,0.4,2.2,0,3.3l-7.8,19.1c-0.7,1.7-3.1,1.7-3.8,0l-7.8-19.1c-0.4-1-0.4-2.2,0-3.3
+l7.8-19.1C22.8,1.6,25.2,1.6,25.9,3.3Z
+M24,20c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S26.2,20,24,20z
+M26,14v-4c0-1.1-0.9-2-2-2 s-2,0.9-2,2v4c0,1.1,0.9,2,2,2S26,15.1,26,14z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on_priority.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on_priority.xml
new file mode 100644
index 0000000..f6f3c89
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on_priority.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2015 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.
+-->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64.0dip"
+ android:height="64.0dip"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M24,4C12.95,4,4,12.95,4,24s8.95,20,20,20s20-8.95,20-20S35.05,4,24,4z M34,26h-8v8h-4v-8h-8v-4h8v-8h4v8h8V26z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_edit_tiles.xml b/packages/SystemUI/res/drawable/ic_qs_edit_tiles.xml
new file mode 100644
index 0000000..218228d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_edit_tiles.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M4,32h4v4H4V32z M4,20h4v-4C5.8,16,4,17.8,4,20z M8,44v-4H4 C4,42.2,5.8,44,8,44z
+M4,28h4v-4H4V28z M12,44h4v-4h-4V44z
+M44,8v20c0,2.2-1.8,4-4,4h-8v4h-4v-4h-8c-2.2,0-4-1.8-4-4v-8h-4v-4h4V8
+c0-2.2,1.8-4,4-4h20C42.2,4,44,5.8,44,8z M40,8H20v20h20V8z
+M28,44c2.2,0,4-1.8,4-4h-4V44z M20,44h4v-4h-4V44z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml b/packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml
new file mode 100644
index 0000000..904ccdf
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml b/packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml
new file mode 100644
index 0000000..9c5983d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_battery_saving.xml b/packages/SystemUI/res/drawable/ic_qs_location_battery_saving.xml
new file mode 100644
index 0000000..efd8f16
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_location_battery_saving.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M24.0,4.0c-7.7,0.0 -14.0,6.3 -14.0,14.0c0.0,10.5 14.0,26.0 14.0,26.0s14.0,-15.5 14.0,-26.0C38.0,10.3 31.7,4.0 24.0,4.0zM24.0,23.0c-2.8,0.0 -5.0,-2.2 -5.0,-5.0s2.2,-5.0 5.0,-5.0c2.8,0.0 5.0,2.2 5.0,5.0S26.8,23.0 24.0,23.0z"/>
+ <path
+ android:pathData="M24.0,4.0c-7.7,0.0 -14.0,6.3 -14.0,14.0c0.0,10.5 14.0,26.0 14.0,26.0l0.0,-21.0 c-2.8,0.0 -5.0,-2.2 -5.0,-5.0s2.2,-5.0 5.0,-5.0l0.0,-9.0z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_off.xml b/packages/SystemUI/res/drawable/ic_qs_location_off.xml
new file mode 100644
index 0000000..e0fe12e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_location_off.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M24.0,13.0c2.8,0.0 5.0,2.2 5.0,5.0c0.0,1.5 -0.7,2.8 -1.7,3.7l7.3,7.3c2.0,-3.7 3.4,-7.6 3.4,-11.0c0.0,-7.7 -6.3,-14.0 -14.0,-14.0c-4.0,0.0 -7.5,1.6 -10.1,4.3l6.4,6.4C21.2,13.6 22.5,13.0 24.0,13.0zM32.7,32.2l-9.3,-9.3l-0.2,-0.2L6.5,6.0L4.0,8.5l6.4,6.4c-0.2,1.0 -0.4,2.0 -0.4,3.1c0.0,10.5 14.0,26.0 14.0,26.0s3.3,-3.7 6.8,-8.7l6.7,6.7l2.5,-2.5L32.7,32.2z"/>
+ <path
+ android:pathData="M23.5,22.9l0.0,0.0 -0.20000076,-0.19999886z"
+ android:fillColor="#4DFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_lock_screen_off.xml b/packages/SystemUI/res/drawable/ic_qs_lock_screen_off.xml
new file mode 100644
index 0000000..fec9665
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_lock_screen_off.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M36,16h-2v-4c0-5.5-4.5-10-10-10S14,6.5,14,12h3.8c0-3.4,2.8-6.2,6.2-6.2
+s6.2,2.8,6.2,6.2v4H12c-2.2,0-4,1.8-4,4v20c0,2.2,1.8,4,4,4h24c2.2,0,4-1.8,4-4V20C40,17.8,38.2,16,36,16Z
+M36,40H12V20L36,40z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_lock_screen_on.xml b/packages/SystemUI/res/drawable/ic_qs_lock_screen_on.xml
new file mode 100644
index 0000000..1b7717c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_lock_screen_on.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M36,16h-2v-4c0-5.5-4.5-10-10-10S14,6.5,14,12v4h-2c-2.2,0-4,1.8-4,4v20
+c0,2.2,1.8,4,4,4h24c2.2,0,4-1.8,4-4V20C40,17.8,38.2,16,36,16Z
+M24,5.8c3.4,0,6.2,2.8,6.2,6.2v4H17.8v-4C17.8,8.6,20.6,5.8,24,5.8z
+M36,40H12V20L36,40z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_adb_off.xml b/packages/SystemUI/res/drawable/ic_qs_network_adb_off.xml
new file mode 100644
index 0000000..7c1e235
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_network_adb_off.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M41,37.9L34.1,31l0,0l-6.5-6.5l0,0l-9.8-9.8l0,0L13.1,10L6.5,3.4L4,6l4.1,4.1
+c-4.3,2-6.9,4.1-7.4,4.4l23.3,29l0,0l0,0l7.8-9.7l6.6,6.6L41,37.9Z
+M14,24.5v-2c0-1.9,0.5-3.6,1.5-5.1l7.1,7.1H14z M21.2,13
+l-5.5-5.5c2.5-0.6,5.3-1,8.3-1c13.4,0,22.4,7.3,23.3,8L36.3,28.1l-3.6-3.6H34v-2c0-2.4-0.9-4.6-2.3-6.3l2.3-2.3l-1.4-1.4l-2.3,2.3
+c-1.7-1.4-3.9-2.3-6.3-2.3C23,12.5,22.1,12.7,21.2,13z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_adb_on.xml b/packages/SystemUI/res/drawable/ic_qs_network_adb_on.xml
new file mode 100644
index 0000000..669622f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_network_adb_on.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M24,43.5l23.3-29c-0.9-0.7-9.9-8-23.3-8c-13.4,0-22.4,7.3-23.3,8L24,43.5L24,43.5
+C24,43.5,24,43.5,24,43.5Z
+M31.7,16.2c1.4,1.7,2.3,3.9,2.3,6.3v2H14v-2c0-2.4,0.9-4.6,2.3-6.3L14,13.9l1.4-1.4l2.3,2.3
+c1.7-1.4,3.9-2.3,6.3-2.3c2.4,0,4.6,0.9,6.3,2.3l2.3-2.3l1.4,1.4L31.7,16.2z
+M22,20.5c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2
+c0-1.1,0.9-2,2-2C21.1,18.5,22,19.4,22,20.5z
+M30,20.5c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2C29.1,18.5,30,19.4,30,20.5
+z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_nfc_off.xml b/packages/SystemUI/res/drawable/ic_qs_nfc_off.xml
new file mode 100644
index 0000000..1349c7c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_nfc_off.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M16.4,8l-4-4H40c2.2,0,4,1.8,4,4v27.6l-4-4V8H16.4Z
+M26,12c-1.5,0-2.8,0.9-3.5,2.1l3.5,3.5 V16h6v7.6l4,4V12H26z
+M43.8,41.1c-0.5,1.7-2,2.9-3.8,2.9H8c-2.2,0-4-1.8-4-4V8c0-1.8,1.3-3.4,2.9-3.8L32,29.2l4,4L43.8,41.1z
+M25,27.9c-0.3,0.1-0.7,0.1-1,0.1c-2.2,0-4-1.8-4-4c0-0.4,0-0.7,0.1-1L16,18.8V32h13.2L25,27.9z
+M37.2,40l-4-4H12V14.8l-4-4V40H37.2 z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_nfc_on.xml b/packages/SystemUI/res/drawable/ic_qs_nfc_on.xml
new file mode 100644
index 0000000..73e735c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_nfc_on.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M40,4H8C5.8,4,4,5.8,4,8v32c0,2.2,1.8,4,4,4h32c2.2,0,4-1.8,4-4V8C44,5.8,42.2,4,40,4Z
+M40,40H8V8h32V40z
+M36,12H26c-2.2,0-4,1.8-4,4v4.6c-1.2,0.7-2,2-2,3.4c0,2.2,1.8,4,4,4s4-1.8,4-4c0-1.5-0.8-2.8-2-3.4V16h6v16H16
+V16h4v-4h-8v24h24V12z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_perf_profile.xml b/packages/SystemUI/res/drawable/ic_qs_perf_profile.xml
new file mode 100644
index 0000000..2ce5d1f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_perf_profile.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:width="64dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48">
+
+ <group
+ android:name="base_gauge">
+
+ <path android:pathData="M24,8c8.8,0,16,7.2,16,16s-7.2,16-16,16S8,32.8,8,24S15.2,8,24,8 M24,4C13,4,4,13,4,24s9,20,20,20s20-9,20-20S35,4,24,4
+ L24,4z M24,20c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S26.2,20,24,20z M32.5,13.5c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2
+ S33.6,13.5,32.5,13.5z M15.5,13.5c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S16.6,13.5,15.5,13.5z M15.5,30.5c-1.1,0-2,0.9-2,2
+ c0,1.1,0.9,2,2,2s2-0.9,2-2C17.5,31.4,16.6,30.5,15.5,30.5z"
+
+ android:fillColor="#FFFFFFFF"/>
+
+ </group>
+
+ <group
+ android:name="needle"
+ android:pivotX="24"
+ android:pivotY="24"
+ android:rotation="-135">
+
+ <path
+ android:strokeColor="#FFFFFFFF"
+ android:strokeWidth="4"
+ android:strokeLineCap="round"
+ android:pathData="M 24,24 h 12"/>
+ </group>
+
+
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_profiles_off.xml b/packages/SystemUI/res/drawable/ic_qs_profiles_off.xml
new file mode 100644
index 0000000..f407c4d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_profiles_off.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M14.304,5.455l0.79-1.93c0.079-0.193-0.013-0.413-0.206-0.492c-0.193-0.079-0.413,0.013-0.492,0.206 l-0.818,2c-0.903-0.207-2.055-0.286-3.433-0.286v0.005h0V4.953c-0.18,0-0.355,0.002-0.527,0.005H9.615 C8.468,4.976,7.495,5.06,6.71,5.239l-0.819-2C5.812,3.046,5.592,2.954,5.399,3.033C5.206,3.112,5.114,3.332,5.193,3.525l0.79,1.93 C4.934,5.852,4.377,6.523,4.377,7.6v2.261v0.587v0.644c0,1.98,1.876,2.588,5.238,2.643v0.003h0.209 c0.105,0.001,0.212,0.002,0.32,0.002v-0.002h0v0.002c0.108,0,0.214-0.001,0.32-0.002h0.015c3.484-0.034,5.432-0.628,5.432-2.646 v-0.644V9.861V7.6C15.909,6.523,15.352,5.852,14.304,5.455Z M7.179,11.014c-0.953,0-1.725-0.772-1.725-1.724 c0-0.953,0.772-1.725,1.725-1.725c0.952,0,1.724,0.772,1.724,1.725C8.904,10.242,8.132,11.014,7.179,11.014z M10.325,12.265H9.961 c-0.268,0-0.485-0.217-0.485-0.485c0-0.01,0.002-0.019,0.003-0.029h1.328c0.001,0.01,0.003,0.019,0.003,0.029 C10.81,12.048,10.593,12.265,10.325,12.265z M13.107,11.014c-0.953,0-1.725-0.772-1.725-1.724c0-0.953,0.772-1.725,1.725-1.725 c0.952,0,1.724,0.772,1.724,1.725C14.832,10.242,14.06,11.014,13.107,11.014z M21.44,10.402c-0.261,1.016-0.5,4.301-5.798,7.557 c-0.439,0.269-0.884,0.974-0.884,2.152l0.05,0.89h-1.922v0h-0.014c0-1.492-1.214-2.706-2.706-2.706 c-1.492,0-2.706,1.214-2.706,2.706v0H5.525l0.07-1.243c0,0-0.203,0.516-0.489,1.243H2.501l1.563-4.171 c0.303-0.793,1.013-1.282,1.733-1.529c0.524-0.18,1.593-0.386,3.586-0.485h1.569c0.492,0.025,0.926,0.055,1.311,0.091 c0,0,0,0,0.001,0s0,0,0.001,0c0.296,0.027,0.563,0.057,0.801,0.089c1.028,0.062,2.506-0.095,4.131-1.475 c1.423-1.209,1.591-2.051,2.28-3.895C20.285,7.463,21.816,8.936,21.44,10.402z M12.316,21h0.013v0H8.02v0H8.019 c0-1.185,0.964-2.148,2.149-2.148C11.352,18.851,12.316,19.815,12.316,21z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_profiles_on.xml b/packages/SystemUI/res/drawable/ic_qs_profiles_on.xml
new file mode 100644
index 0000000..ce752e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_profiles_on.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M14.304,5.455l0.79-1.93c0.079-0.193-0.013-0.413-0.206-0.492c-0.193-0.079-0.413,0.013-0.492,0.206 l-0.818,2c-0.903-0.207-2.055-0.286-3.433-0.286v0.005h0V4.953c-0.18,0-0.355,0.002-0.527,0.005H9.615 C8.468,4.976,7.495,5.06,6.71,5.239l-0.819-2C5.812,3.046,5.592,2.954,5.399,3.033C5.206,3.112,5.114,3.332,5.193,3.525l0.79,1.93 C4.934,5.852,4.377,6.523,4.377,7.6v2.261v0.587v0.644c0,1.98,1.876,2.588,5.238,2.643v0.003h0.209 c0.105,0.001,0.212,0.002,0.32,0.002v-0.002h0v0.002c0.108,0,0.214-0.001,0.32-0.002h0.015c3.484-0.034,5.432-0.628,5.432-2.646 v-0.644V9.861V7.6C15.909,6.523,15.352,5.852,14.304,5.455Z M7.179,11.014c-0.953,0-1.725-0.772-1.725-1.724 c0-0.953,0.772-1.725,1.725-1.725c0.952,0,1.724,0.772,1.724,1.725C8.904,10.242,8.132,11.014,7.179,11.014z M10.325,12.265H9.961 c-0.268,0-0.485-0.217-0.485-0.485c0-0.01,0.002-0.019,0.003-0.029h1.328c0.001,0.01,0.003,0.019,0.003,0.029 C10.81,12.048,10.593,12.265,10.325,12.265z M13.107,11.014c-0.953,0-1.725-0.772-1.725-1.724c0-0.953,0.772-1.725,1.725-1.725 c0.952,0,1.724,0.772,1.724,1.725C14.832,10.242,14.06,11.014,13.107,11.014z M21.44,10.402c-0.261,1.016-0.5,4.301-5.798,7.557 c-0.439,0.269-0.884,0.974-0.884,2.152l0.05,0.89h-1.922v0h-0.014c0-1.492-1.214-2.706-2.706-2.706 c-1.492,0-2.706,1.214-2.706,2.706v0H5.525l0.07-1.243c0,0-0.203,0.516-0.489,1.243H2.501l1.563-4.171 c0.303-0.793,1.013-1.282,1.733-1.529c0.524-0.18,1.593-0.386,3.586-0.485h1.569c0.492,0.025,0.926,0.055,1.311,0.091 c0,0,0,0,0.001,0s0,0,0.001,0c0.296,0.027,0.563,0.057,0.801,0.089c1.028,0.062,2.506-0.095,4.131-1.475 c1.423-1.209,1.591-2.051,2.28-3.895C20.285,7.463,21.816,8.936,21.44,10.402z M12.316,21h0.013v0H8.02v0H8.019 c0-1.185,0.964-2.148,2.149-2.148C11.352,18.851,12.316,19.815,12.316,21z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_avd.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_avd.xml
new file mode 100644
index 0000000..5761fd3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_avd.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_screen_timeout_vector">
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_medtoshort"
+ android:name="time2"/>
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_longtoshort"
+ android:name="time3"/>
+</animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_reverse_avd.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_reverse_avd.xml
new file mode 100644
index 0000000..08871cd
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_long_reverse_avd.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_screen_timeout_vector">
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_longtomed"
+ android:name="time3"/>
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_staymed"
+ android:name="time2" />
+
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_avd.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_avd.xml
new file mode 100644
index 0000000..88b7d14
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_avd.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_screen_timeout_vector">
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_staymed"
+ android:name="time2"/>
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_tolong"
+ android:name="time3"/>
+
+</animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_reverse_avd.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_reverse_avd.xml
new file mode 100644
index 0000000..4f08a14
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_med_reverse_avd.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_screen_timeout_vector">
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_medtoshort_reverse"
+ android:name="time2"/>
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_medtoshort_reverse"
+ android:name="time3"/>
+
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_avd.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_avd.xml
new file mode 100644
index 0000000..694e662
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_avd.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_screen_timeout_vector">
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_tomed"
+ android:name="time2"/>
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_tomed"
+ android:name="time3"/>
+
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_reverse_avd.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_reverse_avd.xml
new file mode 100644
index 0000000..a9a1a7d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_short_reverse_avd.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_screen_timeout_vector">
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_tomed"
+ android:name="time2"/>
+
+ <target
+ android:animation="@anim/ic_qs_screen_timeout_shorttolong"
+ android:name="time3"/>
+
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_screen_timeout_vector.xml b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_vector.xml
new file mode 100644
index 0000000..91f64fd
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_screen_timeout_vector.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+android:height="64dp"
+android:width="64dp"
+android:viewportHeight="48"
+android:viewportWidth="48">
+
+<group
+ android:name="base_screen">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M38,8v32c0,2.2-1.8,4-4,4H14c-2.2,0-4-1.8-4-4V8c0-2.2,1.8-4,4-4h20C36.2,4,38,5.8,38,8Z
+M34,24 c0-5.5-4.5-10-10-10s-10,4.5-10,10c0,5.5,4.5,10,10,10S34,29.5,34,24z" />
+
+</group>
+
+<group
+ android:name="time1"
+ android:pivotX="24"
+ android:pivotY="24"
+ android:rotation="0">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M24,18v6h-6C18,20.7,20.7,18,24,18z"/>
+</group>
+
+<group
+ android:name="time2"
+ android:pivotX="24"
+ android:pivotY="24"
+ android:rotation="0">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M24,18v6h-6C18,20.7,20.7,18,24,18z"/>
+</group>
+
+<group
+ android:name="time3"
+ android:pivotX="24"
+ android:pivotY="24"
+ android:rotation="0">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M24,18v6h-6C18,20.7,20.7,18,24,18z"/>
+
+</group>
+
+
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
new file mode 100644
index 0000000..cefb714
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18.0dp"
+ android:height="24dp"
+ android:viewportWidth="36.0"
+ android:viewportHeight="36.0">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
+M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
+c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
+c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
+c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
+c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
+c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_hp.xml b/packages/SystemUI/res/drawable/ic_qs_signal_hp.xml
new file mode 100644
index 0000000..b8ff918
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_hp.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16.4dp"
+ android:height="32dp"
+ android:viewportWidth="16.4"
+ android:viewportHeight="32">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8,14.667H5.867V10h-3.6v4.667H0V3.333h2.267v4.933h3.6V3.333H8V14.667Z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M16.4,5.6h-2.267V3.333H12V5.6H9.733v2.133H12V10h2.133V7.733H16.4V5.6Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_sync_off.xml b/packages/SystemUI/res/drawable/ic_qs_sync_off.xml
new file mode 100644
index 0000000..4dc0c6c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_sync_off.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M10 6.35V4.26c-.8 .21 -1.55 .54 -2.23 .96 l1.46 1.46c.25-.12 .5 -.24 .77
+-.33zm-7.14-.94l2.36 2.36C4.45 8.99 4 10.44 4 12c0 2.21 .91 4.2 2.36 5.64L4
+20h6v-6l-2.24 2.24C6.68 15.15 6 13.66 6 12c0-1 .25-1.94 .68 -2.77l8.08 8.08c-.25
+.13 -.5 .25 -.77 .34 v2.09c.8-.21 1.55-.54 2.23-.96l2.36 2.36 1.27-1.27L4.14
+4.14 2.86 5.41zM20 4h-6v6l2.24-2.24C17.32 8.85 18 10.34 18 12c0 1-.25 1.94-.68
+2.77l1.46 1.46C19.55 15.01 20 13.56 20 12c0-2.21-.91-4.2-2.36-5.64L20 4z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_sync_on.xml b/packages/SystemUI/res/drawable/ic_qs_sync_on.xml
new file mode 100644
index 0000000..5997690
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_sync_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03
+20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01 .25 -1.97 .7
+-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_category_other.xml b/packages/SystemUI/res/drawable/ic_qs_tile_category_other.xml
new file mode 100644
index 0000000..f3f9dca
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_category_other.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyangenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:width="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF"
+ android:pathData="M12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zm7,-7H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2V5c0,-1.1 -0.89,-2 -2,-2zm-1.75,9c0,0.23 -0.02,0.46 -0.05,0.68l1.48,1.16c0.13,0.11 0.17,0.3 0.08,0.45l-1.4,2.42c-0.09,0.15 -0.27,0.21 -0.43,0.15l-1.74,-0.7c-0.36,0.28 -0.76,0.51 -1.18,0.69l-0.26,1.85c-0.03,0.17 -0.18,0.3 -0.35,0.3h-2.8c-0.17,0 -0.32,-0.13 -0.35,-0.29l-0.26,-1.85c-0.43,-0.18 -0.82,-0.41 -1.18,-0.69l-1.74,0.7c-0.16,0.06 -0.34,0 -0.43,-0.15l-1.4,-2.42c-0.09,-0.15 -0.05,-0.34 0.08,-0.45l1.48,-1.16c-0.03,-0.23 -0.05,-0.46 -0.05,-0.69 0,-0.23 0.02,-0.46 0.05,-0.68l-1.48,-1.16c-0.13,-0.11 -0.17,-0.3 -0.08,-0.45l1.4,-2.42c0.09,-0.15 0.27,-0.21 0.43,-0.15l1.74,0.7c0.36,-0.28 0.76,-0.51 1.18,-0.69l0.26,-1.85c0.03,-0.17 0.18,-0.3 0.35,-0.3h2.8c0.17,0 0.32,0.13 0.35,0.29l0.26,1.85c0.43,0.18 0.82,0.41 1.18,0.69l1.74,-0.7c0.16,-0.06 0.34,0 0.43,0.15l1.4,2.42c0.09,0.15 0.05,0.34 -0.08,0.45l-1.48,1.16c0.03,0.23 0.05,0.46 0.05,0.69z"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_category_system.xml b/packages/SystemUI/res/drawable/ic_qs_tile_category_system.xml
new file mode 100644
index 0000000..a54bec7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_category_system.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyangenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="18dp"
+ android:width="18dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ >
+ <path android:fillColor="#FFFFFFFF"
+ android:pathData="M12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zm7,-7H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2V5c0,-1.1 -0.89,-2 -2,-2zm-1.75,9c0,0.23 -0.02,0.46 -0.05,0.68l1.48,1.16c0.13,0.11 0.17,0.3 0.08,0.45l-1.4,2.42c-0.09,0.15 -0.27,0.21 -0.43,0.15l-1.74,-0.7c-0.36,0.28 -0.76,0.51 -1.18,0.69l-0.26,1.85c-0.03,0.17 -0.18,0.3 -0.35,0.3h-2.8c-0.17,0 -0.32,-0.13 -0.35,-0.29l-0.26,-1.85c-0.43,-0.18 -0.82,-0.41 -1.18,-0.69l-1.74,0.7c-0.16,0.06 -0.34,0 -0.43,-0.15l-1.4,-2.42c-0.09,-0.15 -0.05,-0.34 0.08,-0.45l1.48,-1.16c-0.03,-0.23 -0.05,-0.46 -0.05,-0.69 0,-0.23 0.02,-0.46 0.05,-0.68l-1.48,-1.16c-0.13,-0.11 -0.17,-0.3 -0.08,-0.45l1.4,-2.42c0.09,-0.15 0.27,-0.21 0.43,-0.15l1.74,0.7c0.36,-0.28 0.76,-0.51 1.18,-0.69l0.26,-1.85c0.03,-0.17 0.18,-0.3 0.35,-0.3h2.8c0.17,0 0.32,0.13 0.35,0.29l0.26,1.85c0.43,0.18 0.82,0.41 1.18,0.69l1.74,-0.7c0.16,-0.06 0.34,0 0.43,0.15l1.4,2.42c0.09,0.15 0.05,0.34 -0.08,0.45l-1.48,1.16c0.03,0.23 0.05,0.46 0.05,0.69z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_contract.xml b/packages/SystemUI/res/drawable/ic_qs_tile_contract.xml
new file mode 100644
index 0000000..e98f57c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_contract.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18.0dp"
+ android:height="18.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M12.000000,8.000000l-6.000000,6.000000 1.400000,1.400000 4.600000,-4.599999 4.600000,4.599999 1.400000,-1.400000z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_delete.xml b/packages/SystemUI/res/drawable/ic_qs_tile_delete.xml
new file mode 100755
index 0000000..d934fe0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_delete.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6 19c0 1.1 .9 2 2 2h8c1.1 0 2-.9 2-2v-12h-12v12zm13-15h-3.5l-1-1h-5l-1
+1h-3.5v2h14v-2z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_delete_disable.xml b/packages/SystemUI/res/drawable/ic_qs_tile_delete_disable.xml
new file mode 100755
index 0000000..91e37ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_delete_disable.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="root"
+ android:alpha="1"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <clip-path
+ android:name="mask"
+ android:pathData="M24,24H0V0h1.4l2.9,3l1.4-1.4L4.2,0H24V24z" />
+ <path
+ android:name="cross"
+ android:strokeColor="#FFFFFFFF"
+ android:strokeWidth="3.2"
+ android:strokeAlpha="0"
+ android:pathData="M 4.4 3 L 4.7 3.3" />
+ <path
+ android:name="bin"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1"
+ android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z
+M19,4h-3.5l-1-1h-5l-1,1H5v2h14V4z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_delete_disable_avd.xml b/packages/SystemUI/res/drawable/ic_qs_tile_delete_disable_avd.xml
new file mode 100755
index 0000000..56f7021
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_delete_disable_avd.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_qs_tile_delete_disable" >
+ <target
+ android:name="root"
+ android:animation="@anim/ic_qs_tile_delete_disable_root_anim" />
+ <target
+ android:name="mask"
+ android:animation="@anim/ic_qs_tile_delete_disable_mask_anim" />
+ <target
+ android:name="cross"
+ android:animation="@anim/ic_qs_tile_delete_disable_cross_anim" />
+</animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_delete_enable.xml b/packages/SystemUI/res/drawable/ic_qs_tile_delete_enable.xml
new file mode 100755
index 0000000..d58f169
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_delete_enable.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="root"
+ android:alpha="0.3"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <clip-path
+ android:name="mask"
+ android:pathData="M24,24H0V0h1.4l19.8,19.8l1.4-1.4L4.2,0H24V24z" />
+ <path
+ android:name="cross"
+ android:strokeColor="#FFFFFFFF"
+ android:strokeWidth="3.2"
+ android:strokeAlpha="1"
+ android:pathData="M 4.4 3 L 21 19.6" />
+ <path
+ android:name="bin"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1"
+ android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z
+M19,4h-3.5l-1-1h-5l-1,1H5v2h14V4z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_tile_expand.xml b/packages/SystemUI/res/drawable/ic_qs_tile_expand.xml
new file mode 100644
index 0000000..a429456
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_tile_expand.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18.0dp"
+ android:height="18.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M16.600000,8.600000l-4.600000,4.599999 -4.600000,-4.599999 -1.400000,1.400000 6.000000,6.000000 6.000000,-6.000000z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_usb_tether_off.xml b/packages/SystemUI/res/drawable/ic_qs_usb_tether_off.xml
new file mode 100644
index 0000000..3d54152
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_usb_tether_off.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="64"
+ android:viewportHeight="64">
+
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M48.677,29.715h5.255v-7.254h4.401l-7.047-9.612l-7.052,9.612h4.443V29.715z M54.688,46.753l3.645-4.971h-4.401v-7.255 h-5.255v6.215L54.688,46.753z M36.741,28.805v-3.923h2.109v-8.445h-8.444v6.034L36.741,28.805z M23.942,16.007v-1.679h4.562 l-6.547-8.976l-3.656,5.014L23.942,16.007z M28.916,34.699l22.692,22.692l3.324-3.324L7.6,6.734l-3.324,3.323l15.693,15.694 l0.004,10.381l-8.571-3.715v-3.896c1.257-0.734,2.111-2.079,2.111-3.639c0-2.33-1.887-4.222-4.224-4.222 c-2.332,0-4.222,1.892-4.222,4.222c0,1.56,0.854,2.905,2.113,3.639v6.668l12.794,5.547v5.609c-2.518,0.837-4.348,3.185-4.348,5.987 c0,3.495,2.835,6.333,6.332,6.333c3.501,0,6.337-2.838,6.337-6.333c0-2.802-1.83-5.15-4.352-5.987v-9.113L28.916,34.699z M23.938,29.72l1.843,1.843l-1.839,0.93L23.938,29.72z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_usb_tether_on.xml b/packages/SystemUI/res/drawable/ic_qs_usb_tether_on.xml
new file mode 100644
index 0000000..54f075c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_usb_tether_on.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="64"
+ android:viewportHeight="64">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M48.677,29.724h5.255V22.47h4.401l-7.047-9.611l-7.052,9.611h4.443V29.724z M48.677,34.537h5.255v7.254h4.401l-7.047,9.611 l-7.052-9.611h4.443V34.537z M38.85,16.447h-8.444v8.445h2.11v3.251l-8.574,4.36V14.337h4.562l-6.547-8.975l-6.545,8.975h4.561 v21.805l-8.571-3.715v-3.896c1.257-0.734,2.111-2.079,2.111-3.639c0-2.33-1.887-4.222-4.224-4.222c-2.332,0-4.222,1.892-4.222,4.222c0,1.56,0.854,2.905,2.113,3.639v6.668l12.794,5.547v5.609c-2.518,0.837-4.348,3.184-4.348,5.987c0,3.495,2.835,6.333,6.332,6.333c3.501,0,6.337-2.838,6.337-6.333c0-2.802-1.83-5.15-4.352-5.987v-9.113l12.798-6.512v-5.839h2.11L38.85,16.447L38.85,16.447z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_volume_panel.xml b/packages/SystemUI/res/drawable/ic_qs_volume_panel.xml
new file mode 100644
index 0000000..4b818a5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_volume_panel.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,8.0L14.0,18.0L6.0,18.0zm27.0,6.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,16.11c2.96,-1.48 5.0,-4.53 5.0,-8.06zM28.0,6.46l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41s-4.22,11.69 -10.0,13.41l0.0,4.13c8.01,-1.82 14.0,-8.97 14.0,-17.54S36.01,8.28 28.0,6.46z"/> <!--TODO Needs own icon-->
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings.xml b/packages/SystemUI/res/drawable/ic_settings.xml
index 9c78742..545bc2d 100644
--- a/packages/SystemUI/res/drawable/ic_settings.xml
+++ b/packages/SystemUI/res/drawable/ic_settings.xml
@@ -1,26 +1,25 @@
-<!-- Copyright (C) 2014 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"+
+<!--
+ Copyright (C) 2015 The Android Open Source Project
-http://www.apache.org/licenses/LICENSE-2.0
+ 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.
+ 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.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-android:width="24dp"
-android:height="24dp" android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
-
-<path
- android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
- android:fillColor="#ffffffff"
- />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
+ android:fillColor="#ffffffff" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_notification.xml b/packages/SystemUI/res/drawable/ic_volume_notification.xml
new file mode 100644
index 0000000..c566d5a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_notification.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24dp" >
+
+ <path
+ android:fillColor="@color/volume_icon_color"
+ android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
+
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_notification_mute.xml b/packages/SystemUI/res/drawable/ic_volume_notification_mute.xml
new file mode 100644
index 0000000..57cde85
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_notification_mute.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:fillColor="@color/volume_icon_color"
+ android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" />
+
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index c566d5a..4d5fe81 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -1,5 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2015 The Android Open Source Project
+ Copyright (C) 2016 The CyanogenMod Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,13 +15,12 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0"
- android:width="24dp" >
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
android:fillColor="@color/volume_icon_color"
- android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
-
-</vector> \ No newline at end of file
+ android:pathData="M23.71,16.67C20.66,13.78 16.54,12 12,12 7.46,12 3.34,13.78 0.29,16.67c-0.18,0.18 -0.29,0.43 -0.29,0.71 0,0.28 0.11,0.53 0.29,0.71l2.48,2.48c0.18,0.18 0.43,0.29 0.71,0.29 0.27,0 0.52,-0.11 0.7,-0.28 0.79,-0.74 1.69,-1.36 2.66,-1.85 0.33,-0.16 0.56,-0.5 0.56,-0.9v-3.1c1.45,-0.48 3,-0.73 4.6,-0.73s3.15,0.25 4.6,0.72v3.1c0,0.39 0.23,0.74 0.56,0.9 0.98,0.49 1.87,1.12 2.66,1.85 0.18,0.18 0.43,0.28 0.7,0.28 0.28,0 0.53,-0.11 0.71,-0.29l2.48,-2.48c0.18,-0.18 0.29,-0.43 0.29,-0.71 0,-0.27 -0.11,-0.52 -0.29,-0.7zM21.16,6.26l-1.41,-1.41 -3.56,3.55 1.41,1.41s3.45,-3.52 3.56,-3.55zM13,2h-2v5h2V2zM6.4,9.81L7.81,8.4 4.26,4.84 2.84,6.26c0.11,0.03 3.56,3.55 3.56,3.55z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/lockscreen_shortcuts_phone_background.xml b/packages/SystemUI/res/drawable/lockscreen_shortcuts_phone_background.xml
new file mode 100644
index 0000000..e3cae61
--- /dev/null
+++ b/packages/SystemUI/res/drawable/lockscreen_shortcuts_phone_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item>
+ <shape
+ android:shape="rectangle">
+ <solid
+ android:color="#333333" />
+ <size android:height="@dimen/phone_height" android:width="@dimen/phone_width" />
+ <corners android:bottomLeftRadius="15dp" android:bottomRightRadius="15dp" />
+ </shape>
+ </item>
+ <item android:bottom="@dimen/phone_bottom_padding" android:right="@dimen/phone_side_padding" android:left="@dimen/phone_side_padding">
+ <shape
+ android:shape="rectangle">
+ <solid
+ android:color="@android:color/black" />
+ </shape>
+ </item>
+</layer-list>
+
diff --git a/packages/SystemUI/res/drawable/lockscreen_target_background.xml b/packages/SystemUI/res/drawable/lockscreen_target_background.xml
new file mode 100644
index 0000000..d26da7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/lockscreen_target_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ Copyright (C) 2014 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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#DDDDDD">
+</ripple>
diff --git a/packages/SystemUI/res/drawable/notification_guts_ic_ringer_mute.xml b/packages/SystemUI/res/drawable/notification_guts_ic_ringer_mute.xml
new file mode 100644
index 0000000..63c8315
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_guts_ic_ringer_mute.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/ic_volume_ringer_mute" />
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/notification_guts_ic_settings.xml b/packages/SystemUI/res/drawable/notification_guts_ic_settings.xml
new file mode 100644
index 0000000..312a55f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_guts_ic_settings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/ic_settings" />
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/qs_tile_background_drag.xml b/packages/SystemUI/res/drawable/qs_tile_background_drag.xml
new file mode 100644
index 0000000..0a3ba2d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_tile_background_drag.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015, The CyanogenMod 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.
+*/
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="#FF37474f" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/stat_notify_image.xml b/packages/SystemUI/res/drawable/stat_notify_image.xml
new file mode 100644
index 0000000..17c1bda
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_notify_image.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z
+M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5 L8.5,13.5z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_notify_image_error.xml b/packages/SystemUI/res/drawable/stat_notify_image_error.xml
new file mode 100644
index 0000000..3c2ca40
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_notify_image_error.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z
+M14,12v6h-2h-1H5 l3.5-4.5L10,15l3-4L14,12z M18,18h-2v-2h2V18z M18,14h-2V7h2V14z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
new file mode 100644
index 0000000..59e880b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
@@ -0,0 +1,50 @@
+<!--
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="15dp"
+ android:height="20dp"
+ android:viewportWidth="36"
+ android:viewportHeight="36">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
+M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
+c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
+c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
+c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
+c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
+c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_hp.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_hp.xml
new file mode 100644
index 0000000..a464e18
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_hp.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="8.454dp"
+ android:height="17dp"
+ android:viewportWidth="8.454"
+ android:viewportHeight="17">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M4.25,7.792H3.117V5.313H1.204v2.479H0V1.771h1.204v2.621h1.912V1.771H4.25V7.792Z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.454,2.975H7.25V1.771H6.117v1.204H4.912v1.133h1.205v1.205H7.25V4.108h1.204V2.975Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_roaming.xml b/packages/SystemUI/res/drawable/stat_sys_data_roaming.xml
new file mode 100644
index 0000000..17c4b04
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_roaming.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="4.25dp"
+ android:height="17dp"
+ android:viewportWidth="6.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M 2.8,18.8 l -1,0 0,3.1 -1.6,0 0,-8.5 2.7,0 c 0.9,0 1.5,0.2 2,0.7 0.5,0.5 0.7,1.1 0.7,1.9 0,0.6 -0.1,1.1 -0.3,1.5 -0.2,0.4 -0.5,0.6 -0.9,0.8 l 1.5,3.5 0,0.1 -1.8,0 -1.3,-3.1 z m -1,-1.4 1.1,0 C 3.3,17.4 3.5,17.3 3.7,17 3.9,16.7 4,16.5 4,16.1 4,15.7 3.9,15.3 3.7,15.1 3.5,14.9 3.3,14.7 2.9,14.7 l -1.1,0 0,2.7 z" />
+
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_dnd_priority.xml b/packages/SystemUI/res/drawable/stat_sys_dnd_priority.xml
new file mode 100644
index 0000000..2664bc6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_dnd_priority.xml
@@ -0,0 +1,28 @@
+<!--
+ Copyright (C) 2015 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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="2.5dip"
+ android:insetRight="2.5dip">
+ <vector
+ android:width="17.0dip"
+ android:height="17.0dip"
+ android:viewportHeight="48.0"
+ android:viewportWidth="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M24,4C12.95,4,4,12.95,4,24s8.95,20,20,20s20-8.95,20-20S35.05,4,24,4z M34,26h-8v8h-4v-8h-8v-4h8v-8h4v8h8V26z" />
+ </vector>
+</inset> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_su.xml b/packages/SystemUI/res/drawable/stat_sys_su.xml
new file mode 100644
index 0000000..e013c13
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_su.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="2.5dp"
+ android:insetRight="2.5dp">
+ <vector
+ android:width="23dp"
+ android:height="18dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.49,15.934h-2.373L9.24,21H6.966l0.89-5.066H5.051v-2.089h3.163l0.63-3.584H5.977V8.148h3.238 l0.902-5.141h2.261l-0.902,5.141h2.373l0.914-5.141h2.261l-0.902,5.141h2.719v2.113h-3.089l-0.63,3.584h2.78v2.089h-3.139L13.874,21 H11.6L12.49,15.934Z M10.488,13.845h2.36l0.63-3.584h-2.373L10.488,13.845z" />
+ </vector>
+</inset>
diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml
index f09c01b..8ac471f 100644
--- a/packages/SystemUI/res/drawable/volume_dialog_background.xml
+++ b/packages/SystemUI/res/drawable/volume_dialog_background.xml
@@ -19,4 +19,4 @@
<corners android:radius="@dimen/notification_material_rounded_rect_radius" />
-</shape> \ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/drawable/zen_mode_panel_background.xml b/packages/SystemUI/res/drawable/zen_mode_panel_background.xml
new file mode 100644
index 0000000..a91520a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/zen_mode_panel_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/system_secondary_color" />
+ <corners
+ android:topLeftRadius="0dp"
+ android:topRightRadius="0dp"
+ android:bottomLeftRadius="@dimen/zen_mode_panel_radius"
+ android:bottomRightRadius="@dimen/zen_mode_panel_radius"/>
+</shape>
diff --git a/packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_land.xml b/packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_land.xml
new file mode 100644
index 0000000..43426d1
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_land.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2015, The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/nav_buttons">
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:visibility="gone"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/one"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside" />
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/mid_nav_buttons"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
+ android:animateLayoutChanges="true">
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/two"
+ android:scaleType="centerInside"
+ android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_height="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/three"
+ android:scaleType="centerInside"
+ android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_height="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/four"
+ android:scaleType="centerInside"
+ android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/five"
+ android:scaleType="centerInside"
+ android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ </LinearLayout>
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <FrameLayout
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:layout_marginEnd="2dp" >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/ime_switcher"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="2dp"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_ime_switcher_default"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_ime_switch_button" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/six"
+ android:scaleType="centerInside"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_right"
+ android:visibility="gone"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true"/>
+ </FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_port.xml b/packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_port.xml
new file mode 100644
index 0000000..a7dedbd
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/mid_navigation_bar_port.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015 The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/nav_buttons">
+ <FrameLayout
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0">
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:visibility="gone"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="fitCenter"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:visibility="gone"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="fitCenter"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/one"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="fitCenter" />
+ </FrameLayout>
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/mid_nav_buttons"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
+ android:animateLayoutChanges="true">
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/two"
+ android:scaleType="centerInside"
+ android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_height="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/three"
+ android:scaleType="centerInside"
+ android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_height="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/four"
+ android:scaleType="centerInside"
+ android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/five"
+ android:scaleType="centerInside"
+ android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ </LinearLayout>
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <FrameLayout
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:layout_marginEnd="2dp" >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/ime_switcher"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_ime_switcher_default"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_ime_switch_button" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/six"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_right"
+ android:visibility="gone"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true" />
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 9912343..68883ce 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -3,16 +3,16 @@
**
** Copyright 2012, 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
+** 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
+** 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
+** 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.
-->
@@ -36,126 +36,65 @@
android:orientation="horizontal"
android:clipChildren="false"
android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
+ android:id="@+id/container"
>
- <!-- navigation controls -->
- <View
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:layout_marginStart="2dp"
- android:visibility="invisible"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
- android:scaleType="centerInside"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
- android:scaleType="centerInside"
- systemui:keyCode="3"
- systemui:keyRepeat="true"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:scaleType="centerInside"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <FrameLayout
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:layout_marginEnd="2dp" >
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_menu"
- android:scaleType="centerInside"
- android:layout_marginEnd="2dp"
- systemui:keyCode="82"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_menu"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:scaleType="centerInside"
- android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_ime_switch_button" />
- </FrameLayout>
+ <include layout="@layout/mid_navigation_bar_port"/>
+
</LinearLayout>
- <!-- lights out layout to match exactly -->
- <LinearLayout
+ <LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
- android:id="@+id/lights_out"
- android:visibility="gone"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
>
- <Space
- android:layout_width="match_parent"
+ <View
+ android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <ImageView
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+ android:layout_weight="1" />
+ <!-- lights out layout to match exactly -->
+ <LinearLayout
android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_horizontal"
android:layout_marginStart="40dp"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <ImageView
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_large"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <ImageView
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_marginEnd="40dp"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/lights_out"
+ android:visibility="gone">
+ <ImageView
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ <ImageView
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ <ImageView
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ <ImageView
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ </LinearLayout>
+ <View
+ android:layout_width="0dp"
android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
+ android:layout_weight="1" />
</LinearLayout>
<com.android.systemui.statusbar.policy.DeadZone
@@ -182,127 +121,72 @@
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
android:clipChildren="false"
android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
+ android:id="@+id/container"
>
- <!-- navigation controls -->
- <View
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:layout_marginStart="2dp"
- android:visibility="invisible"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
- android:scaleType="centerInside"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
- android:scaleType="centerInside"
- systemui:keyCode="3"
- systemui:keyRepeat="true"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:scaleType="centerInside"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <FrameLayout
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:layout_weight="0" >
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:src="@drawable/ic_sysbar_menu"
- android:scaleType="centerInside"
- systemui:keyCode="82"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_menu" />
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_ime_switch_button"
- android:scaleType="centerInside" />
- </FrameLayout>
+ <include layout="@layout/mid_navigation_bar_land"/>
+
</LinearLayout>
- <!-- lights out layout to match exactly -->
+ <!-- lights out layout to match exactly -->
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
- android:id="@+id/lights_out"
- android:visibility="gone"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
+ android:visibility="visible"
>
- <Space
- android:layout_width="match_parent"
+ <View
+ android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <ImageView
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+ android:layout_weight="1" />
+ <!-- lights out layout to match exactly -->
+ <LinearLayout
android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
android:layout_marginStart="40dp"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <ImageView
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_large"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <ImageView
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_marginEnd="40dp"
+ android:id="@+id/lights_out"
+ android:visibility="gone"
+ >
+ <ImageView
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ <ImageView
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ <ImageView
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ <ImageView
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
+ android:scaleType="center"
+ />
+ </LinearLayout>
+ <View
+ android:layout_width="0dp"
android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
+ android:layout_weight="1" />
</LinearLayout>
<com.android.systemui.statusbar.policy.DeadZone
diff --git a/packages/SystemUI/res/layout/cmland.xml b/packages/SystemUI/res/layout/cmland.xml
new file mode 100644
index 0000000..3c4e561
--- /dev/null
+++ b/packages/SystemUI/res/layout/cmland.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <com.android.systemui.egg.CMLand
+ android:id="@+id/world"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ </com.android.systemui.egg.CMLand>
+ <FrameLayout
+ android:id="@+id/welcome"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:background="#a0000000"
+ android:clickable="true"
+ >
+ <FrameLayout
+ android:id="@+id/play_button"
+ android:layout_width="72dp"
+ android:layout_height="72dp"
+ android:layout_gravity="center"
+ android:clickable="true"
+ android:background="@drawable/ripplebg"
+ android:focusable="true"
+ android:onClick="startButtonPressed"
+ >
+ <ImageView
+ android:id="@+id/play_button_image"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:scaleType="fitCenter"
+ android:layout_gravity="center"
+ android:tint="#000000"
+ android:src="@drawable/play"
+ />
+ <TextView
+ android:id="@+id/play_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:alpha="0"
+ android:textSize="40dp"
+ android:textColor="#000000"
+ />
+ </FrameLayout>
+ </FrameLayout>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|center_horizontal"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:id="@+id/player_setup"
+ >
+ <ImageButton
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:id="@+id/player_minus_button"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="10dp"
+ android:scaleType="centerInside"
+ android:onClick="playerMinus"
+ android:src="@drawable/minus"
+ />
+ <LinearLayout
+ android:id="@+id/scores"
+ android:layout_width="wrap_content"
+ android:layout_height="64dp"
+ android:padding="12dp"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ >
+ </LinearLayout>
+ <ImageButton
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:id="@+id/player_plus_button"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="10dp"
+ android:scaleType="centerInside"
+ android:onClick="playerPlus"
+ android:src="@drawable/plus"
+ />
+ </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 444f0f0..afb98be 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -32,7 +32,7 @@
android:layout_gravity="bottom|center_horizontal"
android:gravity="center_horizontal"
android:textStyle="italic"
- android:textColor="#ffffff"
+ android:textColor="@color/keyguard_indication_text_color"
android:textAppearance="?android:attr/textAppearanceSmall"
android:accessibilityLiveRegion="polite" />
@@ -47,7 +47,6 @@
android:layout_height="@dimen/keyguard_affordance_height"
android:layout_width="@dimen/keyguard_affordance_width"
android:layout_gravity="bottom|end"
- android:tint="#ffffffff"
android:src="@drawable/ic_camera_alt_24dp"
android:scaleType="center"
android:contentDescription="@string/accessibility_camera_button" />
@@ -57,7 +56,6 @@
android:layout_height="@dimen/keyguard_affordance_height"
android:layout_width="@dimen/keyguard_affordance_width"
android:layout_gravity="bottom|start"
- android:tint="#ffffffff"
android:src="@drawable/ic_phone_24dp"
android:scaleType="center"
android:contentDescription="@string/accessibility_phone_button" />
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index b5f917a..fcd7e62 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -52,13 +52,23 @@
>
<include layout="@layout/system_icons" />
</FrameLayout>
- <TextView android:id="@+id/battery_level"
+ <com.android.systemui.BatteryLevelTextView android:id="@+id/battery_level_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/header_battery_margin_keyguard"
android:paddingEnd="@dimen/battery_level_padding_end"
- android:textColor="#ffffff"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:visibility="gone"
+ android:textSize="@dimen/battery_level_text_size"
+ android:importantForAccessibility="noHideDescendants"/>
+ <com.android.systemui.DockBatteryLevelTextView android:id="@+id/dock_battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:paddingEnd="@dimen/battery_level_padding_end"
+ android:textColor="@color/status_bar_battery_level_text_color"
android:visibility="gone"
android:textSize="@dimen/battery_level_text_size"
android:importantForAccessibility="noHideDescendants"/>
@@ -73,7 +83,7 @@
android:gravity="center_vertical"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#ffffff"
+ android:textColor="@color/keyguard_carrier_text_color"
android:singleLine="true" />
</com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/layout/lockscreen_shortcuts.xml b/packages/SystemUI/res/layout/lockscreen_shortcuts.xml
new file mode 100644
index 0000000..fec5e83
--- /dev/null
+++ b/packages/SystemUI/res/layout/lockscreen_shortcuts.xml
@@ -0,0 +1,65 @@
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+
+ <ImageView
+ android:id="@+id/phone_button"
+ android:gravity="center_horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:src="@drawable/lockscreen_shortcuts_phone_background" />
+
+ <TextView
+ android:textSize="15sp"
+ android:textColor="@color/lockscreen_message_text_color"
+ android:gravity="center"
+ android:layout_below="@id/phone_button"
+ android:layout_alignStart="@id/phone_button"
+ android:layout_alignEnd="@id/phone_button"
+ android:text="@string/lockscreen_message"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent" />
+
+ <RelativeLayout
+ android:layout_alignEnd="@id/phone_button"
+ android:layout_alignStart="@id/phone_button"
+ android:layout_alignBottom="@id/phone_button"
+ android:layout_marginStart="@dimen/phone_side_padding"
+ android:layout_marginEnd="@dimen/phone_side_padding"
+ android:paddingBottom="@dimen/phone_bottom_padding"
+ android:clipChildren="false"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/phone_height">
+ <ImageView
+ android:layout_marginStart="@dimen/lockscreen_icon_side_padding"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:clickable="true"
+ android:scaleType="center"
+ android:id="@+id/left_button"
+ android:layout_width="@dimen/keyguard_affordance_width"
+ android:layout_height="@dimen/keyguard_affordance_height" />
+ <ImageView
+ android:id="@+id/middle_button"
+ android:tint="@color/lockscreen_middle_button_tint_color"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+ android:scaleType="center"
+ android:src="@drawable/ic_lock_24dp"
+ android:layout_width="@dimen/keyguard_affordance_width"
+ android:layout_height="@dimen/keyguard_affordance_height" />
+ <ImageView
+ android:layout_marginEnd="@dimen/lockscreen_icon_side_padding"
+ android:id="@+id/right_button"
+ android:clickable="true"
+ android:scaleType="center"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_width="@dimen/keyguard_affordance_width"
+ android:layout_height="@dimen/keyguard_affordance_height" />
+ </RelativeLayout>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/mid_navigation_bar_land.xml b/packages/SystemUI/res/layout/mid_navigation_bar_land.xml
new file mode 100644
index 0000000..6a1f7aa
--- /dev/null
+++ b/packages/SystemUI/res/layout/mid_navigation_bar_land.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015 The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/nav_buttons">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/ime_switcher"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:contentDescription="@string/accessibility_ime_switch_button"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_ime_switcher_default"
+ android:visibility="invisible" />
+
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/one"
+ android:scaleType="centerInside"
+ android:layout_height="40dp"
+ android:layout_width="match_parent"
+ android:layout_weight="0" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true"/>
+ </FrameLayout>
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ android:gravity="center_vertical"
+ android:id="@+id/mid_nav_buttons"
+ android:layout_gravity="center_vertical"
+ android:clipToPadding="false"
+ android:animateLayoutChanges="true">
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/two"
+ android:scaleType="centerInside"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ <View
+ android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/three"
+ android:scaleType="centerInside"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <View
+ android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/four"
+ android:scaleType="centerInside"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ <View
+ android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/five"
+ android:scaleType="centerInside"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ </LinearLayout>
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_right"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/six"
+ android:scaleType="centerInside"
+ android:layout_height="40dp"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/mid_navigation_bar_port.xml b/packages/SystemUI/res/layout/mid_navigation_bar_port.xml
new file mode 100644
index 0000000..6dfdc16
--- /dev/null
+++ b/packages/SystemUI/res/layout/mid_navigation_bar_port.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015 The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/nav_buttons">
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent" >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:visibility="gone"
+ android:layout_width="40dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/one"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside" />
+ </FrameLayout>
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:id="@+id/mid_nav_buttons"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
+ android:animateLayoutChanges="true">
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/two"
+ android:scaleType="centerInside"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/three"
+ android:scaleType="centerInside"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ systemui:keyRepeat="true"
+ android:layout_weight="0" />
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/four"
+ android:scaleType="centerInside"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ <View
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/five"
+ android:scaleType="centerInside"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ systemui:keyRepeat="true" />
+ </LinearLayout>
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent" >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:background="#FFAA0000"
+ android:id="@+id/ime_switcher"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_weight="0"
+ android:layout_height="match_parent"
+ android:contentDescription="@string/accessibility_ime_switch_button"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_ime_switcher_default"
+ android:visibility="invisible" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/six"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside" />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/dpad_right"
+ android:visibility="gone"
+ android:layout_width="40dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="centerInside"
+ systemui:keyRepeat="true"/>
+ </FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/mland.xml b/packages/SystemUI/res/layout/mland.xml
index d1b6d00..5ec0f7f 100644
--- a/packages/SystemUI/res/layout/mland.xml
+++ b/packages/SystemUI/res/layout/mland.xml
@@ -48,7 +48,7 @@
android:layout_height="48dp"
android:scaleType="fitCenter"
android:layout_gravity="center"
- android:tint="#000000"
+ android:tint="@color/play_button_image_tint_color"
android:src="@drawable/play"
/>
<TextView
@@ -58,7 +58,7 @@
android:layout_gravity="center"
android:alpha="0"
android:textSize="40dp"
- android:textColor="#000000"
+ android:textColor="@color/play_button_text_color"
/>
</FrameLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/mland_scorefield.xml b/packages/SystemUI/res/layout/mland_scorefield.xml
index 0ed72e4..31e4b4b 100644
--- a/packages/SystemUI/res/layout/mland_scorefield.xml
+++ b/packages/SystemUI/res/layout/mland_scorefield.xml
@@ -22,7 +22,7 @@
android:textStyle="bold"
android:textSize="22sp"
android:gravity="center"
- android:textColor="#FFAAAAAA"
+ android:textColor="@color/mland_scorefield_text_color"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="4dp"
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 6ae5cf3..abdbaf7 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -17,31 +17,44 @@
** limitations under the License.
*/
-->
-<FrameLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/mobile_combo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- >
- <com.android.systemui.statusbar.AnimatedImageView
- android:theme="@style/DualToneLightTheme"
- android:id="@+id/mobile_signal"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- systemui:hasOverlappingRendering="false"
- />
- <com.android.systemui.statusbar.AnimatedImageView
- android:theme="@style/DualToneDarkTheme"
- android:id="@+id/mobile_signal_dark"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:alpha="0.0"
- systemui:hasOverlappingRendering="false"
- />
+ android:orientation="horizontal">
+ <FrameLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ >
+ <com.android.systemui.statusbar.AnimatedImageView
+ android:theme="@style/DualToneLightTheme"
+ android:id="@+id/mobile_signal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ systemui:hasOverlappingRendering="false"
+ />
+ <com.android.systemui.statusbar.AnimatedImageView
+ android:theme="@style/DualToneDarkTheme"
+ android:id="@+id/mobile_signal_dark"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:alpha="0.0"
+ systemui:hasOverlappingRendering="false"
+ />
+ <ImageView
+ android:id="@+id/mobile_type"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ />
+ </FrameLayout>
+
<ImageView
- android:id="@+id/mobile_type"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- />
-</FrameLayout>
+ android:id="@+id/mobile_roaming"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:visibility="gone"
+ android:src="@drawable/stat_sys_data_roaming"
+ />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index d58664f..f8f59da 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -4,7 +4,7 @@
**
** Copyright 2011, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
+** 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
**
@@ -37,81 +37,10 @@
android:orientation="horizontal"
android:clipChildren="false"
android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
+ android:id="@+id/container"
>
- <!-- navigation controls -->
- <View
- android:layout_width="@dimen/navigation_side_padding"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_back"
- />
- <View
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
- systemui:keyCode="3"
- systemui:keyRepeat="false"
- android:layout_weight="0"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_home"
- />
- <View
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:layout_weight="0"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_recent"
- />
- <FrameLayout
- android:layout_width="@dimen/navigation_side_padding"
- android:layout_height="match_parent"
- android:layout_weight="0" >
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/menu"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:contentDescription="@string/accessibility_menu"
- android:src="@drawable/ic_sysbar_menu"
- android:visibility="invisible"
- android:scaleType="centerInside"
- android:layout_gravity="end"
- systemui:keyCode="82" />
-
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:contentDescription="@string/accessibility_ime_switch_button"
- android:scaleType="centerInside"
- android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible"
- android:layout_gravity="end" />
- </FrameLayout>
+ <include layout="@layout/mid_navigation_bar_port"/>
</LinearLayout>
@@ -120,20 +49,21 @@
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
+ android:gravity="center_horizontal"
+ android:layout_marginStart="40dp"
+ android:layout_marginEnd="40dp"
+ android:layout_gravity="center_horizontal"
android:id="@+id/lights_out"
android:visibility="gone"
>
<ImageView
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
- android:layout_marginStart="@dimen/navigation_side_padding"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
/>
<View
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
@@ -143,23 +73,18 @@
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
/>
<View
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<ImageView
android:layout_width="@dimen/navigation_key_width"
- android:layout_marginEnd="@dimen/navigation_side_padding"
android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
/>
</LinearLayout>
@@ -183,109 +108,41 @@
android:paddingTop="0dp"
>
- <LinearLayout
+ <LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
android:clipChildren="false"
android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
+ android:id="@+id/container"
>
- <!-- navigation controls -->
- <FrameLayout
- android:layout_weight="0"
- android:layout_width="match_parent"
- android:layout_height="@dimen/navigation_side_padding" >
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="match_parent"
- android:layout_height="@dimen/navigation_extra_key_width"
- android:contentDescription="@string/accessibility_ime_switch_button"
- android:scaleType="centerInside"
- android:src="@drawable/ic_ime_switcher_default"
- android:layout_gravity="top"
- android:visibility="invisible" />
-
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/menu"
- android:layout_width="match_parent"
- android:layout_height="40dp"
- android:contentDescription="@string/accessibility_menu"
- android:src="@drawable/ic_sysbar_menu"
- android:scaleType="centerInside"
- android:layout_gravity="top"
- android:visibility="invisible"
- systemui:keyCode="82" />
- </FrameLayout>
+ <include layout="@layout/mid_navigation_bar_land"/>
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <View
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_home"
- android:scaleType="center"
- systemui:keyCode="3"
- systemui:keyRepeat="false"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <View
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_back"
- android:scaleType="center"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <View
- android:layout_height="@dimen/navigation_side_padding"
- android:layout_width="match_parent"
- android:layout_weight="0"
- android:visibility="invisible"
- />
</LinearLayout>
<!-- lights out layout to match exactly -->
- <LinearLayout
+ <LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_marginTop="40dp"
+ android:layout_marginBottom="40dp"
android:id="@+id/lights_out"
android:visibility="gone"
>
<ImageView
android:layout_height="@dimen/navigation_key_width"
- android:layout_marginTop="@dimen/navigation_side_padding"
android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
/>
<View
- android:layout_height="match_parent"
+ android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
@@ -295,23 +152,18 @@
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
/>
<View
- android:layout_height="match_parent"
+ android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<ImageView
android:layout_height="@dimen/navigation_key_width"
- android:layout_marginBottom="@dimen/navigation_side_padding"
android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
+ android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar_edit_menu_item.xml b/packages/SystemUI/res/layout/navigation_bar_edit_menu_item.xml
new file mode 100644
index 0000000..d951f5b
--- /dev/null
+++ b/packages/SystemUI/res/layout/navigation_bar_edit_menu_item.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015 The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/key_icon"
+ android:layout_width="80dip"
+ android:layout_height="match_parent"
+ android:padding="4dip"
+ android:scaleType="centerInside"/>
+
+ <TextView
+ android:id="@+id/key_text"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:textAppearance="?android:attr/textAppearanceListItemSmall"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:gravity="center_vertical"
+ android:paddingEnd="16dip"
+ android:ellipsize="marquee"/>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index d52c274..effa302 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2014, The Android Open Source Project
+ Copyright (C) 2015 The CyanogenMod Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -82,11 +82,21 @@
android:layout_height="match_parent"
android:layout_weight="0"
android:gravity="center"
- android:src="@drawable/ic_settings"
+ android:src="@drawable/notification_guts_ic_settings"
android:visibility="gone"
/>
<ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
+ android:id="@+id/notification_inspect_filter_notification"
+ android:layout_width="52dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:gravity="center"
+ android:src="@drawable/notification_guts_ic_ringer_mute"
+ android:visibility="gone"
+ />
+
+ <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
android:id="@+id/notification_inspect_item"
android:layout_width="52dp"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/profiles_detail_view.xml b/packages/SystemUI/res/layout/profiles_detail_view.xml
new file mode 100644
index 0000000..c366868
--- /dev/null
+++ b/packages/SystemUI/res/layout/profiles_detail_view.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<com.android.systemui.qs.tiles.ProfilesDetailView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:orientation="vertical">
+
+ <ListView
+ android:id="@android:id/list"
+ android:divider="@null"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+</com.android.systemui.qs.tiles.ProfilesDetailView>
diff --git a/packages/SystemUI/res/layout/qs_custom_detail.xml b/packages/SystemUI/res/layout/qs_custom_detail.xml
new file mode 100644
index 0000000..6aa1fc0
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_custom_detail.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/detail_exterior_padding"
+ android:paddingStart="@dimen/detail_exterior_padding"
+ android:paddingEnd="@dimen/detail_exterior_padding">
+
+ <LinearLayout android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
+
+ <ImageView android:id="@+id/custom_qs_tile_icon"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_marginEnd="12dp" />
+
+ <LinearLayout android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/custom_qs_tile_title"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary"/>
+
+ <TextView android:id="@+id/custom_qs_tile_package "
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="2dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSub"/>
+
+ <TextView android:id="@+id/custom_qs_tile_content_description"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="2dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSub" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_custom_detail_remote.xml b/packages/SystemUI/res/layout/qs_custom_detail_remote.xml
new file mode 100644
index 0000000..bdbe6bb
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_custom_detail_remote.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/detail_exterior_padding"
+ android:paddingStart="@dimen/detail_exterior_padding"
+ android:paddingEnd="@dimen/detail_exterior_padding">
+
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index ddff0f0..5058314 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -18,7 +18,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qs_detail_background"
- android:paddingBottom="8dp"
+ android:paddingTop="@dimen/detail_exterior_padding"
+ android:paddingBottom="@dimen/detail_exterior_padding"
android:orientation="vertical">
<FrameLayout
@@ -44,6 +45,16 @@
android:focusable="true" />
<TextView
+ android:id="@android:id/button3"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:minWidth="88dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:focusable="true" />
+
+ <TextView
android:id="@android:id/button1"
style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index 5a96dc3..6f07543 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -37,4 +37,15 @@
android:clickable="false"
android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
-</com.android.keyguard.AlphaOptimizedLinearLayout> \ No newline at end of file
+ <TextView
+ android:id="@+id/done"
+ android:text="@string/quick_settings_done"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:minWidth="88dp"
+ android:paddingRight="12dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:clickable="false"
+ android:focusable="false" />
+</com.android.keyguard.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index ccdddf7..1ec4952 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -19,8 +19,6 @@
android:layout_height="wrap_content"
android:minHeight="@dimen/qs_detail_item_height"
android:background="@drawable/btn_borderless_rect"
- android:clickable="true"
- android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal" >
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index c22e42c..4ad82cb 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -18,9 +18,9 @@
<com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="16dp"
- android:paddingStart="16dp"
- android:paddingEnd="16dp">
+ android:paddingTop="@dimen/detail_exterior_padding"
+ android:paddingStart="@dimen/detail_exterior_padding"
+ android:paddingEnd="@dimen/detail_exterior_padding">
<LinearLayout
android:id="@android:id/list"
diff --git a/packages/SystemUI/res/layout/qs_detail_items_grid.xml b/packages/SystemUI/res/layout/qs_detail_items_grid.xml
new file mode 100644
index 0000000..617acfb
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_items_grid.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2015 The CyanogenMod 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
+ -->
+
+<!-- GridView -->
+<com.android.systemui.qs.QSDetailItemsGrid
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:numColumns="3"
+ sysui:verticalSpacing="4dp"
+ sysui:horizontalSpacing="4dp" /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_items_list.xml b/packages/SystemUI/res/layout/qs_detail_items_list.xml
new file mode 100644
index 0000000..09021f9
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_items_list.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<!-- extends LinearLayout -->
+<com.android.systemui.qs.QSDetailItemsList xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:minHeight="200dp"
+ android:paddingTop="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
+
+ <ListView
+ android:id="@android:id/list"
+ android:divider="@null"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" />
+
+ <LinearLayout
+ android:id="@android:id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="56dp"
+ android:layout_height="56dp" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailEmpty" />
+ </LinearLayout>
+
+</com.android.systemui.qs.QSDetailItemsList>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 1873168..2807bb0 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -19,13 +19,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/qs_background_primary"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
+ android:paddingBottom="12dp"
android:elevation="2dp">
- <com.android.systemui.qs.QSPanel
+ <com.android.systemui.qs.QSDragPanel
android:id="@+id/quick_settings_panel"
- android:background="#0000"
+ android:background="@color/quick_settings_panel_background"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.android.systemui.qs.QSContainer>
diff --git a/packages/SystemUI/res/layout/qs_settings.xml b/packages/SystemUI/res/layout/qs_settings.xml
new file mode 100644
index 0000000..b7c8d60
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_settings.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The CyanogenMod 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.
+-->
+<com.android.systemui.qs.QSSettings
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/quick_settings_settings_recursion_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:gravity="center_vertical"
+ android:textColor="@color/qs_title_text_color"
+ android:text="@string/quick_settings_title_header"/>
+
+ <!-- show weather -->
+ <com.android.systemui.qs.QSBooleanSettingRow
+ style="@style/SettingRow"
+ android:key="status_bar_show_weather"
+ android:title="@string/quick_settings_title_show_weather"
+ systemui:defaultValue="1"
+ systemui:table="cm_system"/>
+
+ <!-- brightness slider -->
+ <com.android.systemui.qs.QSBooleanSettingRow
+ style="@style/SettingRow"
+ android:key="qs_show_brightness_slider"
+ android:title="@string/quick_settings_title_show_brightness_slider"
+ systemui:defaultValue="1"
+ systemui:table="cm_system"/>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:gravity="center_vertical"
+ android:textColor="@color/qs_title_text_color"
+ android:text="@string/quick_settings_title_tiles"/>
+
+ <!-- first row large -->
+ <com.android.systemui.qs.QSBooleanSettingRow
+ style="@style/SettingRow"
+ android:title="@string/quick_settings_title_enlarge_first_row"
+ android:key="sysui_qs_main_tiles"
+ systemui:defaultValue="1"
+ systemui:table="cm_secure"/>
+
+ <com.android.systemui.qs.QSBooleanSettingRow
+ style="@style/SettingRow"
+ android:title="@string/quick_settings_title_advanced_location"
+ android:key="qs_location_advanced"
+ systemui:defaultValue="0"
+ systemui:table="cm_secure"/>
+
+ <LinearLayout
+ android:id="@+id/reset_tiles"
+ style="@style/SettingRow">
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="24dp"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:id="@+id/title"
+ android:textColor="@color/qs_tile_reset_to_default_text_color"
+ android:text="@string/quick_settings_tile_reset_to_default"
+ android:contentDescription="@null"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+</com.android.systemui.qs.QSSettings>
+
diff --git a/packages/SystemUI/res/layout/qs_settings_row.xml b/packages/SystemUI/res/layout/qs_settings_row.xml
new file mode 100644
index 0000000..bc7f909
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_settings_row.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The CyanogenMod 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="24dp"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:id="@+id/title"
+ android:textColor="@color/qs_row_text_color"
+ android:contentDescription="@null"/>
+
+ <Switch
+ android:id="@+id/switcher"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
+ />
+</merge>
diff --git a/packages/SystemUI/res/layout/qs_tile_category_row.xml b/packages/SystemUI/res/layout/qs_tile_category_row.xml
new file mode 100644
index 0000000..1736221
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_category_row.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/qs_detail_item_height"
+ android:background="@drawable/btn_borderless_rect"
+ android:gravity="center_vertical"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_weight="1"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:ellipsize="end"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@android:id/icon2"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_tile_child_row.xml b/packages/SystemUI/res/layout/qs_tile_child_row.xml
new file mode 100644
index 0000000..bb30729
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_child_row.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/qs_detail_item_height"
+ android:background="@drawable/btn_borderless_rect"
+ android:gravity="center_vertical"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginStart="72dp"
+ android:layout_marginEnd="12dp" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_weight="1"
+ android:layout_marginStart="12dp"
+ android:layout_width="0dp"
+ android:gravity="center_vertical"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_tile_top.xml b/packages/SystemUI/res/layout/qs_tile_top.xml
new file mode 100644
index 0000000..a302c73
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_top.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The CyanogenMod 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.
+-->
+<com.android.systemui.qs.QSPanelTopView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/qs_panel_top"
+ android:layout_width="match_parent"
+ android:paddingTop="@dimen/qs_brightness_padding_top"
+ android:clipToPadding="false"
+ android:layout_height="wrap_content">
+
+ <!-- brightness -->
+ <include android:id="@+id/brightness_container"
+ layout="@layout/quick_settings_brightness_dialog"/>
+
+ <!-- delete target -->
+ <LinearLayout
+ android:id="@+id/delete_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/delete_target"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_delete"
+ />
+ </LinearLayout>
+
+ <!-- edit instructions & add target -->
+ <LinearLayout
+ android:id="@+id/edit_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:layout_weight="1"
+ android:textColor="@color/qs_edit_header_instruction_text_color"
+ android:text="@string/qs_tile_edit_header_instruction"
+ android:contentDescription="@null"/>
+
+ <ImageView
+ android:id="@+id/add_target"
+ android:layout_width="20dp"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:src="@drawable/ic_add_circle_qs"
+ />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/qs_toast"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_width="match_parent"
+ android:textColor="@color/quick_settings_toast_color"/>
+
+
+</com.android.systemui.qs.QSPanelTopView>
+
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index af22f03..666f878 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -24,7 +24,7 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="top|center_horizontal"
- android:paddingTop="16dp"
+ android:paddingTop="@dimen/detail_exterior_padding"
android:minHeight="112dp"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout/quick_settings_notification_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_notification_brightness_dialog.xml
new file mode 100644
index 0000000..1f51fe3
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_notification_brightness_dialog.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ style="@style/BrightnessDialogContainer">
+
+ <com.android.systemui.settings.ToggleSlider
+ android:id="@+id/notification_brightness_slider"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:contentDescription="@string/accessibility_notification_brightness"
+ android:importantForAccessibility="no" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 4b68e77..bd3e3bc 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -21,8 +21,8 @@
android:layout_gravity="center"
android:gravity="center"
android:textSize="16sp"
- android:textColor="#ffffffff"
+ android:textColor="@color/recents_empty_message_text_color"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif"
- android:background="#80000000"
- android:visibility="gone" /> \ No newline at end of file
+ android:background="@color/recents_empty_background_color"
+ android:visibility="gone" />
diff --git a/packages/SystemUI/res/layout/recents_search_bar.xml b/packages/SystemUI/res/layout/recents_search_bar.xml
index 915283e..f9bd02c 100644
--- a/packages/SystemUI/res/layout/recents_search_bar.xml
+++ b/packages/SystemUI/res/layout/recents_search_bar.xml
@@ -23,7 +23,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/recents_search_bar_label"
- android:textColor="#99ffffff"
+ android:textColor="@color/recents_search_bar_label_text_color"
android:textSize="18sp"
android:textAllCaps="true" />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 477d9d7..423ecb8 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -36,7 +36,7 @@
android:layout_marginStart="64dp"
android:layout_marginEnd="64dp"
android:textSize="16sp"
- android:textColor="#ffffffff"
+ android:textColor="@color/task_view_header_text_color"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif-medium"
android:singleLine="true"
@@ -63,4 +63,4 @@
android:background="@drawable/recents_button_bg"
android:visibility="invisible"
android:src="@drawable/recents_dismiss_light" />
-</com.android.systemui.recents.views.TaskViewHeader> \ No newline at end of file
+</com.android.systemui.recents.views.TaskViewHeader>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request.xml b/packages/SystemUI/res/layout/screen_pinning_request.xml
index fea45cc..af203ce 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request.xml
@@ -28,12 +28,6 @@
android:layout_height="wrap_content"
layout="@layout/screen_pinning_request_text_area" />
- <View
- android:id="@+id/spacer"
- android:layout_width="@dimen/screen_pinning_request_width"
- android:layout_height="18dp"
- android:background="@color/screen_pinning_request_bg" />
-
<include
android:layout_width="@dimen/screen_pinning_request_width"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
index df957f4..6d24b0c 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
@@ -29,7 +29,7 @@
android:layout_height="wrap_content"
android:paddingEnd="48dp"
android:paddingStart="48dp"
- android:paddingTop="43dp"
+ android:paddingTop="18dp"
android:text="@string/screen_pinning_title"
android:textColor="@color/screen_pinning_primary_text"
android:textSize="24sp" />
@@ -50,7 +50,7 @@
android:id="@+id/screen_pinning_ok_button"
style="@android:style/Widget.Material.Button"
android:layout_width="wrap_content"
- android:layout_height="36dp"
+ android:layout_height="54dp"
android:layout_alignParentEnd="true"
android:layout_below="@+id/screen_pinning_description"
android:layout_marginEnd="40dp"
@@ -59,14 +59,14 @@
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:text="@string/screen_pinning_positive"
- android:textColor="@android:color/white"
+ android:textColor="@color/screen_pinning_description_text_color"
android:textSize="14sp" />
<Button
android:id="@+id/screen_pinning_cancel_button"
style="@android:style/Widget.Material.Button"
android:layout_width="wrap_content"
- android:layout_height="36dp"
+ android:layout_height="54dp"
android:layout_alignTop="@id/screen_pinning_ok_button"
android:layout_marginEnd="4dp"
android:layout_toStartOf="@id/screen_pinning_ok_button"
@@ -74,7 +74,7 @@
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:text="@string/screen_pinning_negative"
- android:textColor="@android:color/white"
+ android:textColor="@color/screen_pinning_cancel_button_text_color"
android:textSize="14sp" />
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index f8bd6fd..e2c1810 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -25,7 +25,6 @@
android:layout_width="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
- android:paddingEnd="@dimen/signal_cluster_battery_padding"
>
<ImageView
android:id="@+id/vpn"
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index a5b3a83..51f7df7 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -62,6 +62,16 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
+ <com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/left_clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:singleLine="true"
+ android:paddingEnd="6dip"
+ android:gravity="center"
+ android:visibility="gone"
+ />
<com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
@@ -85,6 +95,23 @@
<include layout="@layout/system_icons" />
+ <com.android.systemui.BatteryLevelTextView android:id="@+id/battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:textSize="@dimen/battery_level_text_size" />
+
+ <com.android.systemui.BatteryLevelTextView android:id="@+id/dock_battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:textSize="@dimen/battery_level_text_size"
+ android:visibility="gone"/>
+
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
@@ -97,4 +124,22 @@
</com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
+ <com.android.keyguard.AlphaOptimizedLinearLayout
+ android:id="@+id/center_clock_layout"
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/center_clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:singleLine="true"
+ android:gravity="center"
+ android:visibility="gone"
+ />
+ </com.android.keyguard.AlphaOptimizedLinearLayout>
</com.android.systemui.statusbar.phone.PhoneStatusBarView>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index f7bbce0..996fb71 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -57,8 +57,8 @@
android:layout_marginTop="@dimen/status_bar_header_height_expanded"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/notification_side_padding"
- android:layout_marginRight="@dimen/notification_side_padding"/>
+ android:layout_marginStart="@dimen/qs_panel_side_padding"
+ android:layout_marginEnd="@dimen/qs_panel_side_padding"/>
<!-- A view to reserve space for the collapsed stack -->
<!-- Layout height: notification_min_height + bottom_stack_peek_amount -->
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 5eca471..a017a2e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -23,10 +23,10 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="@dimen/status_bar_header_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:paddingStart="@dimen/notification_side_padding"
- android:paddingEnd="@dimen/notification_side_padding"
+ android:paddingStart="@dimen/notification_header_side_padding"
+ android:paddingEnd="@dimen/notification_header_side_padding"
android:baselineAligned="false"
- android:elevation="4dp"
+ android:elevation="@dimen/status_bar_expanded_header_elevation"
android:background="@drawable/notification_header_bg"
android:clickable="true"
android:focusable="true"
@@ -63,7 +63,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="36dp"
- android:tint="#4DFFFFFF"
+ android:tint="@color/tuner_icon_tint"
android:tintMode="src_in"
android:visibility="invisible"
android:src="@drawable/tuner" />
@@ -85,15 +85,25 @@
>
<include layout="@layout/system_icons" />
</FrameLayout>
- <TextView android:id="@+id/battery_level"
+ <com.android.systemui.BatteryLevelTextView android:id="@+id/battery_level_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/header_battery_margin_expanded"
android:paddingEnd="@dimen/battery_level_padding_end"
- android:textColor="#ffffff"
+ android:textColor="@color/status_bar_battery_level_text_color"
android:textSize="@dimen/battery_level_text_size"
android:importantForAccessibility="noHideDescendants"/>
+ <com.android.systemui.DockBatteryLevelTextView android:id="@+id/dock_battery_level_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_expanded"
+ android:paddingEnd="@dimen/battery_level_padding_end"
+ android:textColor="@color/status_bar_battery_level_text_color"
+ android:textSize="@dimen/battery_level_text_size"
+ android:importantForAccessibility="noHideDescendants"
+ android:visibility="gone"/>
</LinearLayout>
<TextView
@@ -122,6 +132,7 @@
android:layout_marginStart="16dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+ android:background="@drawable/ripple_drawable"
android:layout_below="@id/clock"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm"
/>
@@ -132,18 +143,24 @@
android:layout_marginStart="16dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+ android:background="@drawable/ripple_drawable"
android:layout_below="@id/clock"
systemui:datePattern="eeeeMMMMd"
/>
</FrameLayout>
- <include layout="@layout/split_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_above="@id/date_group"
- android:id="@+id/clock"
- />
+ <FrameLayout
+ android:id="@+id/clock"
+ android:layout_marginStart="16dp"
+ android:layout_above="@id/date_group"
+ android:background="@drawable/ripple_drawable"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <include layout="@layout/split_clock_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+ </FrameLayout>
<com.android.systemui.statusbar.AlphaOptimizedButton android:id="@+id/alarm_status"
android:layout_width="wrap_content"
@@ -153,16 +170,48 @@
android:layout_marginBottom="4dp"
android:drawablePadding="6dp"
android:drawableStart="@drawable/ic_access_alarms_small"
- android:textColor="#64ffffff"
+ android:textColor="@color/status_bar_alarm_status_text_color"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:paddingEnd="6dp"
android:paddingStart="6dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
- android:background="?android:attr/selectableItemBackground"
+ android:background="@drawable/ripple_drawable"
android:visibility="gone"
/>
+ <LinearLayout
+ android:id="@+id/weather_container"
+ android:background="@drawable/ripple_drawable"
+ android:orientation="vertical"
+ android:layout_marginBottom="@dimen/clock_collapsed_bottom_margin"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content">
+ <TextView
+ android:id="@+id/weather_line_1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="@dimen/status_bar_weather_padding_end"
+ android:gravity="right"
+ android:textColor="@color/status_bar_temperature_text_color"
+ android:textSize="@dimen/weather_text_size"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.WeatherTemp"
+ android:importantForAccessibility="noHideDescendants"/>
+ <TextView
+ android:id="@+id/weather_line_2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="@dimen/status_bar_weather_padding_end"
+ android:gravity="right"
+ android:textColor="@color/status_bar_temperature_location_text_color"
+ android:textSize="@dimen/weather_text_size"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.WeatherLocation"
+ android:importantForAccessibility="noHideDescendants"/>
+ </LinearLayout>
+
<include
android:id="@+id/qs_detail_header"
layout="@layout/qs_detail_header"
@@ -191,7 +240,7 @@
android:fontFamily="sans-serif-condensed"
android:textSize="11dp"
android:textStyle="bold"
- android:textColor="#00A040"
+ android:textColor="@color/header_debug_info_text_color"
android:padding="2dp"
/>
diff --git a/packages/SystemUI/res/layout/status_bar_no_notifications.xml b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
index dd501d4..f4d1f1b 100644
--- a/packages/SystemUI/res/layout/status_bar_no_notifications.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
@@ -27,7 +27,7 @@
android:layout_height="64dp"
android:paddingTop="12dp"
android:gravity="top|center_horizontal"
- android:textColor="#ffffff"
+ android:textColor="@color/no_notifications_text_color"
android:textSize="20sp"
android:text="@string/empty_shade_text"/>
</com.android.systemui.statusbar.EmptyShadeView>
diff --git a/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml b/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
index 1675773..be18569 100644
--- a/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
@@ -28,7 +28,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
- android:textColor="@android:color/holo_blue_light"
+ android:textColor="@color/no_recent_apps_text_color"
android:text="@string/status_bar_no_recent_apps"
android:gravity="center_horizontal"
android:layout_gravity="center"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index f699fce..bc8086d 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -44,7 +44,7 @@
android:layout_gravity="center_vertical"
android:background="@drawable/keyguard_overflow_number_background"
android:gravity="center"
- android:textColor="#ff686868"
+ android:textColor="@color/keyguard_overflow_number_text_color"
android:textStyle="bold"
android:textSize="14dp"
/>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml b/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
index e220a16..d99a9f6 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
@@ -25,6 +25,6 @@
android:id="@+id/speedbump_line"
android:layout_width="match_parent"
android:layout_height="1dp"
- android:background="#6fdddddd"
+ android:background="@color/speedbump_line_divider"
android:layout_gravity="center_vertical"/>
</com.android.systemui.statusbar.SpeedBumpView>
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index 062e6cb..d28b870 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -55,7 +55,7 @@
android:layout_centerVertical="true"
android:gravity="center"
android:paddingTop="26dp"
- android:textColor="#666666"
+ android:textColor="@color/toggle_slider_text_color"
android:textSize="12sp"
android:visibility="gone"
/>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index e42ce66..c6178a0 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -18,12 +18,14 @@
-->
<!-- This is the combined status bar / notification panel window. -->
-<com.android.systemui.statusbar.phone.StatusBarWindowView
+<com.android.systemui.statusbar.phone.NavBarInsetLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:fitsSystemWindows="true">
+ android:focusable="true"
+ android:fitsSystemWindows="true"
+ android:descendantFocusability="afterDescendants">
<com.android.systemui.statusbar.BackDropView
android:id="@+id/backdrop"
@@ -43,19 +45,34 @@
android:visibility="invisible" />
</com.android.systemui.statusbar.BackDropView>
- <com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_behind"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:importantForAccessibility="no"
- sysui:ignoreRightInset="true"
- />
-
- <com.android.systemui.statusbar.AlphaOptimizedView
- android:id="@+id/heads_up_scrim"
- android:layout_width="match_parent"
- android:layout_height="@dimen/heads_up_scrim_height"
- android:background="@drawable/heads_up_scrim"
- android:importantForAccessibility="no"/>
+ <com.android.systemui.statusbar.phone.NavBarInsetLayout
+ android:id="@+id/scrimview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="visible"
+ sysui:ignoreRightInset="true"
+ android:fitsSystemWindows="true">
+ <com.android.systemui.statusbar.ScrimView
+ android:id="@+id/scrim_behind"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ sysui:ignoreRightInset="true"
+ android:importantForAccessibility="no"/>
+ <com.android.systemui.statusbar.AlphaOptimizedView
+ android:id="@+id/heads_up_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/heads_up_scrim_height"
+ android:background="@drawable/heads_up_scrim"
+ android:importantForAccessibility="no"/>
+ <com.android.systemui.statusbar.VisualizerView
+ android:id="@+id/visualizerview"
+ android:gravity="bottom"
+ android:layout_gravity="bottom"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ sysui:ignoreRightInset="true"
+ android:visibility="visible"/>
+ </com.android.systemui.statusbar.phone.NavBarInsetLayout>
<include layout="@layout/status_bar"
android:layout_width="match_parent"
@@ -97,4 +114,4 @@
sysui:ignoreRightInset="true"
/>
-</com.android.systemui.statusbar.phone.StatusBarWindowView>
+</com.android.systemui.statusbar.phone.NavBarInsetLayout>
diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml
index 943e846..82e0667 100644
--- a/packages/SystemUI/res/layout/system_icons.xml
+++ b/packages/SystemUI/res/layout/system_icons.xml
@@ -36,5 +36,14 @@
<com.android.systemui.BatteryMeterView android:id="@+id/battery"
android:layout_height="14.5dp"
android:layout_width="9.5dp"
- android:layout_marginBottom="@dimen/battery_margin_bottom"/>
-</LinearLayout> \ No newline at end of file
+ android:layout_marginBottom="@dimen/battery_margin_bottom"
+ android:layout_marginStart="@dimen/signal_cluster_battery_padding"/>
+
+ <com.android.systemui.DockBatteryMeterView android:id="@+id/dock_battery"
+ android:layout_height="14.5dp"
+ android:layout_width="9.5dp"
+ android:layout_marginBottom="@dimen/battery_margin_bottom"
+ android:layout_marginStart="@dimen/signal_cluster_battery_padding"
+ android:visibility="gone"/>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/unlock_fab.xml b/packages/SystemUI/res/layout/unlock_fab.xml
new file mode 100644
index 0000000..c80bc19
--- /dev/null
+++ b/packages/SystemUI/res/layout/unlock_fab.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/show_bouncer"
+ android:layout_width="@dimen/unlock_fab_size"
+ android:layout_height="@dimen/unlock_fab_size"
+ android:layout_gravity="bottom|center_horizontal"
+ android:alpha="0.5"
+ android:src="@drawable/ic_lock_open_24dp" />
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 7617ed4..a766261 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -22,7 +22,7 @@
android:layout_marginLeft="@dimen/notification_side_padding"
android:layout_marginRight="@dimen/notification_side_padding"
android:background="@drawable/volume_dialog_background"
- android:translationZ="4dp" >
+ android:translationZ="@dimen/volume_panel_z">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/volume_expand_button"
@@ -48,4 +48,4 @@
<include layout="@layout/volume_zen_footer" />
</LinearLayout>
-</RelativeLayout> \ No newline at end of file
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 43ab4bb..1f88ef3 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -53,7 +53,7 @@
android:contentDescription="@string/accessibility_desc_close"
android:scaleType="center"
android:src="@drawable/ic_close"
- android:tint="@android:color/white" />
+ android:tint="@color/zen_ic_close_tint_color" />
<TextView
android:id="@+id/zen_introduction_message"
diff --git a/packages/SystemUI/res/menu/recent_popup_menu.xml b/packages/SystemUI/res/menu/recent_popup_menu.xml
new file mode 100644
index 0000000..9b605f9
--- /dev/null
+++ b/packages/SystemUI/res/menu/recent_popup_menu.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/recent_remove_item" android:title="@string/status_bar_recent_remove_item_title" />
+ <item android:id="@+id/recent_inspect_item" android:title="@string/status_bar_recent_inspect_item_title" />
+ <item android:id="@+id/recent_force_stop" android:title="@string/advanced_dev_option_force_stop" />
+ <item android:id="@+id/recent_wipe_app" android:title="@string/advanced_dev_option_wipe_app" />
+ <item android:id="@+id/recent_uninstall" android:title="@string/advanced_dev_option_uninstall" />
+</menu>
diff --git a/packages/SystemUI/res/values-af/cm_arrays.xml b/packages/SystemUI/res/values-af/cm_arrays.xml
new file mode 100644
index 0000000..b156d8e
--- /dev/null
+++ b/packages/SystemUI/res/values-af/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NO</item>
+ <item>O</item>
+ <item>SO</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-af/cm_strings.xml b/packages/SystemUI/res/values-af/cm_strings.xml
new file mode 100644
index 0000000..78abacd
--- /dev/null
+++ b/packages/SystemUI/res/values-af/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Swiep regs vir %1$s</string>
+ <string name="right_shortcut_hint">Swiep links vir %1$s</string>
+ <string name="lockscreen_message">Tik \'n ikoon op die linker of regter kant om \'n slot skerm kortpad toe te wys.</string>
+ <string name="lockscreen_default_target">Standaard</string>
+ <string name="select_application">Kies program</string>
+ <string name="lockscreen_choose_action_title">Kies aksie</string>
+ <string name="lockscreen_none_target">Geen</string>
+ <string name="navbar_dialog_title">Kies \'n aksie om toe te ken</string>
+ <string name="navbar_home_button">Tuis-knoppie</string>
+ <string name="navbar_recent_button">Onlangse programme knoppie</string>
+ <string name="navbar_search_button">Soek-knoppie</string>
+ <string name="navbar_back_button">Terug-knoppie</string>
+ <string name="navbar_empty_button">Los leeg</string>
+ <string name="navbar_menu_conditional_button">Kieslys knoppie (Outoverberg)</string>
+ <string name="navbar_menu_always_button">Kieslys-knoppie (Altyd sigbaar)</string>
+ <string name="navbar_menu_big_button">Kieslys-knoppie</string>
+ <string name="accessibility_dpad_left">Wyser na links</string>
+ <string name="accessibility_dpad_right">Wyser na regs</string>
+ <string name="advanced_dev_option_wipe_app">Vee program data uit</string>
+ <string name="advanced_dev_option_force_stop">Dwing stop</string>
+ <string name="advanced_dev_option_uninstall">Deïnstalleer</string>
+ <string name="accessibility_notification_brightness">Ligte herdelheidsvlak</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiele af.</string>
+ <string name="accessibility_quick_settings_profiles">Profiel: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiele afgeskakel.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profiel verander na <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inisialiseer\u2026</string>
+ <string name="led_notification_title">Ligte instellings</string>
+ <string name="led_notification_text">LED liggie word deur instellings gaktiveer</string>
+ <string name="qs_tile_edit_header_instruction">Druk en hou teëls om te herrangskik</string>
+ <string name="quick_settings_edit_label">Redigeer teëls</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Kan nie die redigeerde teël verwyder nie</string>
+ <string name="qs_tiles_reset_confirmation">Herstel vinnige instelling teëls na standaard konfigurasie?</string>
+ <string name="quick_settings_tile_reset_to_default">Herstel na standaard uitleg</string>
+ <string name="quick_settings_title_header">Hoof</string>
+ <string name="quick_settings_title_tiles">Teëls</string>
+ <string name="quick_settings_title_show_weather">Wys weer</string>
+ <string name="quick_settings_title_show_brightness_slider">Wys helderheid skuiwer</string>
+ <string name="quick_settings_title_enlarge_first_row">Vergroot eerste ry</string>
+ <string name="screen_pinning_description_no_navbar">Dit hou dit binne sig totdat jy dit ontspeld. Raak en hou die knoppie Terug om te ontspeld.</string>
+ <string name="quick_settings_custom_tile_detail_title">Pasgemaakte teël</string>
+ <string name="quick_settings_remove">Verwyder teël</string>
+ <string name="quick_settings_network_adb_label">ADB oor netwerk</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Stelsel profiele</string>
+ <string name="quick_settings_profiles_off">Profiele is afgeskakel</string>
+ <string name="quick_settings_heads_up_label">Loer boodskap</string>
+ <string name="quick_settings_battery_saver_label">Battery bespaarder</string>
+ <string name="quick_settings_caffeine_label">Kafeïen</string>
+ <string name="accessibility_quick_settings_sync_off">Sinchronisering af.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinchronisering aan.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sinchronisering afgeskakel.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sinchronisering aangeskakel.</string>
+ <string name="quick_settings_sync_label">Sinkroniseer</string>
+ <string name="quick_settings_volume_panel_label">Volume paneel</string>
+ <string name="quick_settings_usb_tether_label">USB internet verbinding</string>
+ <string name="quick_settings_screen_timeout_detail_title">Skerm afsnytyd</string>
+ <string name="quick_settings_lockscreen_label">Slotskerm</string>
+ <string name="quick_settings_ambient_display_label">Omgewingstemperatuur skerm</string>
+ <string name="quick_settings_lockscreen_label_enforced">Slotskerm afgedwing</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Afgeskakel deur profiel</string>
+ <string name="accessibility_quick_settings_screen_timeout">Skerm slaap: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Skerm slaap verander na <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Battery modus</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Battery modus: energiebesparing modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Battery modus: gebalanseerde modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Battery modus: werkverrigting modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Battery modus: doeltreffendheid modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Battery modus: vinnige modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Battery modus verander na energiebesparings modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Battery modus verander na gebalanseerde modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Battery modus verander na werkverrigting modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Battery modus verander na doeltreffendheid modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Battery modus verander na vinnige modus.</string>
+ <string name="quick_settings_performance_profile_detail_title">Battery modus</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Slotskerm af.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Slotskerm aan.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Slotskerm afgeskakel.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Slotskerm aangeskakel.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Omgewingstemperatuur vertoning af.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Omgewingstemperatuur vertoning aan.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Omgewingstemperatuur skerm vertoning is afgeskakel.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Omgewingstemperatuur skerm vertoning is aangeskakel.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Loer boodskap af.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Loer boodskap aan.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Loer boodskap is afgeskakel.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Loer boodskap is aangeskakel.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kafeïen af.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kafeïen aan.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Battery bespaarder af.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Battery bespaarder aan.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Battery bespaarder afgeskakel.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Battery bespaarder aangeskakel.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamiese teëls</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Volgende alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Kies IME</string>
+ <string name="dynamic_qs_tile_su_label">\'Root\' toegang</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay af.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: outo modus.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: dag modus.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nag modus.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: buitelug modus.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay afgeskakel.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay verander na outo modus.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay verander na dag modus.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay verander na dag modus.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay verander na buitelug modus.</string>
+ <string name="quick_settings_title_advanced_location">Drie-staat ligging</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Liggingverslaggewing: battery besparing.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Liggingverslaggewing: sensors alleenlik.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Liggingverslaggewing: hoë akkuraatheid modus.</string>
+ <string name="quick_settings_location_detail_title">Liggingsinligting modus</string>
+ <string name="quick_settings_location_battery_saving_label">Battery besparend</string>
+ <string name="quick_settings_location_gps_only_label">Slegs Toestel</string>
+ <string name="quick_settings_location_high_accuracy_label">Hoë akkuraatheid</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Plek verslagdoening verander na battery sparing modus.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Plek verslagdoening verander na sensors alleenlik modus.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Plek verslagdoening verander na hoë akkuraatheid modus.</string>
+ <string name="quick_settings_tiles_category_system">Stelsel teëls</string>
+ <string name="quick_settings_tiles_add_tiles">Voeg \'n teël by</string>
+ <string name="hotspot_apm_message">Kan nie aan mobiele netwerke koppel terwyl vliegtuig modus aan is nie. Skakel vliegtuig modus af en probeer weer.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Flitslig is aan</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Raak om af te skakel</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ar/cm_arrays.xml b/packages/SystemUI/res/values-ar/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-ar/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ar/cm_strings.xml b/packages/SystemUI/res/values-ar/cm_strings.xml
new file mode 100644
index 0000000..a59d14a
--- /dev/null
+++ b/packages/SystemUI/res/values-ar/cm_strings.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">تحريك إلى اليمين من أجل %1$s</string>
+ <string name="right_shortcut_hint">تحريك إلى اليسار من أجل %1$s</string>
+ <string name="select_application">حدد التطبيق</string>
+ <string name="lockscreen_choose_action_title">اختر إجراء</string>
+ <string name="lockscreen_none_target">لا شيء</string>
+ <string name="navbar_dialog_title">اختر الإجراء لتخصيصه</string>
+ <string name="navbar_home_button">زر الرئيسية</string>
+ <string name="navbar_recent_button">زر الأشياء الأخيرة</string>
+ <string name="navbar_search_button">زر البحث</string>
+ <string name="navbar_back_button">زر العودة</string>
+ <string name="navbar_empty_button">زر خالٍ</string>
+ <string name="navbar_menu_conditional_button">زر القائمة (الإخفاء التلقائي)</string>
+ <string name="navbar_menu_always_button">زر القائمة (يظهر دائماً)</string>
+ <string name="navbar_menu_big_button">زر القائمة</string>
+ <string name="accessibility_dpad_left">المؤشر إلى اليسار</string>
+ <string name="accessibility_dpad_right">المؤشر الى اليمين</string>
+ <string name="advanced_dev_option_wipe_app">مسح بيانات التطبيق</string>
+ <string name="advanced_dev_option_force_stop">إيقاف إجباري</string>
+ <string name="advanced_dev_option_uninstall">إلغاء التثبيت</string>
+ <string name="accessibility_quick_settings_profiles_off">إيقاف ملفات التعريف.</string>
+ <string name="accessibility_quick_settings_profiles">ملف التعريف: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">تعطيل ملفات التعريف. </string>
+ <string name="accessibility_quick_settings_profiles_changed">تم تغيير ملف التعريف إلى <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">تهيئة\u2026</string>
+ <string name="screen_pinning_description_no_navbar">ستظل ظاهرة حتى يمكنك إزالتها. المس مع الاستمرار زر العودة لإزالتها.</string>
+ <string name="quick_settings_custom_tile_detail_title">مربع مخصص</string>
+ <string name="quick_settings_remove">إزالة المربع</string>
+ <string name="quick_settings_network_adb_label">ADB عبر الشبكة</string>
+ <string name="quick_settings_compass_label">بوصلة</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">ملفات تعريف النظام</string>
+ <string name="quick_settings_profiles_off">تعطيل ملفات التعريف</string>
+ <string name="quick_settings_heads_up_label">إنذار مسبق</string>
+ <string name="quick_settings_battery_saver_label">موفر البطارية</string>
+ <string name="accessibility_quick_settings_sync_off">تعطيل المزامنة. </string>
+ <string name="accessibility_quick_settings_sync_on">تشغيل المزامنة.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">تم تعطيل المزامنة.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">تم تشغيل المزامنة.</string>
+ <string name="quick_settings_sync_label">المزامنة</string>
+ <string name="quick_settings_volume_panel_label">لوحة مستوى الصوت</string>
+ <string name="quick_settings_usb_tether_label">الربط عبر USB
+</string>
+ <string name="quick_settings_screen_timeout_detail_title">مهلة الشاشة</string>
+ <string name="quick_settings_lockscreen_label">شاشة القفل</string>
+ <string name="quick_settings_ambient_display_label">العرض المحيط</string>
+ <string name="quick_settings_lockscreen_label_enforced">إعمال قفل الشاشة</string>
+ <string name="accessibility_quick_settings_screen_timeout">مهلة الشاشة: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">تم تغيير مهلة الشاشة إلى: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">وضع البطارية</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">وضع البطارية: وضع توفير الطاقة.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">وضع البطارية: وضع متوازن.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">وضع البطارية: وضع الأداء.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">وضع البطارية: وضع الكفاءة.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">وضع البطارية: الوضع السريع.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">تم تغيير وضع البطارية إلى وضع توفير الطاقة.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">تم تغيير وضع البطارية إلى الوضع المتوازن.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">تم تغيير وضع البطارية إلى وضع الأداء.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">تم تغيير وضع البطارية الى وضع الكفاءة.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">تم تغيير وضع البطارية الى الوضع السريع.</string>
+ <string name="quick_settings_performance_profile_detail_title">وضع البطارية</string>
+ <string name="accessibility_quick_settings_lock_screen_off">تعطيل شاشة القفل.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">تشغيل شاشة القفل.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">تم تعطيل شاشة القفل.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">تم تشغيل شاشة القفل.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">تعطيل العرض المحيط.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">تشغيل العرض المحيط.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">تم تعطيل العرض المحيط.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">تم تشغيل العرض المحيط.</string>
+ <string name="accessibility_quick_settings_heads_up_off">تعطيل الإنذار المسبق.</string>
+ <string name="accessibility_quick_settings_heads_up_on">تشغيل الإنذار المسبق.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">تم تعطيل الإنذار المسبق.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">تم تشغيل الإنذار المسبق.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">إيقاف موفر البطارية.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">تشغيل موفر البطارية.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">تم ايقاف موفر البطارية.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">تشغيل موفر البطارية.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">مربع ديناميكي</string>
+ <string name="dynamic_qs_tile_next_alarm_label">التنبيه المقبل</string>
+ <string name="dynamic_qs_tile_ime_selector_label">محدد IME</string>
+ <string name="dynamic_qs_tile_su_label">الوصول إلى root</string>
+ <string name="accessibility_quick_settings_live_display_off">تعطيل LiveDisplay.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: الوضع التلقائي.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: الوضع النهاري.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: الوضع الليلي.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: وضع الأماكن المفتوحة.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">تم تعطيل LiveDisplay.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">تغيير LiveDisplay إلى الوضع التلقائي.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">تغيير LiveDisplay إلى الوضع النهاري.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">تغيير LiveDisplay إلى الوضع الليلي.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">تغيير LiveDisplay إلى وضع الأماكن المفتوحة.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">تحديد الموقع: وضع توفير البطارية.</string>
+ <string name="accessibility_quick_settings_location_gps_only">تحديد الموقع: وضع المستشعرات فقط.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">تحديد الموقع: وضع الدقة العالية.</string>
+ <string name="quick_settings_location_detail_title">وضع الموقع</string>
+ <string name="quick_settings_location_battery_saving_label">توفير البطارية</string>
+ <string name="quick_settings_location_gps_only_label">الجهاز فقط</string>
+ <string name="quick_settings_location_high_accuracy_label">دقة عالية</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">تغيير تحديد الموقع إلى وضع توفير البطارية.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">تغيير تحديد الموقع إلى وضع المستشعرات فقط.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">تغيير تحديد الموقع إلى وضع الدقة العالية.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ast-rES/cm_arrays.xml b/packages/SystemUI/res/values-ast-rES/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-ast-rES/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ast-rES/cm_strings.xml b/packages/SystemUI/res/values-ast-rES/cm_strings.xml
new file mode 100644
index 0000000..9628bf6
--- /dev/null
+++ b/packages/SystemUI/res/values-ast-rES/cm_strings.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Esliza a la derecha pa %1$s</string>
+ <string name="right_shortcut_hint">Esliza a la esquierda pa %1$s</string>
+ <string name="select_application">Esbillar app</string>
+ <string name="lockscreen_choose_action_title">Esbillar aición</string>
+ <string name="lockscreen_none_target">Nengún</string>
+ <string name="navbar_dialog_title">Seleicionar botón a amosar</string>
+ <string name="navbar_home_button">Botón Aniciu</string>
+ <string name="navbar_recent_button">Botón Recientes</string>
+ <string name="navbar_search_button">Botón Gueta</string>
+ <string name="navbar_back_button">Botón Atrás</string>
+ <string name="navbar_empty_button">Botón baleru</string>
+ <string name="navbar_menu_conditional_button">Botón Menú (auto-anubrir)</string>
+ <string name="navbar_menu_always_button">Botón Menú (siempre visible)</string>
+ <string name="navbar_menu_big_button">Botón Menú</string>
+ <string name="accessibility_dpad_left">Cursor esquierda</string>
+ <string name="accessibility_dpad_right">Cursor derecha</string>
+ <string name="advanced_dev_option_wipe_app">Desaniciar datos</string>
+ <string name="advanced_dev_option_force_stop">Forciar detención</string>
+ <string name="advanced_dev_option_uninstall">Desinstalar</string>
+ <string name="quick_settings_compass_init">Anicializando\u2026</string>
+ <string name="quick_settings_network_adb_label">ADB sobre rede</string>
+ <string name="quick_settings_compass_label">Brúxula</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Perfiles del sistema</string>
+ <string name="quick_settings_profiles_off">Perfiles deshabilitaos</string>
+ <string name="quick_settings_battery_saver_label">Aforrador d\'enerxía</string>
+ <string name="quick_settings_volume_panel_label">Panel de volume</string>
+ <string name="quick_settings_usb_tether_label">USB tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Tiempu d\'espera</string>
+ <string name="quick_settings_lockscreen_label">Pantalla de bloquéu</string>
+ <string name="quick_settings_ambient_display_label">Pantalla ambiente</string>
+ <string name="quick_settings_lockscreen_label_enforced">Bloquéu de pantalla forzáu</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Pantalla ambiente apagada.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Pantalla ambiente prendida.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Apagóse la pantalla ambiente.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Prendióse la pantalla ambiente.</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Alarma siguiente</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Seleutor d\'IME</string>
+ <string name="dynamic_qs_tile_su_label">Accesu root</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Informes de llocalización: mou d\'aforru de batería.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Informes de llocalización: mou de namái sensores.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Informes de llocalización: mou d\'alta precisión.</string>
+ <string name="quick_settings_location_detail_title">Mou de llocalización</string>
+ <string name="quick_settings_location_battery_saving_label">Aforru d\'enerxía</string>
+ <string name="quick_settings_location_gps_only_label">Namái preséu</string>
+ <string name="quick_settings_location_high_accuracy_label">Precisión alta</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ast-rES/strings.xml b/packages/SystemUI/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..b4ea942
--- /dev/null
+++ b/packages/SystemUI/res/values-ast-rES/strings.xml
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">IU sistema</string>
+ <string name="status_bar_clear_all_button">Llimpiar</string>
+ <string name="status_bar_recent_remove_item_title">Desaniciar de la llista</string>
+ <string name="status_bar_recent_inspect_item_title">Información de l\'aplicación</string>
+ <string name="status_bar_no_recent_apps">Les tos pantalles recientes apaecen equí</string>
+ <string name="status_bar_accessibility_dismiss_recents">Inorar aplicaciones recientes</string>
+ <string name="status_bar_no_notifications_title">Nun tienes notificaciones</string>
+ <string name="status_bar_ongoing_events_title">Entrante</string>
+ <string name="status_bar_latest_events_title">Notificaciones</string>
+ <string name="battery_low_title">Batería baxa</string>
+ <string name="invalid_charger">Nun s\'almite la carga por USB.\nUsa namái el cargador proporcionáu.</string>
+ <string name="invalid_charger_title">La carga USB nun ta sofitada.</string>
+ <string name="invalid_charger_text">Usar namái el cargador suministráu.</string>
+ <string name="battery_low_why">Axustes</string>
+ <string name="battery_saver_confirmation_title">¿Prender l\'aforrador d\'enerxía?</string>
+ <string name="battery_saver_confirmation_ok">Activar</string>
+ <string name="battery_saver_start_action">Prender l\'aforrador d\'enerxía</string>
+ <string name="status_bar_settings_settings_button">Axustes</string>
+ <string name="status_bar_settings_wifi_button">Wi-Fi</string>
+ <string name="status_bar_settings_auto_rotation">Xirar pantalla automáticamente</string>
+ <string name="status_bar_settings_mute_label">SILENC</string>
+ <string name="status_bar_settings_auto_brightness_label">AUTO</string>
+ <string name="status_bar_settings_notifications">Notificaciones</string>
+ <string name="bluetooth_tethered">Bluetooth ancláu</string>
+ <string name="status_bar_input_method_settings_configure_input_methods">Configurar métodos d\'entrada</string>
+ <string name="status_bar_use_physical_keyboard">Tecláu físicu</string>
+ <string name="usb_device_permission_prompt">¿Permitir que l\'aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al preséu USB?</string>
+ <string name="usb_accessory_permission_prompt">¿Permitir que l\'aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al preséu USB?</string>
+ <string name="usb_device_confirm_prompt">¿Quies abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> al coneutar esti preséu USB?</string>
+ <string name="usb_accessory_confirm_prompt">¿Quies abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> al coneutar esti preséu USB?</string>
+ <string name="usb_accessory_uri_prompt">Nenguna aplicación instalada funciona con esti preséu USB. Más información: <xliff:g id="URL">%1$s</xliff:g></string>
+ <string name="title_usb_accessory">Preséu USB</string>
+ <string name="label_view">Ver</string>
+ <string name="always_use_device">Usar de mou predetermináu pa esti preséu USB</string>
+ <string name="always_use_accessory">Usar de mou predetermináu pa esti preséu USB</string>
+ <string name="usb_debugging_title">¿Permitir depuración USB?</string>
+ <string name="usb_debugging_message">La buelga dixital de la to clave RSA ye:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g></string>
+ <string name="usb_debugging_always">Permitir siempre dende esti ordenador</string>
+ <string name="compat_mode_on">Zoom p\'axustar</string>
+ <string name="compat_mode_off">Espander p\'axustar</string>
+ <string name="screenshot_saving_ticker">Guardando captura...</string>
+ <string name="screenshot_saving_title">Guardando captura...</string>
+ <string name="screenshot_saving_text">La captura de pantalla ta guardándose.</string>
+ <string name="screenshot_saved_title">Captura guardada</string>
+ <string name="screenshot_saved_text">Toca pa ver la captura de pantalla</string>
+ <string name="screenshot_failed_title">Nun pudo guardase la captura de pantalla.</string>
+ <string name="screenshot_failed_text">Nun pue facese captura de pantalla porque nun hai espaciu, o nun hai permisu pa esta app.</string>
+ <string name="usb_preference_title">Opciones de tresferencia de ficheros por USB</string>
+ <string name="use_mtp_button_title">Activar como reproductor de medios (MTP)</string>
+ <string name="use_ptp_button_title">Activar como cámara (PTP)</string>
+ <string name="installer_cd_button_title">Instalar Android File Transfer pa Mac</string>
+ <string name="accessibility_back">Atrás</string>
+ <string name="accessibility_home">Aniciu</string>
+ <string name="accessibility_menu">Menú</string>
+ <string name="accessibility_recent">Perspeutiva</string>
+ <string name="accessibility_search_light">Guetar</string>
+ <string name="accessibility_camera_button">Cámara</string>
+ <string name="accessibility_phone_button">Teléfonu</string>
+ <string name="accessibility_unlock_button">Desbloquiar</string>
+ <string name="unlock_label">desbloquiar</string>
+ <string name="phone_label">abrir teléfonu</string>
+ <string name="camera_label">abrir cámara</string>
+ <string name="accessibility_compatibility_zoom_button">Botón de zoom de compatibilidá</string>
+ <string name="accessibility_compatibility_zoom_example">Zoom de pantalla más pequeña a más grande</string>
+ <string name="accessibility_bluetooth_connected">Bluetooth coneutáu</string>
+ <string name="accessibility_bluetooth_disconnected">Bluetooth desconeutáu</string>
+ <string name="accessibility_no_battery">Ensin batería</string>
+ <string name="accessibility_battery_one_bar">Una barra de batería</string>
+ <string name="accessibility_battery_two_bars">Dos barres de batería</string>
+ <string name="accessibility_battery_three_bars">Trés barres de batería</string>
+ <string name="accessibility_battery_full">Batería completa</string>
+ <string name="accessibility_no_phone">Ensin teléfonu</string>
+ <string name="accessibility_phone_one_bar">Una barra de cobertoria</string>
+ <string name="accessibility_phone_two_bars">Dos barres de cobertoria</string>
+ <string name="accessibility_phone_three_bars">Trés barres de cobertoria</string>
+ <string name="accessibility_phone_signal_full">Cobertoria al máximu</string>
+ <string name="accessibility_no_data">Ensin datos</string>
+ <string name="accessibility_data_one_bar">Una barra de datos</string>
+ <string name="accessibility_data_two_bars">Dos barres de datos</string>
+ <string name="accessibility_data_three_bars">Trés barres de datos</string>
+ <string name="accessibility_data_signal_full">Señal de datos al máximu</string>
+ <string name="accessibility_wifi_name">Coneutáu a <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
+ <string name="accessibility_bluetooth_name">Coneutáu a <xliff:g id="bluetooth" example="Car Audio">%s</xliff:g>.</string>
+ <string name="accessibility_no_wimax">Ensin conexón WiMAX</string>
+ <string name="accessibility_wimax_one_bar">Una barra de WiMAX</string>
+ <string name="accessibility_wimax_two_bars">Dos barres de WiMAX</string>
+ <string name="accessibility_wimax_three_bars">Trés barres de WiMAX</string>
+ <string name="accessibility_wimax_signal_full">Señal de WiMAX al máximu</string>
+ <string name="accessibility_no_signal">Nun hai señal</string>
+ <string name="accessibility_not_connected">Ensin conexón</string>
+ <string name="accessibility_zero_bars">Nenguna barra</string>
+ <string name="accessibility_one_bar">Una barra</string>
+ <string name="accessibility_two_bars">Dos barres</string>
+ <string name="accessibility_three_bars">Trés barres</string>
+ <string name="accessibility_signal_full">Señal al máximu</string>
+ <string name="accessibility_desc_on">Activáu</string>
+ <string name="accessibility_desc_off">Desactiváu</string>
+ <string name="accessibility_desc_connected">Coneutáu</string>
+ <string name="accessibility_desc_connecting">Coneutando.</string>
+ <string name="accessibility_data_connection_gprs">GPRS</string>
+ <string name="accessibility_data_connection_1x">1 X</string>
+ <string name="accessibility_data_connection_hspa">HSPA</string>
+ <string name="accessibility_data_connection_3g">3G</string>
+ <string name="accessibility_data_connection_3.5g">3.5 G</string>
+ <string name="accessibility_data_connection_4g">4G</string>
+ <string name="accessibility_data_connection_lte">LTE</string>
+ <string name="accessibility_data_connection_cdma">CDMA</string>
+ <string name="accessibility_data_connection_roaming">Itinerancia</string>
+ <string name="accessibility_data_connection_edge">Tipu Edge</string>
+ <string name="accessibility_data_connection_wifi">Wi-Fi</string>
+ <string name="accessibility_no_sim">Ensin tarxeta SIM</string>
+ <string name="accessibility_bluetooth_tether">Anclaxe de Bluetooth</string>
+ <string name="accessibility_airplane_mode">Mou avión</string>
+ <string name="accessibility_battery_level"><xliff:g id="NUMBER">%d</xliff:g> por cientu de batería</string>
+ <string name="accessibility_settings_button">Axustes del sistema</string>
+ <string name="accessibility_notifications_button">Notificaciones</string>
+ <string name="accessibility_remove_notification">Desaniciar notificación</string>
+ <string name="accessibility_gps_enabled">GPS habilitáu</string>
+ <string name="accessibility_gps_acquiring">Obteniendo llocalización...</string>
+ <string name="accessibility_tty_enabled">Teletipu habilitáu</string>
+ <string name="accessibility_ringer_vibrate">Mou vibración</string>
+ <string name="accessibility_ringer_silent">Mou silenciu</string>
+ <string name="accessibility_recents_item_will_be_dismissed">Descartar <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+ <string name="accessibility_recents_item_dismissed">Desanicióse <xliff:g id="APP">%s</xliff:g>.</string>
+ <string name="accessibility_recents_item_launched">Aniciando <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+ <string name="accessibility_notification_dismissed">Notificación inorada</string>
+ <string name="accessibility_desc_notification_shade">Pantalla de notificaciones</string>
+ <string name="accessibility_desc_quick_settings">Axustes rápidos</string>
+ <string name="accessibility_desc_lock_screen">Pantalla de bloquéu.</string>
+ <string name="accessibility_desc_settings">Axustes</string>
+ <string name="accessibility_desc_recent_apps">Perspeutiva.</string>
+ <string name="accessibility_quick_settings_user">Usuariu <xliff:g id="USER">%s</xliff:g></string>
+ <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_wifi_changed_off">Wifi apagada.</string>
+ <string name="accessibility_quick_settings_wifi_changed_on">Wifi prendida.</string>
+ <string name="accessibility_quick_settings_mobile">Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g></string>
+ <string name="accessibility_quick_settings_battery">Batería <xliff:g id="STATE">%s</xliff:g></string>
+ <string name="accessibility_quick_settings_airplane_off">Mou avión apagáu.</string>
+ <string name="accessibility_quick_settings_airplane_on">Mou avión prendíu.</string>
+ <string name="accessibility_quick_settings_airplane_changed_off">Mou avión apagáu.</string>
+ <string name="accessibility_quick_settings_airplane_changed_on">Mou avión prendíu.</string>
+ <string name="accessibility_quick_settings_bluetooth_off">Bluetooth desactiváu.</string>
+ <string name="accessibility_quick_settings_bluetooth_on">Bluetooth prendíu.</string>
+ <string name="accessibility_quick_settings_bluetooth_connecting">Coneutando Bluetooth.</string>
+ <string name="accessibility_quick_settings_bluetooth_connected">Bluetooth coneutáu.</string>
+ <string name="accessibility_quick_settings_bluetooth_changed_off">Bluetooth desconeutáu.</string>
+ <string name="accessibility_quick_settings_bluetooth_changed_on">Bluetooth coneutáu.</string>
+ <string name="accessibility_quick_settings_location_off">Informe de llocalización desactiváu</string>
+ <string name="accessibility_quick_settings_location_on">Informe de llocalización activáu</string>
+ <string name="accessibility_quick_settings_location_changed_off">Informe de llocalización apagáu</string>
+ <string name="accessibility_quick_settings_location_changed_on">Informe de llocalización prendíu</string>
+ <string name="accessibility_quick_settings_alarm">L\'alarma va sonar a les <xliff:g id="TIME">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_close">Zarrar panel.</string>
+ <string name="accessibility_quick_settings_more_time">Más tiempu.</string>
+ <string name="accessibility_quick_settings_less_time">Menos tiempu.</string>
+ <string name="accessibility_quick_settings_flashlight_off">Llinterna apagada.</string>
+ <string name="accessibility_quick_settings_flashlight_on">Llinterna prendida.</string>
+ <string name="accessibility_quick_settings_flashlight_changed_off">Llinterna desconeutada.</string>
+ <string name="accessibility_quick_settings_flashlight_changed_on">Llinterna coneutada.</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_off">Inversión de color apagáu</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_on">Inversión de color prendíu</string>
+ <string name="accessibility_quick_settings_hotspot_changed_off">Puntu d\'accesu móvil apagáu</string>
+ <string name="accessibility_quick_settings_hotspot_changed_on">Puntu d\'accesu móvil prendíu</string>
+ <string name="accessibility_casting_turned_off">Pantalla d\'emisión parada.</string>
+ <string name="accessibility_brightness">Amosar brillu</string>
+ <string name="status_bar_settings_signal_meter_disconnected">Ensin conexón a Internet</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid">Con conexón Wi-Fi</string>
+ <string name="gps_notification_searching_text">Guetando GPS</string>
+ <string name="gps_notification_found_text">Llocalización definida por GPS</string>
+ <string name="accessibility_location_active">Solicitúes de llocalización actives</string>
+ <string name="accessibility_clear_all">Llimpiar toles notificaciones</string>
+ <string name="status_bar_notification_inspect_item_title">Axustes de notificaciones</string>
+ <string name="status_bar_notification_app_settings_title">Axustes <xliff:g id="app_name" example="Calendar">%s</xliff:g></string>
+ <string name="accessibility_rotation_lock_off">La pantalla va xirar automáticamente.</string>
+ <string name="accessibility_rotation_lock_on_landscape">La pantalla ta bloquiada en mou horizontal.</string>
+ <string name="accessibility_rotation_lock_on_portrait">La pantalla ta bloquiada en mou vertical.</string>
+ <string name="accessibility_rotation_lock_off_changed">La pantalla va xirar agora automáticamente.</string>
+ <string name="accessibility_rotation_lock_on_landscape_changed">La pantalla ta bloquiada en mou horizontal.</string>
+ <string name="accessibility_rotation_lock_on_portrait_changed">La pantalla ta bloquiada en mou vertical.</string>
+ <string name="dessert_case">Caxa para postres</string>
+ <string name="start_dreams">Curiapantalles</string>
+ <string name="ethernet_label">Ethernet</string>
+ <string name="quick_settings_bluetooth_label">Bluetooth</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label">Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> preseos)</string>
+ <string name="quick_settings_bluetooth_off_label">Bluetooth desactiváu</string>
+ <string name="quick_settings_bluetooth_detail_empty_text">Nun hai disponibles preseos empareyaos</string>
+ <string name="quick_settings_brightness_label">Brillu</string>
+ <string name="quick_settings_rotation_unlocked_label">Xiru-auto</string>
+ <string name="quick_settings_rotation_locked_label">Xiru bloquiáu</string>
+ <string name="quick_settings_rotation_locked_portrait_label">Retratu</string>
+ <string name="quick_settings_rotation_locked_landscape_label">Paisaxe</string>
+ <string name="quick_settings_ime_label">Métodu d\'entrada</string>
+ <string name="quick_settings_location_label">Llocalización</string>
+ <string name="quick_settings_location_off_label">Llocalización desactivada</string>
+ <string name="quick_settings_media_device_label">Preséu multimedia</string>
+ <string name="quick_settings_rssi_label">RSSI</string>
+ <string name="quick_settings_rssi_emergency_only">Namái llamaes d\'emerxencia</string>
+ <string name="quick_settings_settings_label">Axustes</string>
+ <string name="quick_settings_time_label">Hora</string>
+ <string name="quick_settings_user_label">Yo</string>
+ <string name="quick_settings_user_title">Usuariu</string>
+ <string name="quick_settings_user_new_user">Usuariu nuevu</string>
+ <string name="quick_settings_wifi_label">Wi-Fi</string>
+ <string name="quick_settings_wifi_not_connected">Non coneutáu</string>
+ <string name="quick_settings_wifi_no_network">Nun hai rede.</string>
+ <string name="quick_settings_wifi_off_label">Wi-Fi desactiváu</string>
+ <string name="quick_settings_casting">Emisión</string>
+ <string name="quick_settings_cast_device_default_name">Preséu ensin nome</string>
+ <string name="quick_settings_cast_device_default_description">Preparáu pa emitir</string>
+ <string name="quick_settings_cast_detail_empty_text">Nun hai preseos disponibles</string>
+ <string name="quick_settings_brightness_dialog_title">Brillu</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label">AUTO</string>
+ <string name="quick_settings_inversion_label">Invertir colores</string>
+ <string name="quick_settings_color_space_label">Mou de correición de color</string>
+ <string name="quick_settings_more_settings">Más axustes</string>
+ <string name="quick_settings_done">Fecho</string>
+ <string name="quick_settings_connected">Coneutáu</string>
+ <string name="quick_settings_connecting">Coneutando...</string>
+ <string name="quick_settings_tethering_label">Anclaxe a rede</string>
+ <string name="quick_settings_hotspot_label">Hotspot</string>
+ <string name="quick_settings_notifications_label">Notificaciones</string>
+ <string name="quick_settings_flashlight_label">Llinterna</string>
+ <string name="quick_settings_cellular_detail_title">Datos móvil</string>
+ <string name="quick_settings_cellular_detail_data_usage">Usu de datos</string>
+ <string name="quick_settings_cellular_detail_remaining_data">Datos restantes</string>
+ <string name="quick_settings_cellular_detail_data_used"><xliff:g id="data_used" example="2.0 GB">%s</xliff:g> usaos</string>
+ <string name="quick_settings_cellular_detail_data_limit">Llende <xliff:g id="data_limit" example="2.0 GB">%s</xliff:g></string>
+ <string name="quick_settings_cellular_detail_data_warning">Avisu <xliff:g id="data_limit" example="2.0 GB">%s</xliff:g></string>
+ <string name="recents_empty_message">Les tos pantalles recientes apaecen equí</string>
+ <string name="recents_app_info_button_label">Info d\'aplicación</string>
+ <string name="recents_search_bar_label">guetar</string>
+ <string name="recents_launch_error_message">Nun pudo aniciase <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+ <string name="expanded_header_battery_charged">Cargada</string>
+ <string name="expanded_header_battery_charging">Cargando</string>
+ <string name="expanded_header_battery_charging_with_time">Queden <xliff:g id="charging_time" example="2 hrs 25 min">%s</xliff:g> cargando</string>
+ <string name="expanded_header_battery_not_charging">Nun se ta cargando</string>
+ <string name="battery_meter_very_low_overlay_symbol">!</string>
+ <string name="ssl_ca_cert_warning">La rede pue\nsupervisase</string>
+ <string name="description_target_search">Guetar</string>
+ <string name="description_direction_up">Esliza\'l deu hacia arriba pa <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
+ <string name="description_direction_left">\"Esliza\'l deu hacia la esquierda pa <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
+ <string name="keyguard_more_overflow_text">+<xliff:g id="number_of_notifications" example="5">%d</xliff:g></string>
+ <string name="speed_bump_explanation">Notificaciones menos urxentes, debaxo</string>
+ <string name="notification_tap_again">Toca otra vuelta p\'abrir</string>
+ <string name="keyguard_unlock">Eslizar arriba pa desbloquiar</string>
+ <string name="keyguard_indication_charging_time">Cargando (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> pa completar)</string>
+ <string name="accessibility_multi_user_switch_switcher">Camudar usuariu</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current">Cambiar usuariu, usuariu actual <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
+ <string name="accessibility_multi_user_switch_quick_contact">Amosar perfil</string>
+ <string name="user_add_user">Amestar usuariu</string>
+ <string name="user_new_user_name">Usuariu nuevu</string>
+ <string name="guest_nickname">Convidáu</string>
+ <string name="guest_new_guest">Amestar convidáu</string>
+ <string name="guest_exit_guest">Desaniciar convidáu</string>
+ <string name="guest_exit_guest_dialog_title">Desaniciar convidáu?</string>
+ <string name="guest_exit_guest_dialog_message">Van desaniciase toles apps y datos nesta sesión.</string>
+ <string name="guest_exit_guest_dialog_remove">Desaniciar</string>
+ <string name="guest_wipe_session_title">Bienllegáu otra vuelta, convidáu!</string>
+ <string name="guest_wipe_session_message">Quies continuar la to sesión?</string>
+ <string name="guest_wipe_session_wipe">Aniciar sesión nueva</string>
+ <string name="guest_wipe_session_dontwipe">Sí, siguir</string>
+ <string name="user_add_user_title" msgid="2108112641783146007">Amestar usuariu nuevu?</string>
+ <string name="user_add_user_message_short" msgid="1511354412249044381">Cuando amiestes un usuariu nuevu, esi usuariu necesita configurar el so espaciu\n\nCualquier usuariu pue anovar apps pa otros usuarios. </string>
+ <string name="battery_saver_notification_title">L\'aforrador de batería ta activáu</string>
+ <string name="battery_saver_notification_text">Amenorga los datos de rindimientu y de fondu</string>
+ <string name="battery_saver_notification_action_text">Prender l\'aforrador d\'enerxía</string>
+ <string name="notification_hidden_text">Conteníos anubríos</string>
+ <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> va empezar a capturar tolo que s\'amuese na pantalla.</string>
+ <string name="media_projection_remember_text">Nun amosar más</string>
+ <string name="clear_all_notifications_text">Llimpiar too</string>
+ <string name="media_projection_action_text">Aniciar agora</string>
+ <string name="empty_shade_text">Nun tienes notificaciones</string>
+ <string name="device_owned_footer">El preséu pue ser monitoreáu</string>
+ <string name="profile_owned_footer">El perfil pue ser monitoreáu</string>
+ <string name="vpn_footer">La rede pue ser monitoreada</string>
+ <string name="monitoring_title_device_owned">Monitoréu de preseos</string>
+ <string name="monitoring_title_profile_owned">Monitoréu de perfiles</string>
+ <string name="monitoring_title">Monitoréu de rede</string>
+ <string name="disable_vpn">Deshabilitar VPN</string>
+ <string name="disconnect_vpn">Desconeutar VPN</string>
+ <string name="keyguard_indication_trust_disabled">El preséu va tar bloquiáu hasta que lu desbloquies manualmente</string>
+ <string name="hidden_notifications_title">Obtener notificaciones más rápido</string>
+ <string name="hidden_notifications_text">Veles enantes de desbloquiar</string>
+ <string name="hidden_notifications_cancel">Non, gracies</string>
+ <string name="hidden_notifications_setup">Configurar</string>
+ <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
+ <string name="status_bar_ethernet">Ethernet</string>
+ <string name="status_bar_airplane">Mou avión</string>
+ <string name="accessibility_status_bar_hotspot">Hotspot</string>
+ <string name="enable_bluetooth_confirmation_ok">Activar</string>
+</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/cm_arrays.xml b/packages/SystemUI/res/values-az-rAZ/cm_arrays.xml
new file mode 100644
index 0000000..da47b5a
--- /dev/null
+++ b/packages/SystemUI/res/values-az-rAZ/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Şi</item>
+ <item>ŞŞ</item>
+ <item>Şə</item>
+ <item>CŞ</item>
+ <item>C</item>
+ <item>CQ</item>
+ <item>Q</item>
+ <item>ŞQ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/cm_strings.xml b/packages/SystemUI/res/values-az-rAZ/cm_strings.xml
new file mode 100644
index 0000000..d7414f7
--- /dev/null
+++ b/packages/SystemUI/res/values-az-rAZ/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">%1$s üçün sağa sürüşdürün</string>
+ <string name="right_shortcut_hint">%1$s üçün sola sürüşdürün</string>
+ <string name="select_application">Tətbiqetmə seç</string>
+ <string name="lockscreen_choose_action_title">Hərəkət seç</string>
+ <string name="lockscreen_none_target">Yoxdur</string>
+ <string name="navbar_dialog_title">Hərəkət seçin</string>
+ <string name="navbar_home_button">Əsas ekran düyməsi</string>
+ <string name="navbar_recent_button">Son tətb. düyməsi</string>
+ <string name="navbar_search_button">Axtarış düyməsi</string>
+ <string name="navbar_back_button">Geri düyməsi</string>
+ <string name="navbar_empty_button">Boş düymə</string>
+ <string name="navbar_menu_conditional_button">Menyu (avtoGizlət) düyməsi</string>
+ <string name="navbar_menu_always_button">Menyu (hmşGöstər) düyməsi</string>
+ <string name="navbar_menu_big_button">Menyu düyməsi</string>
+ <string name="accessibility_dpad_left">Sol kursor</string>
+ <string name="accessibility_dpad_right">Sağ kursor</string>
+ <string name="advanced_dev_option_wipe_app">Tətbiq verilənlərini sil</string>
+ <string name="advanced_dev_option_force_stop">Dayanmağa məcbur et</string>
+ <string name="advanced_dev_option_uninstall">Çıxart</string>
+ <string name="accessibility_quick_settings_profiles_off">Profillər bağlıdır.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profillər bağlıdır.</string>
+ <string name="accessibility_quick_settings_profiles_changed"><xliff:g id="profile" example="Default">%s</xliff:g> profilinə keçildi.</string>
+ <string name="quick_settings_compass_init">Başladılır\u2026</string>
+ <string name="screen_pinning_description_no_navbar">Ekrandan çıxarılana qədər görsənəcək. Çıxartmaq üçün Geri düyməsinə toxunub basılı tutun.</string>
+ <string name="quick_settings_custom_tile_detail_title">Özəl kvadrat</string>
+ <string name="quick_settings_remove">Kvadratı çıxart</string>
+ <string name="quick_settings_network_adb_label">Şəbəkə üzərindən ADB</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Sistem profilləri</string>
+ <string name="quick_settings_profiles_off">Profillər ləğv edildi</string>
+ <string name="quick_settings_heads_up_label">Açılan başlıqlar</string>
+ <string name="quick_settings_battery_saver_label">Batereyaya qənaət</string>
+ <string name="accessibility_quick_settings_sync_off">Eyniləşdirmə bağlıdır.</string>
+ <string name="accessibility_quick_settings_sync_on">Eyniləşdirmə açıqdır.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Eyniləşdirmə bağlanıldı.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Eyniləşdirmə açıldı.</string>
+ <string name="quick_settings_sync_label">Eyniləşdirmə</string>
+ <string name="quick_settings_volume_panel_label">Səs paneli</string>
+ <string name="quick_settings_usb_tether_label">USB internet paylaşımı</string>
+ <string name="quick_settings_screen_timeout_detail_title">Ekrana qoyulan vaxt</string>
+ <string name="quick_settings_lockscreen_label">Kilid ekranı</string>
+ <string name="quick_settings_ambient_display_label">Bildiriş ekranı</string>
+ <string name="quick_settings_lockscreen_label_enforced">Kilit ekranı məcburidir</string>
+ <string name="accessibility_quick_settings_screen_timeout">Ekrana qoyulan vaxt: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Ekrana qoyulan vaxt <xliff:g id="timeout" example="30 seconds">%s</xliff:g> olaraq tənzimləndi.</string>
+ <string name="qs_tile_performance">Batereya rejimi</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Batereya rejimi: enerjiyə qənaəti rejimi.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Batereya rejimi: tarazlaşdırılmış rejim.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Batereya rejimi: performans rejimi.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Batareya rejimi: səmərəli rejim.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Batereya rejimi: cəld rejim.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Batereya rejimi enerjiyə qənaət rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Batereya rejimi tarazlaşdırılmış rejimə keçdi.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Batereya rejimi performans rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Batereya rejimi səmərəli rejimə keçdi.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Batereya rejimi cəld rejiminə keçdi.</string>
+ <string name="quick_settings_performance_profile_detail_title">Batereya rejimi</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Kilit ekranı bağlıdır.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Kilit ekranı açıldı.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Kilit ekranı bağlanıldı.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Kilit ekranı açıldı.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Bildiriş ekranı bağlıdır.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Bildiriş ekranı açıqdır.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Bildiriş ekranı bağlanıldı.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Bildiriş ekranı açıldı.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Açılan başlıq bildirişi bağlıdır.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Açılan başlıq bildişi açıqdır.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Açılan başlıq bildirişi bağlanıldı.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Açılan başlıq bildirişi açıldı.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Batereyaya qənaət bağlıdır.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Batereyaya qənaət açıqdır.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Batereyaya qənaət bağlanıldı.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Batereyaya qənaət açıldı.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamik kvadrat</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Növbəti zəngli saat</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME seçici</string>
+ <string name="dynamic_qs_tile_su_label">Root müraciəti</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay bağlıdır.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: avtomatik rejim.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: gündüz rejimi.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: gecə rejimi.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: açıq hava rejimi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay bağlanıldı.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay avtomatik rejimə keçdi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay gündüz rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay gecə rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay açıq hava rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Yer hesabatı: batareyaya qənaət rejimi.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Yer hesabatı: yalnız sensorlar rejimi.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Yer hesabatı: yüksək həssaslıq rejimi.</string>
+ <string name="quick_settings_location_detail_title">Yer rejimi</string>
+ <string name="quick_settings_location_battery_saving_label">Batareyaya qənaət</string>
+ <string name="quick_settings_location_gps_only_label">Yalnız cihaz</string>
+ <string name="quick_settings_location_high_accuracy_label">Yüksək həssaslıq</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Yer bildirişi batereyaya qənaət rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Yer bildirişi yalnız sensorlar rejiminə keçdi.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Yer bildirişi yüksək dəqiqlik rejiminə keçdi.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-be/cm_arrays.xml b/packages/SystemUI/res/values-be/cm_arrays.xml
new file mode 100644
index 0000000..5a2d012
--- /dev/null
+++ b/packages/SystemUI/res/values-be/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Паўночны</item>
+ <item>Паўночна-Усходні</item>
+ <item>Усходні</item>
+ <item>Паўднёва-Усходні</item>
+ <item>Паўднёвы</item>
+ <item>Паўднёва-Заходні</item>
+ <item>Заходні</item>
+ <item>Паўночна-Заходні</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-be/cm_strings.xml b/packages/SystemUI/res/values-be/cm_strings.xml
new file mode 100644
index 0000000..65a09b6
--- /dev/null
+++ b/packages/SystemUI/res/values-be/cm_strings.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Правядзіце направа, каб адкрыць дадатак %1$s</string>
+ <string name="right_shortcut_hint">Правядзіце налева, каб адкрыць дадатак %1$s</string>
+ <string name="lockscreen_message">Націсніце значок злева альбо справа для змянення цэтліка экрана блакавання.</string>
+ <string name="lockscreen_default_target">Па змаўчанні</string>
+ <string name="select_application">Выбар дадатку</string>
+ <string name="lockscreen_choose_action_title">Выбар дзеяння</string>
+ <string name="lockscreen_none_target">Нічога</string>
+ <string name="navbar_dialog_title">Выберыце дзеянне</string>
+ <string name="navbar_home_button">Дамоў</string>
+ <string name="navbar_recent_button">Запушчаныя дадаткі</string>
+ <string name="navbar_search_button">Пошук</string>
+ <string name="navbar_back_button">Назад</string>
+ <string name="navbar_empty_button">Пустая кнопка</string>
+ <string name="navbar_menu_conditional_button">Меню (калі даступна)</string>
+ <string name="navbar_menu_always_button">Меню (заўсёды)</string>
+ <string name="navbar_menu_big_button">Меню</string>
+ <string name="accessibility_dpad_left">Курсор налева</string>
+ <string name="accessibility_dpad_right">Курсор направа</string>
+ <string name="advanced_dev_option_wipe_app">Сцерці дадзеныя</string>
+ <string name="advanced_dev_option_force_stop">Спыніць прымусова</string>
+ <string name="advanced_dev_option_uninstall">Выдаліць</string>
+ <string name="accessibility_notification_brightness">Яскравасць</string>
+ <string name="accessibility_quick_settings_profiles_off">Профілі выключаны.</string>
+ <string name="accessibility_quick_settings_profiles">Профіль: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Профілі выключаны.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Профіль зменены на <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Ініцыялізацыя\u2026</string>
+ <string name="led_notification_title">Індыкатар падзей</string>
+ <string name="led_notification_text">Светадыёд уключаны параметрамі</string>
+ <string name="qs_tile_edit_header_instruction">Націсніце і ўтрымвайце плітку для змены</string>
+ <string name="quick_settings_edit_label">Рэдагаваць плітку</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Немагчыма выдаліць кнопку рэдагавання</string>
+ <string name="qs_tiles_reset_confirmation">Аднавіць набор плітак па змаўчанні?</string>
+ <string name="quick_settings_tile_reset_to_default">Скінуць на \"па змаўчанню\"</string>
+ <string name="quick_settings_title_header">Назва</string>
+ <string name="quick_settings_title_tiles">Пліткі</string>
+ <string name="quick_settings_title_show_weather">Звесткі пра надвор\'е</string>
+ <string name="quick_settings_title_show_brightness_slider">Паказваць рэгулятар яскравасці</string>
+ <string name="quick_settings_title_enlarge_first_row">Павялічыць першы рад</string>
+ <string name="screen_pinning_description_no_navbar">Гэты дадатак застанецца актыўным, пакуль вы не скасуеце блакаванне доўгім націскам кнопкі \"Назад\".</string>
+ <string name="quick_settings_custom_tile_detail_title">Карыстальніцкая плітка</string>
+ <string name="quick_settings_remove">Выдаліць плітку</string>
+ <string name="quick_settings_network_adb_label">Адладка па сетцы</string>
+ <string name="quick_settings_compass_label">Компас</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Сістэмныя профілі</string>
+ <string name="quick_settings_profiles_off">Профілі адключаны</string>
+ <string name="quick_settings_heads_up_label">Усплывальныя паведамленні</string>
+ <string name="quick_settings_battery_saver_label">Энергазахавання</string>
+ <string name="accessibility_quick_settings_sync_off">Сінхранізацыя адключаная.</string>
+ <string name="accessibility_quick_settings_sync_on">Сінхранізацыя ўключана.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Сінхранізацыя адключаная.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Сінхранізацыя ўключана.</string>
+ <string name="quick_settings_sync_label">Сінхранізацыя</string>
+ <string name="quick_settings_volume_panel_label">Панэль гучнасці</string>
+ <string name="quick_settings_usb_tether_label">USB-мадэм</string>
+ <string name="quick_settings_screen_timeout_detail_title">Затрымка адключэння экрана</string>
+ <string name="quick_settings_lockscreen_label">Экран блакіроўкі</string>
+ <string name="quick_settings_ambient_display_label">Індыкацыя падзей</string>
+ <string name="quick_settings_lockscreen_label_enforced">Блакаванне экрана ўключана</string>
+ <string name="accessibility_quick_settings_screen_timeout">Час да выключэння экрана: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Час да выключэння экрана зменены на <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Энергаспажыванне</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Рэжым батарэі: энергазахавальны.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Рэжым батарэі: збалансаваны.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Рэжым батарэі: прадукцыйны.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Рэжым энергаспажывання: эфектыўны.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Рэжым энергаспажывання: прадукцыйнасць.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Рэжым батарэі зменены на энергазахавальны.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Рэжым батарэі зменены на збалансаваны.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Рэжым батарэі зменены на прадукцыйны.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Рэжым энергаспажывання зменены на эфектыўны.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Рэжым энергаспажывання зменены на прадукцыйны.</string>
+ <string name="quick_settings_performance_profile_detail_title">Энергаспажыванне</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Экран блакавання выключаны.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Экран блакавання ўключаны.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Экран блакавання выключаны.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Экран блакавання ўключаны.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Індыкацыя падзей экранам адключаная.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Індыкацыя падзей экранам уключана.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Індыкацыя падзей экранам адключаная.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Індыкацыя падзей экранам уключана.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Усплывальныя паведамленні адключаны.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Усплывальныя паведамленні ўключаны.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Усплывальныя паведамленні адключаны.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Усплывальныя паведамленні ўключаны.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Рэжым энергазахавання вымкнуты.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Рэжым энергазахавання ўлучаны.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Рэжым энергазахавання вымкнуты.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Рэжым энергазахавання ўлучаны.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Дынамічная плітка</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Наступны будзільнік</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Выбар метаду ўводу</string>
+ <string name="dynamic_qs_tile_su_label">Суперкарыстальнік</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay выключаны.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay працуе ў аўтаматычным рэжыме.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay працуе ў дзённым рэжыме.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay працуе ў начным рэжыме.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay працуе ў рэжыме \"на вуліцы\".</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay выключаны.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay пераключаны ў аўтаматычны рэжым.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay пераключаны ў дзённы рэжым.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay пераключаны ў начны рэжым.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay пераключаны ў рэжым \"на вуліцы\".</string>
+ <string name="quick_settings_title_advanced_location">Налады адсылання геададзеных</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Адпраўка месцазнаходжання: рэжым эканоміі батарэі.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Адпраўка месцазнаходжання: толькі па GPS.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Адпраўка месцазнаходжання: рэжым высокай дакладнасці.</string>
+ <string name="quick_settings_location_detail_title">Вызначэнне месцазнаходжання</string>
+ <string name="quick_settings_location_battery_saving_label">Па каардынатах сеткі</string>
+ <string name="quick_settings_location_gps_only_label">Па спадарожніках GPS</string>
+ <string name="quick_settings_location_high_accuracy_label">Па ўсіх крыніцах</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Служба адпраўкі месцазнаходжання пераключана ў рэжым эканоміі батарэі.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Для адпраўкі месцазнаходжання выкарыстоўваюцца толькі дадзеныя GPS.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Служба адпраўкі месцазнаходжання пераключана ў рэжым высокай дакладнасці.</string>
+ <string name="quick_settings_tiles_category_system">Сістэмны пліткі</string>
+ <string name="quick_settings_tiles_add_tiles">Дадаць плітку</string>
+</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
new file mode 100644
index 0000000..7f9d3ea
--- /dev/null
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="use_mtp_button_title">Падлучыць як медыяпрайгравальнік (MTP)</string>
+ <string name="installer_cd_button_title">Усталяваць праграму Android File Transfer для Mac</string>
+ <string name="accessibility_bluetooth_connected">Bluetooth падлучаны.</string>
+ <string name="accessibility_bluetooth_disconnected">Bluetooth адлучаны.</string>
+ <string name="status_bar_airplane">Рэжым самалёту</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bg/cm_arrays.xml b/packages/SystemUI/res/values-bg/cm_arrays.xml
new file mode 100644
index 0000000..d80936a
--- /dev/null
+++ b/packages/SystemUI/res/values-bg/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Север</item>
+ <item>Северо-изток</item>
+ <item>Изток</item>
+ <item>Юго-изток</item>
+ <item>Юг</item>
+ <item>Юго-запад</item>
+ <item>Запад</item>
+ <item>Северо-запад</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-bg/cm_strings.xml b/packages/SystemUI/res/values-bg/cm_strings.xml
new file mode 100644
index 0000000..6d6b9c3
--- /dev/null
+++ b/packages/SystemUI/res/values-bg/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s </xliff:g> - <xliff:g id="condition">%2$s </xliff:g></string>
+ <string name="left_shortcut_hint">Плъзнете надясно за %1$s</string>
+ <string name="right_shortcut_hint">Плъзнете наляво за %1$s</string>
+ <string name="lockscreen_message">Докоснете иконата в наляво или надясно, за да присвоите команда за бърз достъп при заключен на екран.</string>
+ <string name="lockscreen_default_target">По подразбиране</string>
+ <string name="select_application">Изберете приложение</string>
+ <string name="lockscreen_choose_action_title">Изберете действие</string>
+ <string name="lockscreen_none_target">Няма</string>
+ <string name="navbar_dialog_title">Изберете действие</string>
+ <string name="navbar_home_button">Начален бутон</string>
+ <string name="navbar_recent_button">Последен бутон</string>
+ <string name="navbar_search_button">Бутон за търсене</string>
+ <string name="navbar_back_button">Бутон \"назад\"</string>
+ <string name="navbar_empty_button">Празен бутон</string>
+ <string name="navbar_menu_conditional_button">Меню бутон (Автоскриване)</string>
+ <string name="navbar_menu_always_button">Меню бутон (Видим)</string>
+ <string name="navbar_menu_big_button">Меню бутон</string>
+ <string name="accessibility_dpad_left">Курсора наляво</string>
+ <string name="accessibility_dpad_right">Курсора надясно</string>
+ <string name="advanced_dev_option_wipe_app">Изтриване данни на приложението</string>
+ <string name="advanced_dev_option_force_stop">Принудително спиране</string>
+ <string name="advanced_dev_option_uninstall">Деинсталиране</string>
+ <string name="accessibility_notification_brightness">Яркостта на светлината</string>
+ <string name="accessibility_quick_settings_profiles_off">Изключени профили.</string>
+ <string name="accessibility_quick_settings_profiles">Профил: <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Профилите са изключени.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Профила е сменен с <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="quick_settings_compass_init">Стартиране на\u2026</string>
+ <string name="led_notification_title">Настройки на светлината</string>
+ <string name="led_notification_text">LED светлини, разрешени в настройките</string>
+ <string name="qs_tile_edit_header_instruction">Натиснете и задръжте плочка за да я пренаредите или премахнете</string>
+ <string name="quick_settings_edit_label">Редактиране на плочки</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Не може да изтрие редактираната на плочка</string>
+ <string name="qs_tiles_reset_confirmation">Нулиране бързи настройки на плочки и връщане на конфигурацията по подразбиране?</string>
+ <string name="quick_settings_tile_reset_to_default">Възстанови оформление по подразбиране</string>
+ <string name="quick_settings_title_header">Горен</string>
+ <string name="quick_settings_title_tiles">Плочки</string>
+ <string name="quick_settings_title_show_weather">Показване на времето</string>
+ <string name="quick_settings_title_show_brightness_slider">Показване на плъзгача за яркост</string>
+ <string name="quick_settings_title_enlarge_first_row">Уголемяване на първия ред</string>
+ <string name="screen_pinning_description_no_navbar">Това допълнение ще остане активено, докато не натиснете и зъдържите на бутона \"Назад\".</string>
+ <string name="quick_settings_custom_tile_detail_title">Персонализирана плочка</string>
+ <string name="quick_settings_remove">Премахни на плочки</string>
+ <string name="quick_settings_network_adb_label">ADB чрез мрежата</string>
+ <string name="quick_settings_compass_label">Компас</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Системни профили</string>
+ <string name="quick_settings_profiles_off">Деактивирани профили</string>
+ <string name="quick_settings_heads_up_label">Изскачащи известия</string>
+ <string name="quick_settings_battery_saver_label">Пестене на батерия</string>
+ <string name="quick_settings_caffeine_label">Кофеин</string>
+ <string name="accessibility_quick_settings_sync_off">Изключена синхронизация.</string>
+ <string name="accessibility_quick_settings_sync_on">Включена синхронизация.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Синхронизацията е изключена.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Синхронизацията е включена.</string>
+ <string name="quick_settings_sync_label">Синхронизация</string>
+ <string name="quick_settings_volume_panel_label">Панел на звука</string>
+ <string name="quick_settings_usb_tether_label">Тетъринг през USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Изключване на дисплея</string>
+ <string name="quick_settings_lockscreen_label">Заключен екран</string>
+ <string name="quick_settings_ambient_display_label">Атмосферен екран</string>
+ <string name="quick_settings_lockscreen_label_enforced">Принудително заключен екран</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Деактивирано от профила</string>
+ <string name="accessibility_quick_settings_screen_timeout">Изключване на екрана след: <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Изключване на екрана е променен на <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="qs_tile_performance">Режим на батерията</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Режим на батерията: Енергоспестяващ.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Режим на батерията: Балансиран.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Режим на батерията: Производителен.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Режим на батерията: Ефективен.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Режим на батерията: Скоростен.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Преминаване в режим Енергоспестяващ.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Преминаване в режим Балансиран.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Преминаване в режим Производителен.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Преминаване в режим Ефективност.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Преминаване в режим Скоростен.</string>
+ <string name="quick_settings_performance_profile_detail_title">Режим на батерията</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Изключване на заключване на екрана.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Включване на заключване на екран.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Заключване екран е изключено.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Заключване екран е включено.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Атмосферен екран изключен.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Атмосферен екран включен.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Атмосферен екран е изключен.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Атмосферен екран е включен.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Изключи Изскачащи съобщения.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Включи Изскачащи съобщения.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Изскачащите известия са изключени.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Изскачащите известия са включени.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Кофеин изключен.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Кофеин включен.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Режим за пестене на батерията изключен.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Режим за запазване на батерията нключен.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Режим за пестене на батерията е изключен.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Пестене на батерията е включено.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Динамични плочки</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Следваща аларма</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME селектор</string>
+ <string name="dynamic_qs_tile_su_label">Root достъп</string>
+ <string name="accessibility_quick_settings_live_display_off">Изключи Адаптивен екран.</string>
+ <string name="accessibility_quick_settings_live_display_auto">Адаптивен екран: автоматичен режим.</string>
+ <string name="accessibility_quick_settings_live_display_day">Адаптивен екран: дневен режим.</string>
+ <string name="accessibility_quick_settings_live_display_night">Адаптивен екран: нощен режим.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">Адаптивен екран: външен режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">Адаптивен екран е изключен.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">Адаптивен екран е променен на автоматичен режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">Адаптивен екран е променен на дневен режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">Адаптивен екран е променен на нощен режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">Адаптивен екран е променен на външен режим.</string>
+ <string name="quick_settings_title_advanced_location">Три-посочно местоположение</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Настройка на местоположение: икономичен режим на батерията.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Доклад на местоположение: само по GPS.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Доклад на местоположение: прецизен режим.</string>
+ <string name="quick_settings_location_detail_title">Режим за местоположение</string>
+ <string name="quick_settings_location_battery_saving_label">Пестене на батерия</string>
+ <string name="quick_settings_location_gps_only_label">Само чрез GPS</string>
+ <string name="quick_settings_location_high_accuracy_label">Висока точност</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Доклад на местоположение променен в икономичен режим на батерията.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Доклад на местоположение променен в режим GPS.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Доклад на местоположение променен в прецизен режим.</string>
+ <string name="quick_settings_tiles_category_system">Системни плочки</string>
+ <string name="quick_settings_tiles_add_tiles">Добавяне на плочка</string>
+ <string name="hotspot_apm_message">Свързването към мобилна мрежа не е възможно, докато сте в Самолетен режим. Изключете го и след това опитайте отново.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Фенерчето е включено</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Натиснете, за изключване</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/cm_arrays.xml b/packages/SystemUI/res/values-bn-rBD/cm_arrays.xml
new file mode 100644
index 0000000..e694747
--- /dev/null
+++ b/packages/SystemUI/res/values-bn-rBD/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>উঃ</item>
+ <item>উঃপূঃ</item>
+ <item>পূঃ</item>
+ <item>দঃপূঃ</item>
+ <item>দঃ</item>
+ <item>দঃপঃ</item>
+ <item>পঃ</item>
+ <item>উঃপঃ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/cm_strings.xml b/packages/SystemUI/res/values-bn-rBD/cm_strings.xml
new file mode 100644
index 0000000..8db74b9
--- /dev/null
+++ b/packages/SystemUI/res/values-bn-rBD/cm_strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="navbar_dialog_title">দায়িত্ব অর্পণ পদক্ষেপ বেছে নিন</string>
+ <string name="navbar_home_button">মূল বোতাম</string>
+ <string name="navbar_recent_button">সাম্প্রতিক বোতাম</string>
+ <string name="navbar_search_button">অনুসন্ধান বোতাম</string>
+ <string name="navbar_back_button">ব্যাক বোতাম</string>
+ <string name="navbar_menu_conditional_button">মেনু (স্বয়ংক্রিয়অদৃশ্য) বোতাম</string>
+ <string name="navbar_menu_always_button">মেনু (সর্বদাদৃশ্যমান) বোতাম</string>
+ <string name="navbar_menu_big_button">মেনু বোতাম</string>
+ <string name="accessibility_dpad_left">কার্সর বামে</string>
+ <string name="accessibility_dpad_right">কার্সর ডানে</string>
+ <string name="advanced_dev_option_wipe_app">অ্যাপ ডাটা মুছে ফেলুন</string>
+ <string name="advanced_dev_option_force_stop">জোরপূর্বক বন্ধ</string>
+ <string name="advanced_dev_option_uninstall">আনইনস্টল</string>
+ <string name="quick_settings_compass_init">আরম্ভ করা\u2026</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ca/cm_arrays.xml b/packages/SystemUI/res/values-ca/cm_arrays.xml
new file mode 100644
index 0000000..cb6fbec
--- /dev/null
+++ b/packages/SystemUI/res/values-ca/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ca/cm_strings.xml b/packages/SystemUI/res/values-ca/cm_strings.xml
new file mode 100644
index 0000000..ed84e26
--- /dev/null
+++ b/packages/SystemUI/res/values-ca/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Llisca a la dreta per %1$s</string>
+ <string name="right_shortcut_hint">Llisca a l\'esquerra per %1$s</string>
+ <string name="lockscreen_message">Toca una icona a l\'esquerra o a la dreta per reassignar una drecera a la pantalla de bloqueig.</string>
+ <string name="lockscreen_default_target">Per defecte</string>
+ <string name="select_application">Selecciona l\'aplicació</string>
+ <string name="lockscreen_choose_action_title">Tria una acció</string>
+ <string name="lockscreen_none_target">Cap</string>
+ <string name="navbar_dialog_title">Escull l\'acció a assignar</string>
+ <string name="navbar_home_button">Botó Inici</string>
+ <string name="navbar_recent_button">Botó Recent</string>
+ <string name="navbar_search_button">Botó Cerca</string>
+ <string name="navbar_back_button">Botó Enrera</string>
+ <string name="navbar_empty_button">Botó buit</string>
+ <string name="navbar_menu_conditional_button">Botó Menú (autoAmaga)</string>
+ <string name="navbar_menu_always_button">Botó Menú (mostraSempre)</string>
+ <string name="navbar_menu_big_button">Botó Menú</string>
+ <string name="accessibility_dpad_left">Cursor esquerra</string>
+ <string name="accessibility_dpad_right">Cursor dreta</string>
+ <string name="advanced_dev_option_wipe_app">Neteja dades de l\'aplicació</string>
+ <string name="advanced_dev_option_force_stop">Força tancament</string>
+ <string name="advanced_dev_option_uninstall">Desinstal·la</string>
+ <string name="accessibility_notification_brightness">Brillantor dels llums</string>
+ <string name="accessibility_quick_settings_profiles_off">Perfils desactivats.</string>
+ <string name="accessibility_quick_settings_profiles">Perfils: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">S\'han desactivat els perfils.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Perfil canviat a <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">S\'està inicialitzant\u2026</string>
+ <string name="led_notification_title">Ajustaments de llums</string>
+ <string name="led_notification_text">Llum LED habilitada per ajustos</string>
+ <string name="qs_tile_edit_header_instruction">Prem i aguanta les cel·les per reordenar-les</string>
+ <string name="quick_settings_edit_label">Edita cel·les</string>
+ <string name="quick_settings_cannot_delete_edit_tile">No s\'ha pogut esborrar la cel·la Edita</string>
+ <string name="qs_tiles_reset_confirmation">Vols restaurar les cel·les d\'ajustaments ràpids a la configuració predeterminada?</string>
+ <string name="quick_settings_tile_reset_to_default">Restaura la disposició per defecte</string>
+ <string name="quick_settings_title_header">Capçalera</string>
+ <string name="quick_settings_title_tiles">Cel·les</string>
+ <string name="quick_settings_title_show_weather">Mostra el temps</string>
+ <string name="quick_settings_title_show_brightness_slider">Mostra la barra liscant de brillantor</string>
+ <string name="quick_settings_title_enlarge_first_row">Engrandeix la primera fila</string>
+ <string name="screen_pinning_description_no_navbar">Això ho manté a la vista fins que el desancoris. Toca i aguanta el botó Enrera per desancorar.</string>
+ <string name="quick_settings_custom_tile_detail_title">Cel·la personalitzada</string>
+ <string name="quick_settings_remove">Esborra cel·la</string>
+ <string name="quick_settings_network_adb_label">ADB sobre xarxa</string>
+ <string name="quick_settings_compass_label">Brúixola</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Perfils de sistema</string>
+ <string name="quick_settings_profiles_off">Perfils desactivats</string>
+ <string name="quick_settings_heads_up_label">Notificacions emergents</string>
+ <string name="quick_settings_battery_saver_label">Estalvi de bateria</string>
+ <string name="quick_settings_caffeine_label">Cafeïna</string>
+ <string name="accessibility_quick_settings_sync_off">Sinc desactivada.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinc activada.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">S\'ha desactivat la sincronització.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">S\'ha activat la sincronització.</string>
+ <string name="quick_settings_sync_label">Sinc</string>
+ <string name="quick_settings_volume_panel_label">Panell de volum</string>
+ <string name="quick_settings_usb_tether_label">Ancoratge USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Temps d\'espera de la pantalla</string>
+ <string name="quick_settings_lockscreen_label">Pantalla de bloqueig</string>
+ <string name="quick_settings_ambient_display_label">Pantalla ambient</string>
+ <string name="quick_settings_lockscreen_label_enforced">Pantalla de bloqueig aplicada</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Deshabilitat pel perfil</string>
+ <string name="accessibility_quick_settings_screen_timeout">Temps d\'espera de la pantalla: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Temps d\'espera de la pantalla canviat a <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Mode de la bateria</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Mode de la bateria: mode estalvi d\'energia.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Mode de la bateria: mode equilibrat.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Mode de la bateria: mode rendiment.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Mode de la bateria: mode d\'eficiència.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Mode de la bateria: mode ràpid.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Mode de la bateria canviat a mode estalvi d\'energia.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Mode de la bateria canviat a mode equilibrat.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Mode de la bateria canviat a mode rendiment.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Mode de la bateria canviat a mode d\'eficiència.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Mode de la bateria canviat a mode ràpid.</string>
+ <string name="quick_settings_performance_profile_detail_title">Mode de la bateria</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Pantalla de bloqueig desactivada.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Pantalla de bloqueig activada.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">S\'ha desactivat la pantalla de bloqueig.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">S\'ha activat la pantalla de bloqueig.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Pantalla ambient desactivada.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Pantalla ambient activada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">S\'ha desactivat la pantalla ambient.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">S\'ha activat la pantalla ambient.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Notificacions emergents apagades.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Notificacions emergents activades.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">S\'han apagat les notificacions emergents.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">S\'han encès les notificacions emergents.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Cafeïna desactivada.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Cafeïna activada.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Estalvi de bateria apagat.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Estalvi de bateria encès.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">S\'ha apagat l\'estalvi de bateria.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">S\'ha encès l\'estalvi de bateria.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Cel·la dinàmica</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Propera alarma</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Selector de l\'IME</string>
+ <string name="dynamic_qs_tile_su_label">Accés Superusuari</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay desactivat.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: mode automàtic.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: mode diurn.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: mode nocturn.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: mode exterior.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">S\'ha desactivat el LiveDisplay.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay canviat al mode automàtic.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay canviat al mode diurn.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay canviat al mode nocturn.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay canviat al mode exterior.</string>
+ <string name="quick_settings_title_advanced_location">Localització per triangulació</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Informes d\'ubicació: Mode d\'estalvi de bateria.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Informes d\'ubicació: Mode només sensors.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Informes d\'ubicació: Mode d\'alta precisió.</string>
+ <string name="quick_settings_location_detail_title">Mode d\'ubicació</string>
+ <string name="quick_settings_location_battery_saving_label">Estalvi de bateria</string>
+ <string name="quick_settings_location_gps_only_label">Només dispositiu</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precisió</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Informes d\'ubicació canviats al mode d\'estalvi d\'energia.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Informes d\'ubicació canviats al mode només sensors.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Informes d\'ubicació canviats al mode d\'alta precisió.</string>
+ <string name="quick_settings_tiles_category_system">Cel·les del sistema</string>
+ <string name="quick_settings_tiles_add_tiles">Afegeix una cel·la</string>
+ <string name="hotspot_apm_message">No es pot connectar a xarxes mòbils mentre el mode Avió està habilitat. Deshabilita el mode Avió i intenta-ho de nou.</string>
+ <string name="quick_settings_tile_flashlight_not_title">La llanterna està encesa</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Pica per apagar-la</string>
+</resources>
diff --git a/packages/SystemUI/res/values-cs/cm_arrays.xml b/packages/SystemUI/res/values-cs/cm_arrays.xml
new file mode 100644
index 0000000..ca2178e
--- /dev/null
+++ b/packages/SystemUI/res/values-cs/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>JV</item>
+ <item>J</item>
+ <item>JZ</item>
+ <item>Z</item>
+ <item>SZ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-cs/cm_strings.xml b/packages/SystemUI/res/values-cs/cm_strings.xml
new file mode 100644
index 0000000..7e4c34e
--- /dev/null
+++ b/packages/SystemUI/res/values-cs/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Přejeďte doprava pro %1$s</string>
+ <string name="right_shortcut_hint">Přejeďte doleva pro %1$s</string>
+ <string name="lockscreen_message">Dotykem na ikonu na levé nebo pravé straně zamykací obrazovky změňte zástupce.</string>
+ <string name="lockscreen_default_target">Výchozí</string>
+ <string name="select_application">Vybrat aplikaci</string>
+ <string name="lockscreen_choose_action_title">Zvolit akci</string>
+ <string name="lockscreen_none_target">Žádný</string>
+ <string name="navbar_dialog_title">Vybrat akci k přiřazení</string>
+ <string name="navbar_home_button">Tlačítko Domů</string>
+ <string name="navbar_recent_button">Tlačítko Nedávné</string>
+ <string name="navbar_search_button">Tlačítko Hledat</string>
+ <string name="navbar_back_button">Tlačítko Zpět</string>
+ <string name="navbar_empty_button">Prázdné tlačítko</string>
+ <string name="navbar_menu_conditional_button">Tlačítko (skrývat) Nabídka</string>
+ <string name="navbar_menu_always_button">Tlačítko (vždy zobrazit) Nabídka</string>
+ <string name="navbar_menu_big_button">Tlačítko Nabídka</string>
+ <string name="accessibility_dpad_left">Kurzor doleva</string>
+ <string name="accessibility_dpad_right">Kurzor doprava</string>
+ <string name="advanced_dev_option_wipe_app">Vymazat data aplikací</string>
+ <string name="advanced_dev_option_force_stop">Vynutit ukončení</string>
+ <string name="advanced_dev_option_uninstall">Odinstalovat</string>
+ <string name="accessibility_notification_brightness">Jas podsvícení</string>
+ <string name="accessibility_quick_settings_profiles_off">Profily vyp.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profily vypnuty.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil změněn na <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicializace\u2026</string>
+ <string name="led_notification_title">Nastavení jasu</string>
+ <string name="led_notification_text">LED světlo povoleno v nastavení</string>
+ <string name="qs_tile_edit_header_instruction">Stiskněte a podržte tlačítko dlaždice pro přeskupení</string>
+ <string name="quick_settings_edit_label">Úprava dlaždic</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Dlaždici „Úprava dlaždic“ nelze odstranit</string>
+ <string name="qs_tiles_reset_confirmation">Obnovit výchozí dlaždice rychlého nastavení?</string>
+ <string name="quick_settings_tile_reset_to_default">Obnovit výchozí rozložení</string>
+ <string name="quick_settings_title_header">Záhlaví</string>
+ <string name="quick_settings_title_tiles">Dlaždice</string>
+ <string name="quick_settings_title_show_weather">Zobrazit počasí</string>
+ <string name="quick_settings_title_show_brightness_slider">Zobrazit posuvník jasu</string>
+ <string name="quick_settings_title_enlarge_first_row">Zvětšit první řádek</string>
+ <string name="screen_pinning_description_no_navbar">Zůstává zobrazeno, dokud není uvolněn. Dotykem a podržením tlačítka Zpět bude provedeno uvolnění.</string>
+ <string name="quick_settings_custom_tile_detail_title">Vlastní dlaždice</string>
+ <string name="quick_settings_remove">Odebrat dlaždici</string>
+ <string name="quick_settings_network_adb_label">ADB přes síť</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systémové profily</string>
+ <string name="quick_settings_profiles_off">Profily zakázány</string>
+ <string name="quick_settings_heads_up_label">Plovoucí upozornění</string>
+ <string name="quick_settings_battery_saver_label">Spořič baterie</string>
+ <string name="quick_settings_caffeine_label">Kofein</string>
+ <string name="accessibility_quick_settings_sync_off">Synch. vyp.</string>
+ <string name="accessibility_quick_settings_sync_on">Synch. zap.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchronizace vypnuta.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchronizace zapnuta.</string>
+ <string name="quick_settings_sync_label">Synchronizace</string>
+ <string name="quick_settings_volume_panel_label">Panel hlasitosti</string>
+ <string name="quick_settings_usb_tether_label">USB tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Zhasínání obrazovky</string>
+ <string name="quick_settings_lockscreen_label">Zamykací obrazovka</string>
+ <string name="quick_settings_ambient_display_label">Ambientní zobrazení</string>
+ <string name="quick_settings_lockscreen_label_enforced">Vynucení zámku obrazovky</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Potlačen profilem</string>
+ <string name="accessibility_quick_settings_screen_timeout">Limit vypnutí obrazovky: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Limit vypnutí obrazovky změněn na <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Režim baterie</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Režim baterie: úspora energie.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Režim baterie: vyvážený.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Režim baterie: výkonný.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Režim baterie: efektivita</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Režim baterie: výkon</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Režim baterie změněn na úsporu energie.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Režim baterie změněn na vyvážený.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Režim baterie změněn na vysoký výkon.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Režim baterie změněn na efektivní.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Režim baterie změněn na výkonný.</string>
+ <string name="quick_settings_performance_profile_detail_title">Režim baterie</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Zámek displeje vyp.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Zámek displeje zap.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Zámek displeje je vypnutý.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Zámek displeje je zapnutý.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambientní zobrazení vypnuto.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambientní zobrazení zapnuto.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambientní zobrazení vypnuto.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambientní zobrazení zapnuto.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Plovoucí upozorněn vyp.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Plovoucí upozornění zap.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Plovoucí upozorněn vyp.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Plovoucí upozornění zap.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kofein vyp.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kofein zap.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Spořič baterie vyp.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Spořič baterie zap.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Spořič baterie vypnut.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Spořič baterie zapnut.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamické dlaždice</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Další budík</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Výběr IME</string>
+ <string name="dynamic_qs_tile_su_label">Root přístup</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay vyp.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automatický režim.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: režim ve dne.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: režim v noci.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: režim venku.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay vypnutý.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay změněn na automatický režim.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay změněn na režim ve dne.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay změněn na režim v noci.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay změněn na režim venku.</string>
+ <string name="quick_settings_title_advanced_location">Třístavové nastavení určení polohy</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Zjištění polohy: úsporný režim.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Zjištění polohy: pouze GPS.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Zjištění polohy: vysoká přesnost.</string>
+ <string name="quick_settings_location_detail_title">Poloha</string>
+ <string name="quick_settings_location_battery_saving_label">Úspora baterie</string>
+ <string name="quick_settings_location_gps_only_label">Pouze zařízení</string>
+ <string name="quick_settings_location_high_accuracy_label">Vysoká přesnost</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Zjištění polohy změněno na úsporu baterie.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Zjištění polohy změněno na pouze GPS.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Zjištění polohy změněno na vysokou přesnost.</string>
+ <string name="quick_settings_tiles_category_system">Systémové dlaždice</string>
+ <string name="quick_settings_tiles_add_tiles">Přidat dlaždici</string>
+ <string name="hotspot_apm_message">Nelze se připojit k mobilním datům při zapnutém režimu „Letadlo“. Vypněte tento režim a zkuste to znovu.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Svítilna zapnuta</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Dotykem vypněte</string>
+</resources>
diff --git a/packages/SystemUI/res/values-da/cm_arrays.xml b/packages/SystemUI/res/values-da/cm_arrays.xml
new file mode 100644
index 0000000..9763e17
--- /dev/null
+++ b/packages/SystemUI/res/values-da/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NØ</item>
+ <item>Ø</item>
+ <item>SØ</item>
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>NV</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-da/cm_strings.xml b/packages/SystemUI/res/values-da/cm_strings.xml
new file mode 100644
index 0000000..7102c5e
--- /dev/null
+++ b/packages/SystemUI/res/values-da/cm_strings.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Stryg til højre for %1$s</string>
+ <string name="right_shortcut_hint">Stryg til venstre for %1$s</string>
+ <string name="lockscreen_message">Tryk på et ikon til venstre eller højre for at tildele en genvej til skærmlåsen.</string>
+ <string name="lockscreen_default_target">Standard</string>
+ <string name="select_application">Vælg applikation</string>
+ <string name="lockscreen_choose_action_title">Vælg handling</string>
+ <string name="lockscreen_none_target">Ingen</string>
+ <string name="navbar_dialog_title">Vælg handling at tildele</string>
+ <string name="navbar_home_button">Startknap</string>
+ <string name="navbar_recent_button">Seneste-knap</string>
+ <string name="navbar_search_button">Søgeknap</string>
+ <string name="navbar_back_button">Tilbageknap</string>
+ <string name="navbar_empty_button">Tom knap</string>
+ <string name="navbar_menu_conditional_button">Menuknap (auto-skjul)</string>
+ <string name="navbar_menu_always_button">Menuknap (vis altid)</string>
+ <string name="navbar_menu_big_button">Menuknap</string>
+ <string name="accessibility_dpad_left">Venstremarkør</string>
+ <string name="accessibility_dpad_right">Højremarkør</string>
+ <string name="advanced_dev_option_wipe_app">Ryd appdata</string>
+ <string name="advanced_dev_option_force_stop">Gennemtving stop</string>
+ <string name="advanced_dev_option_uninstall">Afinstallér</string>
+ <string name="accessibility_notification_brightness">Lysstyrke</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiler fra.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiler slået fra.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil ændret til <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Initialisere\u2026</string>
+ <string name="led_notification_title">Indstillinger for lys</string>
+ <string name="led_notification_text">LED-lys aktiveret via indstillinger</string>
+ <string name="qs_tile_edit_header_instruction">Tryk og hold, for at flytte fliserne</string>
+ <string name="quick_settings_edit_label">Redigér fliser</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Kan ikke slette Redigér-flisen</string>
+ <string name="quick_settings_tile_reset_to_default">Nulstil til standardlayout</string>
+ <string name="quick_settings_title_header">Overskrift</string>
+ <string name="quick_settings_title_tiles">Fliser</string>
+ <string name="quick_settings_title_show_weather">Vis vejr</string>
+ <string name="screen_pinning_description_no_navbar">Dette fastholder det i visningen indtil du frigører det. Tryk og hold tilbage-knappen nede for at frigøre.</string>
+ <string name="quick_settings_custom_tile_detail_title">Tilpasset flise</string>
+ <string name="quick_settings_remove">Fjern flise</string>
+ <string name="quick_settings_network_adb_label">ADB via netværk</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systemprofiler</string>
+ <string name="quick_settings_profiles_off">Profiler deaktiveret</string>
+ <string name="quick_settings_heads_up_label">Svævende meddelelser</string>
+ <string name="quick_settings_battery_saver_label">Strømsparetilstand</string>
+ <string name="accessibility_quick_settings_sync_off">Synkr. fra.</string>
+ <string name="accessibility_quick_settings_sync_on">Synkr. til.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synkr. er slået fra.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synkr. er slået til.</string>
+ <string name="quick_settings_sync_label">Synkr.</string>
+ <string name="quick_settings_volume_panel_label">Lydstyrkepanel</string>
+ <string name="quick_settings_usb_tether_label">USB-tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Skærm-timeout</string>
+ <string name="quick_settings_lockscreen_label">Låseskærm</string>
+ <string name="quick_settings_ambient_display_label">Inaktivitetsvisning</string>
+ <string name="quick_settings_lockscreen_label_enforced">Tving låseskærm</string>
+ <string name="accessibility_quick_settings_screen_timeout">Tidsudløb for skærm: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Tidsudløb for skærm ændret til <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Batteritilstand</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Batteri tilstand: strømsparetilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Batteri tilstand: balanceret tilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Batteri tilstand: høj ydeevne tilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Batteritilstand: effektivitetstilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Batteritilstand: hurtig tilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Batteritilstand skiftet til strømsparetilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Batteritilstand ændret til balanceret tilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Batteritilstand ændret til tilstanden høj ydeevne.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Batteritilstand ændret til effektivitetstilstand.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Batteritilstand ændret til hurtigt tilstand.</string>
+ <string name="quick_settings_performance_profile_detail_title">Batteritilstand</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Skærmlås fra.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Skærmlås til.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Skærmlås er slået fra.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Skærmlås er slået til.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Inaktivitetsvisning fra.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Inaktivitetsvisning til.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Inaktivitetsvisning er slået fra.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Inaktivitetsvisning er slået til.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Svævende meddelelser fra.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Svævende meddelelser til.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Svævende meddelelser er slået fra.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Svævende meddelelser er slået til.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Strømsparetilstand fra.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Strømsparetilstand til.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Strømsparetilstand er slået fra.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Strømsparetilstand er slået til.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamisk flise</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Næste alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME-vælger</string>
+ <string name="dynamic_qs_tile_su_label">Root-adgang</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay fra.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automatisk tilstand.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: dag tilstand.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nat tilstand.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: udendørstilstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay er slået fra.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay ændret til auto tilstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay ændret til dag tilstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay ændret til nat tilstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay ændret til udendørstilstand.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Placeringsrapportering: Batterisparetilstand.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Placeringsrapportering: Kun sensorer-tilstand.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Placeringsrapportering: Høj nøjagtighed-tilstand.</string>
+ <string name="quick_settings_location_detail_title">Placeringstilstand</string>
+ <string name="quick_settings_location_battery_saving_label">Batteribesparelse</string>
+ <string name="quick_settings_location_gps_only_label">Kun enhed</string>
+ <string name="quick_settings_location_high_accuracy_label">Høj nøjagtighed</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Rapportering af placering ændret til batterisparetilstand.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Lokationsrapportering ændret til kun at bruge sensorer.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Lokationsrapportering ændret til høj nøjagtighed.</string>
+ <string name="quick_settings_tiles_category_system">System-fliser</string>
+ <string name="quick_settings_tiles_add_tiles">Tilføj en flise</string>
+</resources>
diff --git a/packages/SystemUI/res/values-de/cm_arrays.xml b/packages/SystemUI/res/values-de/cm_arrays.xml
new file mode 100644
index 0000000..b156d8e
--- /dev/null
+++ b/packages/SystemUI/res/values-de/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NO</item>
+ <item>O</item>
+ <item>SO</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-de/cm_strings.xml b/packages/SystemUI/res/values-de/cm_strings.xml
new file mode 100644
index 0000000..e63f2d0
--- /dev/null
+++ b/packages/SystemUI/res/values-de/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> – <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Nach rechts wischen für %1$s</string>
+ <string name="right_shortcut_hint">Nach links wischen für %1$s</string>
+ <string name="lockscreen_message">Berühren Sie das linke oder rechte Symbol, um eine Sperrbildschirm-Verknüpfung festzulegen.</string>
+ <string name="lockscreen_default_target">Standard</string>
+ <string name="select_application">App wählen</string>
+ <string name="lockscreen_choose_action_title">Aktion auswählen</string>
+ <string name="lockscreen_none_target">Keine</string>
+ <string name="navbar_dialog_title">Funktion zuweisen</string>
+ <string name="navbar_home_button">Home</string>
+ <string name="navbar_recent_button">Anwendungsverlauf-Taste</string>
+ <string name="navbar_search_button">Suche-Taste</string>
+ <string name="navbar_back_button">Zurück-Taste</string>
+ <string name="navbar_empty_button">Nicht belegt</string>
+ <string name="navbar_menu_conditional_button">Menü (automatisch ausblenden)</string>
+ <string name="navbar_menu_always_button">Menü (immer sichtbar)</string>
+ <string name="navbar_menu_big_button">Menüschaltfläche</string>
+ <string name="accessibility_dpad_left">Pfeiltaste links</string>
+ <string name="accessibility_dpad_right">Pfeiltaste rechts</string>
+ <string name="advanced_dev_option_wipe_app">Anwendungsdaten löschen</string>
+ <string name="advanced_dev_option_force_stop">Beenden erzwingen</string>
+ <string name="advanced_dev_option_uninstall">Deinstallieren</string>
+ <string name="accessibility_notification_brightness">Helligkeit</string>
+ <string name="accessibility_quick_settings_profiles_off">Profile aus.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profile ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil auf <xliff:g id="profile" example="Default">%s</xliff:g> geändert.</string>
+ <string name="quick_settings_compass_init">Initialisierung\u2026</string>
+ <string name="led_notification_title">LED-Einstellungen</string>
+ <string name="led_notification_text">Benachrichtigungs-LED durch Einstellungen aktiviert</string>
+ <string name="qs_tile_edit_header_instruction">Drücken und halten Sie die Kacheln, um sie neu anzuordnen.</string>
+ <string name="quick_settings_edit_label">Kacheln bearbeiten</string>
+ <string name="quick_settings_cannot_delete_edit_tile">\"Kacheln bearbeiten\" kann nicht gelöscht werden</string>
+ <string name="qs_tiles_reset_confirmation">Kacheln der Schnelleinstellungen auf Standardkonfiguration zurücksetzen?</string>
+ <string name="quick_settings_tile_reset_to_default">Standardlayout wiederherstellen</string>
+ <string name="quick_settings_title_header">Kopfzeile</string>
+ <string name="quick_settings_title_tiles">Kacheln</string>
+ <string name="quick_settings_title_show_weather">Wetter anzeigen</string>
+ <string name="quick_settings_title_show_brightness_slider">Helligkeitsregler anzeigen</string>
+ <string name="quick_settings_title_enlarge_first_row">Erste Zeile vergrößern</string>
+ <string name="screen_pinning_description_no_navbar">Dies fixiert die aktuelle Ansicht. Zum Lösen die Zurück-Taste drücken und halten.</string>
+ <string name="quick_settings_custom_tile_detail_title">Benutzerdefinierte Kachel</string>
+ <string name="quick_settings_remove">Kachel entfernen</string>
+ <string name="quick_settings_network_adb_label">ADB über Netzwerk</string>
+ <string name="quick_settings_compass_label">Kompass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systemprofile</string>
+ <string name="quick_settings_profiles_off">Profile deaktiviert</string>
+ <string name="quick_settings_heads_up_label">Pop-up</string>
+ <string name="quick_settings_battery_saver_label">Akku-Sparmodus</string>
+ <string name="quick_settings_caffeine_label">Koffein</string>
+ <string name="accessibility_quick_settings_sync_off">Synchronisierung aus.</string>
+ <string name="accessibility_quick_settings_sync_on">Synchronisierung an.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchronisierung ist ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchronisierung ist eingeschaltet.</string>
+ <string name="quick_settings_sync_label">Synchronisieren</string>
+ <string name="quick_settings_volume_panel_label">Lautstärke</string>
+ <string name="quick_settings_usb_tether_label">USB-Tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Bildschirm-Timeout</string>
+ <string name="quick_settings_lockscreen_label">Bildschirmsperre</string>
+ <string name="quick_settings_ambient_display_label">Inaktivitätsdisplay</string>
+ <string name="quick_settings_lockscreen_label_enforced">Bildschirmsperre aktiviert</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Durch Profil gesperrt</string>
+ <string name="accessibility_quick_settings_screen_timeout">Ruhezustand nach <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Zeit bis zum Ruhezustand in <xliff:g id="timeout" example="30 seconds">%s</xliff:g> geändert.</string>
+ <string name="qs_tile_performance">Akkumodus</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Akkumodus: Energie sparen.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Akkumodus: Ausgeglichen.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Akkumodus: Mehr Leistung.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Akkumodus: Effizient.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Akkumodus: Schnell.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Akkumodus auf \"Energie sparen\" geändert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Akkumodus auf \"Ausgeglichen\" geändert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Akkumodus auf \"Mehr Leistung\" geändert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Akkumodus auf \"Effizient\" geändert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Akkumodus auf \"Schnell\" geändert.</string>
+ <string name="quick_settings_performance_profile_detail_title">Akkumodus</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Bildschirmsperre aus.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Bildschirmsperre an.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Bildschirmsperre ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Bildschirmsperre eingeschaltet.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Inaktivitätsdisplay aus.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Inaktivitätsdisplay an.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Inaktivitätsdisplay ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Inaktivitätsdisplay eingeschaltet.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Pop-up aus.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Pop-up an.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Pop-up ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Pop-up eingeschaltet.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Koffein aus.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Koffein an.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Akku-Sparmodus aus.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Akku-Sparmodus an.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Akku-Sparmodus ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Akku-Sparmodus eingeschaltet.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamische Kachel</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Nächster Alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Eingabemethode</string>
+ <string name="dynamic_qs_tile_su_label">Root-Zugriff</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay aus.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: Automatisch.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: Tag.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: Nacht.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: Außen.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay ausgeschaltet.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay auf Auto-Modus geändert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay auf Tag-Modus geändert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay auf Nacht-Modus geändert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay auf Außen-Modus geändert.</string>
+ <string name="quick_settings_title_advanced_location">Standort mit drei Zuständen</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Standortdienste: Energiesparmodus</string>
+ <string name="accessibility_quick_settings_location_gps_only">Standortdienste: Nur Gerät</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Standortdienste: Hohe Genauigkeit</string>
+ <string name="quick_settings_location_detail_title">Standortmodus</string>
+ <string name="quick_settings_location_battery_saving_label">Akku-Sparmodus</string>
+ <string name="quick_settings_location_gps_only_label">Nur Gerät</string>
+ <string name="quick_settings_location_high_accuracy_label">Hohe Genauigkeit</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Standortmodus auf \"Energiesparmodus\" geändert.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Standortmodus auf \"Nur Gerät\" geändert.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Standortmodus auf \"Hohe Genauigkeit\" geändert.</string>
+ <string name="quick_settings_tiles_category_system">System-Kacheln</string>
+ <string name="quick_settings_tiles_add_tiles">Kachel hinzufügen</string>
+ <string name="hotspot_apm_message">Im Flugmodus ist keine Verbindung zum Mobilfunknetz möglich. Deaktivieren Sie den Flugmodus und versuchen Sie es erneut.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Taschenlampe ist eingeschaltet</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Zum Ausschalten tippen</string>
+</resources>
diff --git a/packages/SystemUI/res/values-el/cm_arrays.xml b/packages/SystemUI/res/values-el/cm_arrays.xml
new file mode 100644
index 0000000..2a1bb43
--- /dev/null
+++ b/packages/SystemUI/res/values-el/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Β</item>
+ <item>ΒΑ</item>
+ <item>Α</item>
+ <item>ΝΑ</item>
+ <item>Ν</item>
+ <item>ΝΔ</item>
+ <item>Δ</item>
+ <item>ΒΔ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-el/cm_strings.xml b/packages/SystemUI/res/values-el/cm_strings.xml
new file mode 100644
index 0000000..d2e57e1
--- /dev/null
+++ b/packages/SystemUI/res/values-el/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Σύρετε προς τα δεξιά για %1$s</string>
+ <string name="right_shortcut_hint">Σύρετε προς τα αριστερά για %1$s</string>
+ <string name="lockscreen_message">Πιέστε ένα εικονίδιο στα αριστερά ή δεξιά για να αντιστοιχίσετε εκ νέου μια συντόμευση οθόνης κλειδώματος.</string>
+ <string name="lockscreen_default_target">Προεπιλογή</string>
+ <string name="select_application">Επιλέξτε εφαρμογή</string>
+ <string name="lockscreen_choose_action_title">Επιλέξτε ενέργεια</string>
+ <string name="lockscreen_none_target">Καμία</string>
+ <string name="navbar_dialog_title">Επιλέξτε ενέργεια για εκχώρηση</string>
+ <string name="navbar_home_button">Πλήκτρο αρχικής οθόνης</string>
+ <string name="navbar_recent_button">Πλήκτρο πρόσφατων εφαρμογών</string>
+ <string name="navbar_search_button">Πλήκτρο αναζήτησης</string>
+ <string name="navbar_back_button">Πλήκτρο πίσω</string>
+ <string name="navbar_empty_button">Άδειο πλήκτρο</string>
+ <string name="navbar_menu_conditional_button">Πλήκτρο μενού (αυτόματη απόκρυψη)</string>
+ <string name="navbar_menu_always_button">Πλήκτρο μενού (εμφάνιση πάντα)</string>
+ <string name="navbar_menu_big_button">Πλήκτρο μενού</string>
+ <string name="accessibility_dpad_left">Κέρσορας αριστερά</string>
+ <string name="accessibility_dpad_right">Κέρσορας δεξιά</string>
+ <string name="advanced_dev_option_wipe_app">Εκκαθάριση δεδομένων</string>
+ <string name="advanced_dev_option_force_stop">Αναγκαστική διακοπή</string>
+ <string name="advanced_dev_option_uninstall">Απεγκατάσταση</string>
+ <string name="accessibility_notification_brightness">Φωτεινότητα LED</string>
+ <string name="accessibility_quick_settings_profiles_off">Ανενεργά προφίλ.</string>
+ <string name="accessibility_quick_settings_profiles">Προφίλ: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Τα προφίλ απενεργοποιήθηκαν.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Το προφίλ άλλαξε σε <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Προετοιμασία\u2026</string>
+ <string name="led_notification_title">Ρυθμίσεις LED</string>
+ <string name="led_notification_text">Το LED ενεργοποιήθηκε από τις ρυθμίσεις</string>
+ <string name="qs_tile_edit_header_instruction">Πιέστε παρατεταμένα στα πλακίδια για αναδιάταξη</string>
+ <string name="quick_settings_edit_label">Επεξεργασία πλακιδίων</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Δεν είναι δυνατή η διαγραφή του πλακιδίου επεξεργασίας</string>
+ <string name="qs_tiles_reset_confirmation">Επαναφορά των πλακιδίων γρήγορων ρυθμίσεων στις προεπιλογές;</string>
+ <string name="quick_settings_tile_reset_to_default">Επαναφορά στην προεπιλεγμένη διάταξη</string>
+ <string name="quick_settings_title_header">Επικεφαλίδα</string>
+ <string name="quick_settings_title_tiles">Πλακίδια</string>
+ <string name="quick_settings_title_show_weather">Εμφάνιση καιρού</string>
+ <string name="quick_settings_title_show_brightness_slider">Εμφάνιση ρυθμιστικού φωτεινότητας</string>
+ <string name="quick_settings_title_enlarge_first_row">Μεγέθυνση της πρώτης γραμμής</string>
+ <string name="screen_pinning_description_no_navbar">Αυτό κλειδώνει την συγκεκριμένη οθόνη μέχρι να την ξεκαρφιτσώσετε. Αγγίξτε και κρατήστε πατημένο το πλήκτρο Πίσω για ξεκαρφίτσωμα.</string>
+ <string name="quick_settings_custom_tile_detail_title">Προσαρμοσμένο πλακίδιο</string>
+ <string name="quick_settings_remove">Αφαίρεση πλακιδίου</string>
+ <string name="quick_settings_network_adb_label">ADB μέσω δικτύου</string>
+ <string name="quick_settings_compass_label">Πυξίδα</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Προφίλ συστήματος</string>
+ <string name="quick_settings_profiles_off">Προφίλ απενεργοποιημένα</string>
+ <string name="quick_settings_heads_up_label">Αναδυόμενες ειδοποιήσεις</string>
+ <string name="quick_settings_battery_saver_label">Εξοικονόμηση μπαταρίας</string>
+ <string name="quick_settings_caffeine_label">Καφεΐνη</string>
+ <string name="accessibility_quick_settings_sync_off">Ανενεργός συγχρονισμός.</string>
+ <string name="accessibility_quick_settings_sync_on">Ενεργός συγχρονισμός.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Ο συγχρονισμός απενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Ο συγχρονισμός ενεργοποιήθηκε.</string>
+ <string name="quick_settings_sync_label">Συγχρονισμός</string>
+ <string name="quick_settings_volume_panel_label">Πάνελ έντασης</string>
+ <string name="quick_settings_usb_tether_label">Πρόσδεση USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Χρονικό όριο οθόνης</string>
+ <string name="quick_settings_lockscreen_label">Οθόνη κλειδώματος</string>
+ <string name="quick_settings_ambient_display_label">Οθόνη ambient</string>
+ <string name="quick_settings_lockscreen_label_enforced">Επιβαλλόμενη οθόνη κλειδώματος</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Απενεργοποιήθηκε από προφίλ</string>
+ <string name="accessibility_quick_settings_screen_timeout">Χρονικό όριο οθόνης: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Το χρονικό όριο οθόνης άλλαξε σε: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Λειτουργία μπαταρίας</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Λειτουργία μπαταρίας: εξοικονόμηση ενέργειας.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Λειτουργία μπαταρίας: ισορροπημένο.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Λειτουργία μπαταρίας: επιδόσεις.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Λειτουργία μπαταρίας: αποδοτικό.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Λειτουργία μπαταρίας: γρήγορο.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Η λειτουργία μπαταρίας άλλαξε σε εξοικονόμηση ενέργειας.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Η λειτουργία μπαταρίας άλλαξε σε ισορροπημένο.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Η λειτουργία μπαταρίας άλλαξε σε επιδόσεις.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Η λειτουργία μπαταρίας άλλαξε σε αποδοτικό.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Η λειτουργία μπαταρίας άλλαξε σε γρήγορο.</string>
+ <string name="quick_settings_performance_profile_detail_title">Λειτουργία μπαταρίας</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Ανενεργή οθόνη κλειδώματος.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Ενεργή οθόνη κλειδώματος.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Η οθόνη κλειδώματος απενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Η οθόνη κλειδώματος ενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ανενεργή οθόνη ambient.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ενεργή οθόνη ambient.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Η οθόνη ambient απενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Η οθόνη ambient ενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Ανενεργές αναδυόμενες ειδοποιήσεις.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Ενεργές αναδυόμενες ειδοποιήσεις.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Οι αναδυόμενες ειδοποιήσεις απενεργοποιήθηκαν.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Οι αναδυόμενες ειδοποιήσεις ενεργοποιήθηκαν.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Καφεΐνη ανενεργή.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Καφεΐνη ενεργή.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Ανενεργή εξοικονόμηση μπαταρίας.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Ενεργή εξοικονόμηση μπαταρίας.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Η εξοικονόμηση μπαταρίας απενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Η εξοικονόμηση μπαταρίας ενεργοποιήθηκε.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Δυναμικό πλακίδιο</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Επόμενο ξυπνητήρι</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Επιλογέας μεθόδου εισόδου</string>
+ <string name="dynamic_qs_tile_su_label">Πρόσβαση root</string>
+ <string name="accessibility_quick_settings_live_display_off">Ανενεργό LiveDisplay.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: αυτόματη λειτουργία.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: λειτουργία ημέρας.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: λειτουργία νύχτας.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: λειτουργία εξωτερικού χώρου.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">Το LiveDisplay απενεργοποιήθηκε.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">Το LiveDisplay άλλαξε σε αυτόματη λειτουργία.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">Το LiveDisplay άλλαξε σε λειτουργία ημέρας.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">Το LiveDisplay άλλαξε σε λειτουργία νύχτας.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">Το LiveDisplay άλλαξε σε λειτουργία εξωτερικού χώρου.</string>
+ <string name="quick_settings_title_advanced_location">Προηγμένη ρύθμιση τοποθεσίας</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Αναφορά τοποθεσίας: λειτουργία εξοικονόμησης μπαταρίας.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Αναφορά τοποθεσίας: λειτουργία μόνο αισθητήρων.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Αναφορά τοποθεσίας: λειτουργία υψηλής ακρίβειας.</string>
+ <string name="quick_settings_location_detail_title">Λειτουργία τοποθεσίας</string>
+ <string name="quick_settings_location_battery_saving_label">Εξοικονόμηση μπαταρίας</string>
+ <string name="quick_settings_location_gps_only_label">Μόνο συσκευή</string>
+ <string name="quick_settings_location_high_accuracy_label">Υψηλή ακρίβεια</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Η αναφορά τοποθεσίας άλλαξε σε λειτουργία εξοικονόμησης μπαταρίας.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Η αναφορά τοποθεσίας άλλαξε σε λειτουργία μόνο αισθητήρων.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Η αναφορά τοποθεσίας άλλαξε σε λειτουργία υψηλής ακρίβειας.</string>
+ <string name="quick_settings_tiles_category_system">Πλακίδια συστήματος</string>
+ <string name="quick_settings_tiles_add_tiles">Προσθήκη πλακιδίου</string>
+ <string name="hotspot_apm_message">Δεν είναι δυνατή η σύνδεση με δίκτυα κινητής τηλεφωνίας ενώ είναι ενεργοποιημένη η λειτουργία πτήσης. Απενεργοποιήστε τη λειτουργία πτήσης και προσπαθήστε ξανά.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Ο φακός είναι ενεργοποιημένος</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Πιέστε για απενεργοποίηση</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/cm_arrays.xml b/packages/SystemUI/res/values-en-rAU/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rAU/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/cm_strings.xml b/packages/SystemUI/res/values-en-rAU/cm_strings.xml
new file mode 100644
index 0000000..bac2e03
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rAU/cm_strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Swipe right for %1$s</string>
+ <string name="right_shortcut_hint">Swipe left for %1$s</string>
+ <string name="select_application">Select application</string>
+ <string name="lockscreen_choose_action_title">Choose action</string>
+ <string name="lockscreen_none_target">None</string>
+ <string name="navbar_dialog_title">Choose action to assign</string>
+ <string name="navbar_home_button">Home button</string>
+ <string name="navbar_recent_button">Recent button</string>
+ <string name="navbar_search_button">Search button</string>
+ <string name="navbar_back_button">Back button</string>
+ <string name="navbar_empty_button">Empty button</string>
+ <string name="navbar_menu_conditional_button">Menu (autoHide) button</string>
+ <string name="navbar_menu_always_button">Menu (alwaysShow) button</string>
+ <string name="navbar_menu_big_button">Menu button</string>
+ <string name="accessibility_dpad_left">Cursor left</string>
+ <string name="accessibility_dpad_right">Cursor right</string>
+ <string name="advanced_dev_option_wipe_app">Wipe app data</string>
+ <string name="advanced_dev_option_force_stop">Force stop</string>
+ <string name="advanced_dev_option_uninstall">Uninstall</string>
+ <string name="quick_settings_compass_init">Initialising\u2026</string>
+ <string name="quick_settings_network_adb_label">ADB over network</string>
+ <string name="quick_settings_compass_label">Compass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">System profiles</string>
+ <string name="quick_settings_profiles_off">Profiles disabled</string>
+ <string name="quick_settings_screen_timeout_detail_title">Screen timeout</string>
+ <string name="quick_settings_lockscreen_label">Lock screen</string>
+ <string name="quick_settings_lockscreen_label_enforced">Lock screen enforced</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Location reporting: Battery-saving mode.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Location reporting: Sensors-only mode.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Location reporting: High-accuracy mode.</string>
+ <string name="quick_settings_location_detail_title">Location mode</string>
+ <string name="quick_settings_location_battery_saving_label">Battery-saving</string>
+ <string name="quick_settings_location_gps_only_label">Device only</string>
+ <string name="quick_settings_location_high_accuracy_label">High accuracy</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/cm_arrays.xml b/packages/SystemUI/res/values-en-rIN/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rIN/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/cm_strings.xml b/packages/SystemUI/res/values-en-rIN/cm_strings.xml
new file mode 100644
index 0000000..1e364db
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rIN/cm_strings.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Swipe right for %1$s</string>
+ <string name="right_shortcut_hint">Swipe left for %1$s</string>
+ <string name="lockscreen_message">Tap an icon on the left or right to reassign a lock screen shortcut.</string>
+ <string name="lockscreen_default_target">Default</string>
+ <string name="select_application">Select application</string>
+ <string name="lockscreen_choose_action_title">Choose action</string>
+ <string name="lockscreen_none_target">None</string>
+ <string name="navbar_dialog_title">Choose action to assign</string>
+ <string name="navbar_home_button">Home button</string>
+ <string name="navbar_recent_button">Recent button</string>
+ <string name="navbar_search_button">Search button</string>
+ <string name="navbar_back_button">Back button</string>
+ <string name="navbar_empty_button">Empty button</string>
+ <string name="navbar_menu_conditional_button">Menu (autoHide) button</string>
+ <string name="navbar_menu_always_button">Menu (alwaysShow) button</string>
+ <string name="navbar_menu_big_button">Menu button</string>
+ <string name="accessibility_dpad_left">Cursor left</string>
+ <string name="accessibility_dpad_right">Cursor right</string>
+ <string name="advanced_dev_option_wipe_app">Wipe app data</string>
+ <string name="advanced_dev_option_force_stop">Force stop</string>
+ <string name="advanced_dev_option_uninstall">Uninstall</string>
+ <string name="accessibility_notification_brightness">Light brightness</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiles off.</string>
+ <string name="accessibility_quick_settings_profiles">Profile: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiles turned off.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profile changed to <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Initializing\u2026</string>
+ <string name="led_notification_title">Light settings</string>
+ <string name="led_notification_text">LED light enabled by settings</string>
+ <string name="qs_tile_edit_header_instruction">Press and hold tiles to rearrange</string>
+ <string name="quick_settings_edit_label">Edit tiles</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Cannot delete the Edit tile</string>
+ <string name="qs_tiles_reset_confirmation">Reset quick settings tiles to default configuration?</string>
+ <string name="quick_settings_tile_reset_to_default">Reset to default layout</string>
+ <string name="quick_settings_title_header">Header</string>
+ <string name="quick_settings_title_tiles">Tiles</string>
+ <string name="quick_settings_title_show_weather">Show weather</string>
+ <string name="quick_settings_title_enlarge_first_row">Enlarge first row</string>
+ <string name="screen_pinning_description_no_navbar">This keeps it in view until you unpin. Touch and hold the Back button to unpin.</string>
+ <string name="quick_settings_custom_tile_detail_title">Custom tile</string>
+ <string name="quick_settings_remove">Remove tile</string>
+ <string name="quick_settings_network_adb_label">ADB over network</string>
+ <string name="quick_settings_compass_label">Compass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">System profiles</string>
+ <string name="quick_settings_profiles_off">Profiles disabled</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Battery saver</string>
+ <string name="accessibility_quick_settings_sync_off">Sync off.</string>
+ <string name="accessibility_quick_settings_sync_on">Sync on.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sync turned off.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sync turned on.</string>
+ <string name="quick_settings_sync_label">Sync</string>
+ <string name="quick_settings_volume_panel_label">Volume panel</string>
+ <string name="quick_settings_usb_tether_label">USB tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Screen timeout</string>
+ <string name="quick_settings_lockscreen_label">Lock screen</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Lock screen enforced</string>
+ <string name="accessibility_quick_settings_screen_timeout">Screen timeout: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Screen timeout changed to <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Battery mode</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Battery mode: power save mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Battery mode: balanced mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Battery mode: performance mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Battery mode: efficiency mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Battery mode: quick mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Battery mode changed to power save mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Battery mode changed to balanced mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Battery mode changed to performance mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Battery mode changed to efficiency mode.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Battery mode changed to quick mode.</string>
+ <string name="quick_settings_performance_profile_detail_title">Battery mode</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Lock screen off.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Lock screen on.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Lock screen turned off.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Lock screen turned on.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display off.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display on.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient display turned off.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display turned on.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up off.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up on.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up turned off.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up turned on.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Battery saver off.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Battery saver on.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Battery saver turned off.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Battery saver turned on.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamic tile</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Next alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME selector</string>
+ <string name="dynamic_qs_tile_su_label">Root access</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay off.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: auto mode.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: day mode.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: night mode.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: outdoor mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay turned off.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay changed to auto mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay changed to day mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay changed to night mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay changed to outdoor mode.</string>
+ <string name="quick_settings_title_advanced_location">Tri-state location</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Location reporting: battery saving mode.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Location reporting: sensors only mode.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Location reporting: high accuracy mode.</string>
+ <string name="quick_settings_location_detail_title">Location mode</string>
+ <string name="quick_settings_location_battery_saving_label">Battery saving</string>
+ <string name="quick_settings_location_gps_only_label">Device only</string>
+ <string name="quick_settings_location_high_accuracy_label">High accuracy</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Location reporting changed to battery saving mode.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Location reporting changed to sensors only mode.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Location reporting changed to high accuracy mode.</string>
+ <string name="quick_settings_tiles_category_system">System tiles</string>
+ <string name="quick_settings_tiles_add_tiles">Add a tile</string>
+</resources>
diff --git a/packages/SystemUI/res/values-eo/cm_arrays.xml b/packages/SystemUI/res/values-eo/cm_arrays.xml
new file mode 100644
index 0000000..8084f6b
--- /dev/null
+++ b/packages/SystemUI/res/values-eo/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>N-Or</item>
+ <item>Or</item>
+ <item>S-Or</item>
+ <item>S</item>
+ <item>S-Ok</item>
+ <item>Ok</item>
+ <item>N-Ok</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-eo/cm_strings.xml b/packages/SystemUI/res/values-eo/cm_strings.xml
new file mode 100644
index 0000000..e903d2b
--- /dev/null
+++ b/packages/SystemUI/res/values-eo/cm_strings.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Movi dekstren por %1$s</string>
+ <string name="right_shortcut_hint">Movi maldekstren por %1$s</string>
+ <string name="select_application">Elekti aplikaĵon</string>
+ <string name="lockscreen_choose_action_title">Elekti agon</string>
+ <string name="lockscreen_none_target">Nenio</string>
+ <string name="navbar_dialog_title">Elekti agon por atribui</string>
+ <string name="navbar_home_button">Hejmbutono</string>
+ <string name="navbar_recent_button">Lasttempe-butono</string>
+ <string name="navbar_search_button">Serĉ-butono</string>
+ <string name="navbar_back_button">Reen-butono</string>
+ <string name="navbar_empty_button">Malplena butono</string>
+ <string name="navbar_menu_conditional_button">Menubutono (aŭtomate kaŝita)</string>
+ <string name="navbar_menu_always_button">Menubutono (ĉiam videbla)</string>
+ <string name="navbar_menu_big_button">Menubutono</string>
+ <string name="accessibility_dpad_left">Maldekstra kursoro</string>
+ <string name="accessibility_dpad_right">Dekstra kursoro</string>
+ <string name="advanced_dev_option_wipe_app">Forigi ĉiujn datumojn</string>
+ <string name="advanced_dev_option_force_stop">Devigi ĉesadon</string>
+ <string name="advanced_dev_option_uninstall">Malinstali</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiloj malaktivaj.</string>
+ <string name="accessibility_quick_settings_profiles">Profilo: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiloj malŝaltitaj.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profilo ŝanĝita al <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Preparado\u2026</string>
+ <string name="screen_pinning_description_no_navbar">Tio lasos ĝin videbla ĝin kiam vi malfiksos ĝin. Tuŝetu kaj tenu la reenbutonon por malfiksi.</string>
+ <string name="quick_settings_custom_tile_detail_title">Tajlorita kahelo</string>
+ <string name="quick_settings_remove">Forigi kahelon</string>
+ <string name="quick_settings_network_adb_label">reta ADB</string>
+ <string name="quick_settings_compass_label">Kompaso</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Sistemaj profiloj</string>
+ <string name="quick_settings_profiles_off">Profiloj malŝaltitaj</string>
+ <string name="quick_settings_heads_up_label">Atentigoj</string>
+ <string name="accessibility_quick_settings_sync_off">Sinkronigado malaktiva.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinkronigado aktiva.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sinkronigado malŝaltita.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sinkronigado ŝaltita.</string>
+ <string name="quick_settings_sync_label">Sinkronigo</string>
+ <string name="quick_settings_usb_tether_label">USB modemo</string>
+ <string name="quick_settings_screen_timeout_detail_title">Ekrana tempolimo</string>
+ <string name="quick_settings_lockscreen_label">Ŝlosa ekrano</string>
+ <string name="quick_settings_ambient_display_label">Ĉirkaŭaĵa afiŝado</string>
+ <string name="quick_settings_lockscreen_label_enforced">Ŝlosa ekrano devigita</string>
+ <string name="accessibility_quick_settings_screen_timeout">Ekrana tempolimo: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Ekrana tempolimo ŝanĝita al <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Bateria reĝimo: reĝimo de energia ŝparado.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Bateria reĝimo: meza reĝimo.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Bateria reĝimo: reĝimo de rendimento.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Bateria reĝimo ŝanĝita al reĝimo de energia ŝparado.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Bateria reĝimo ŝanĝita al meza reĝimo.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Bateria reĝimo ŝanĝita al reĝimo de rendimento.</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Ŝlosa ekrano malaktiva.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Ŝlosa ekrano aktiva.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Ŝlosa ekrano malŝaltita.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Ŝlosa ekrano ŝaltita.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ĉirkaŭaĵa afiŝado malaktiva.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ĉirkaŭaĵa afiŝado aktiva.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ĉirkaŭaĵa afiŝado malŝaltita.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ĉirkaŭaĵa afiŝado ŝaltita.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Atentigoj malaktivaj.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Atentigoj aktivaj.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Atentigoj malŝaltitaj.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Atentigoj ŝaltitaj.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamika kahelo</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Venonta alarmo</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME elektilo</string>
+ <string name="dynamic_qs_tile_su_label">Radikuzanta atingo</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay malaktiva.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: aŭtomata reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: taga reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nokta reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: ekstera reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay malŝaltita.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay ŝanĝita al aŭtomata reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay ŝanĝita al taga reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay ŝanĝita al nokta reĝimo.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay ŝanĝita al ekstera reĝimo.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Lokalizado: reĝimo de bateria ŝparado.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Lokalizado: reĝimo de nur aparato.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Lokalizado: reĝimo de alta precizeco.</string>
+ <string name="quick_settings_location_detail_title">Moduso por loko</string>
+ <string name="quick_settings_location_battery_saving_label">Ŝparado de baterio</string>
+ <string name="quick_settings_location_gps_only_label">Nur aparato</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precizeco</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Lokalizado ŝanĝita al ŝparado de baterio.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Lokalizado ŝanĝita al reĝimo de nur aparato.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Lokalizado ŝanĝita al reĝimo de alta precizeco.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es/cm_arrays.xml b/packages/SystemUI/res/values-es/cm_arrays.xml
new file mode 100644
index 0000000..cb6fbec
--- /dev/null
+++ b/packages/SystemUI/res/values-es/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-es/cm_strings.xml b/packages/SystemUI/res/values-es/cm_strings.xml
new file mode 100644
index 0000000..92425c1
--- /dev/null
+++ b/packages/SystemUI/res/values-es/cm_strings.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Desliza a la derecha para %1$s</string>
+ <string name="right_shortcut_hint">Desliza a la izquierda para %1$s</string>
+ <string name="lockscreen_message">Toca un icono a la izquierda o derecha para volver a asignar un atajo a la pantalla de bloqueo.</string>
+ <string name="lockscreen_default_target">Por defecto</string>
+ <string name="select_application">Selecciona una aplicación</string>
+ <string name="lockscreen_choose_action_title">Elegir acción</string>
+ <string name="lockscreen_none_target">Ninguno</string>
+ <string name="navbar_dialog_title">Elegir acción a asignar</string>
+ <string name="navbar_home_button">Botón Inicio</string>
+ <string name="navbar_recent_button">Botón reciente</string>
+ <string name="navbar_search_button">Botón de búsqueda</string>
+ <string name="navbar_back_button">Botón Atrás</string>
+ <string name="navbar_empty_button">Botón vacío</string>
+ <string name="navbar_menu_conditional_button">Botón de menú (auto-ocultar)</string>
+ <string name="navbar_menu_always_button">Botón de menú (siempre visible)</string>
+ <string name="navbar_menu_big_button">Botón de menú</string>
+ <string name="accessibility_dpad_left">Cursor izquierdo</string>
+ <string name="accessibility_dpad_right">Cursor derecho</string>
+ <string name="advanced_dev_option_wipe_app">Borrar datos de la aplicación</string>
+ <string name="advanced_dev_option_force_stop">Forzar detención</string>
+ <string name="advanced_dev_option_uninstall">Desinstalar</string>
+ <string name="accessibility_notification_brightness">Brillo ligero</string>
+ <string name="accessibility_quick_settings_profiles_off">Perfiles desactivados.</string>
+ <string name="accessibility_quick_settings_profiles">Perfil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Perfiles desactivado.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Perfil cambiado a <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicializando\u2026</string>
+ <string name="led_notification_title">Ajustes de luz</string>
+ <string name="led_notification_text">Luz LED activada por ajustes</string>
+ <string name="qs_tile_edit_header_instruction">Toca y deja presionados los controles para reorganizarlos</string>
+ <string name="quick_settings_edit_label">Editar controles</string>
+ <string name="quick_settings_cannot_delete_edit_tile">No se puede eliminar el control de \"Editar\"</string>
+ <string name="qs_tiles_reset_confirmation">¿Restaurar los controles de ajustes rápidos a su configuración predeterminada?</string>
+ <string name="quick_settings_tile_reset_to_default">Restaurar disposición por defecto</string>
+ <string name="quick_settings_title_header">Encabezado</string>
+ <string name="quick_settings_title_tiles">Controles</string>
+ <string name="quick_settings_title_show_weather">Mostrar el clima</string>
+ <string name="quick_settings_title_enlarge_first_row">Ampliar la primera fila</string>
+ <string name="screen_pinning_description_no_navbar">Esto fija la pantalla en esta vista hasta que es liberada. Mantén pulsado el botón Atrás para liberarla.</string>
+ <string name="quick_settings_custom_tile_detail_title">Control personalizado</string>
+ <string name="quick_settings_remove">Eliminar control</string>
+ <string name="quick_settings_network_adb_label">ADB sobre red</string>
+ <string name="quick_settings_compass_label">Brújula</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Perfiles del sistema</string>
+ <string name="quick_settings_profiles_off">Perfiles desactivados</string>
+ <string name="quick_settings_heads_up_label">Notificaciones emergentes</string>
+ <string name="quick_settings_battery_saver_label">Modo de ahorro de batería</string>
+ <string name="accessibility_quick_settings_sync_off">Sincronización desactivada.</string>
+ <string name="accessibility_quick_settings_sync_on">Sincronización activada.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sincronización desactivada.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sincronización activada.</string>
+ <string name="quick_settings_sync_label">Sincronizar</string>
+ <string name="quick_settings_volume_panel_label">Panel de volumen</string>
+ <string name="quick_settings_usb_tether_label">Anclaje de red por USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Tiempo de espera de pantalla</string>
+ <string name="quick_settings_lockscreen_label">Pantalla de bloqueo</string>
+ <string name="quick_settings_ambient_display_label">Pantalla ambiente</string>
+ <string name="quick_settings_lockscreen_label_enforced">Pantalla de bloqueo forzada</string>
+ <string name="accessibility_quick_settings_screen_timeout">Tiempo de espera de pantalla: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Tiempo de espera de pantalla cambiado a <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Modo de la batería</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Modo de batería: ahorro de energía.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Modo de batería: equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Modo de batería: rendimiento.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Modo de la batería: eficiente.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Modo de la batería: rápido.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Modo de batería cambiado a ahorro de energía.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Modo de batería cambiado a equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Modo de batería cambiado a rendimiento.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Modo de la batería cambiado a eficiente.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Modo de la batería cambiado a rápido.</string>
+ <string name="quick_settings_performance_profile_detail_title">Modo de la batería</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Bloqueo de pantalla desactivado.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Bloqueo de pantalla activado.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Bloqueo de pantalla desactivado.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Bloqueo de pantalla activado.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Pantalla ambiente desactivada.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Pantalla ambiente activada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Pantalla ambiente desactivada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Pantalla ambiente activada.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Desactivar notificaciones emergentes.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Activar notificaciones emergentes.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Notificaciones emergentes desactivadas.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Notificaciones emergentes activadas.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Apagar modo de ahorro de batería.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Encender modo de ahorro de batería.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Modo de ahorro de batería apagado.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Modo de ahorro de batería encendido.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Control dinámico</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Próxima alarma</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Selector IME</string>
+ <string name="dynamic_qs_tile_su_label">Acceso administrativo</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay desactivado.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modo diurno.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modo nocturno.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modo aire libre.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay desactivado.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay cambió a modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay ha cambiado a modo diurno.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay ha cambiado a modo nocturno.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay cambiado a modo aire libre.</string>
+ <string name="quick_settings_title_advanced_location">Ubicación por triangulación</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Informes de ubicación: modo de ahorro de batería.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Informes de ubicación: modo de solo sensores.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Informes de ubicación: modo de alta precisión.</string>
+ <string name="quick_settings_location_detail_title">Modo de ubicación</string>
+ <string name="quick_settings_location_battery_saving_label">Ahorro de batería</string>
+ <string name="quick_settings_location_gps_only_label">Solo en dispositivo</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precisión</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Informes de ubicación cambiados a modo de ahorro de batería.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Informes de ubicación cambiados a modo solo dispositivo.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Informes de ubicación cambiados a modo de gran precisión.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/cm_arrays.xml b/packages/SystemUI/res/values-et-rEE/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-et-rEE/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/cm_strings.xml b/packages/SystemUI/res/values-et-rEE/cm_strings.xml
new file mode 100644
index 0000000..4d9eafa
--- /dev/null
+++ b/packages/SystemUI/res/values-et-rEE/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Libista paremale et käivitada %1$s</string>
+ <string name="right_shortcut_hint">Libista vasakule et käivitada %1$s</string>
+ <string name="select_application">Valige rakendus</string>
+ <string name="lockscreen_choose_action_title">Valige toiming</string>
+ <string name="lockscreen_none_target">Puudub</string>
+ <string name="navbar_dialog_title">Vali toiming mida lisada</string>
+ <string name="navbar_home_button">Kodu nupp</string>
+ <string name="navbar_recent_button">Hiljutiste nupp</string>
+ <string name="navbar_search_button">Otsimise nupp</string>
+ <string name="navbar_back_button">Tagasi nupp</string>
+ <string name="navbar_empty_button">Tühi nupp</string>
+ <string name="navbar_menu_conditional_button">Menüü (isePeida) nupp</string>
+ <string name="navbar_menu_always_button">Menüü (alatiNäita) nupp</string>
+ <string name="navbar_menu_big_button">Menüü nupp</string>
+ <string name="accessibility_dpad_left">Kursor vasakule</string>
+ <string name="accessibility_dpad_right">Kursor paremale</string>
+ <string name="advanced_dev_option_wipe_app">Kustuta rakenduse andmed</string>
+ <string name="advanced_dev_option_force_stop">Jõuga peatamine</string>
+ <string name="advanced_dev_option_uninstall">Eemalda</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiilid väljas.</string>
+ <string name="accessibility_quick_settings_profiles">Profiil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiilid välja lülitatud.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profiil muudetud: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Määratlen\u2026</string>
+ <string name="screen_pinning_description_no_navbar">See hoiab vaate kuni vabastamiseni. Vajuta ja hoia tagasi nuppu vabastamiseks.</string>
+ <string name="quick_settings_custom_tile_detail_title">Kohandatud plaat</string>
+ <string name="quick_settings_remove">Eemalda plaat</string>
+ <string name="quick_settings_network_adb_label">ADB üle võrgu</string>
+ <string name="quick_settings_compass_label">Kompass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Süsteemi profiilid</string>
+ <string name="quick_settings_profiles_off">Profiilid välja lülitatud</string>
+ <string name="quick_settings_heads_up_label">Etteteavitus</string>
+ <string name="quick_settings_battery_saver_label">Akusäästja</string>
+ <string name="accessibility_quick_settings_sync_off">Sünk väljas.</string>
+ <string name="accessibility_quick_settings_sync_on">Sünk sees.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sünk välja lülitatud.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sünk sisse lülitatud.</string>
+ <string name="quick_settings_sync_label">Sünk</string>
+ <string name="quick_settings_volume_panel_label">Helipaneel</string>
+ <string name="quick_settings_usb_tether_label">USB lõastamine</string>
+ <string name="quick_settings_screen_timeout_detail_title">Ekraani viide</string>
+ <string name="quick_settings_lockscreen_label">Lukustusekraan</string>
+ <string name="quick_settings_ambient_display_label">Ambient kuva</string>
+ <string name="quick_settings_lockscreen_label_enforced">Lukustusekraan sunnitud</string>
+ <string name="accessibility_quick_settings_screen_timeout">Ekraani ajalõpp: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Ekraani ajalõpp muudetud <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Aku režiim</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Aku režiim: energiasäästmise režiim.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Aku režiim: tasakaalustatud režiim.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Aku režiim: jõudlus režiim.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Aku režiim: energiatõhususe režiimis.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Aku režiim: kiirrežiim.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Aku režiim muudeti energiasäästu režiimiks.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Aku režiim muudeti tasakaalustatud režiimiks.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Aku režiim muudeti jõudluse režiimiks.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Aku režiimi muudeti tõhususe režiimiks.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Aku režiimi muudeti kiirrežiimiks.</string>
+ <string name="quick_settings_performance_profile_detail_title">Aku režiim</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Lukustusekraan väljas.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Lukustusekraan sees.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Lukustusekraan välja lülitatud.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Lukustusekraan sisse lülitatud.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient kuva väljas.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient kuva sees.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient kuva väljalülitatud.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient kuva sisselülitatud.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Etteteavitus väljas.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Etteteavitus sees.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Etteteavitus on väljalülitatud.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Etteteavitus on sisselülitatud.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Akusäästja väljas.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Akusäästja sees.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Akusäästja on välja lülitatud.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Akusäästja on sisse lülitatud.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dünaamiline plaat</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Järgmine alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME valija</string>
+ <string name="dynamic_qs_tile_su_label">Root ligipääs</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay väljas.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automaatrežiim.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: päev-režiim.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: Öörežiim.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: õues režiim.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay välja lülitatud.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay muudetud automaatrežiimi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay muudetud päev-režiimi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay muudetud Öörežiimi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay muudetud õues režiimi.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Asukoha teatamine: aku säästmise režiim.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Asukoha teatamine: ainult andurite režiim.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Asukoha teatamine: kõrge täpsusega režiim.</string>
+ <string name="quick_settings_location_detail_title">Asukoha režiim</string>
+ <string name="quick_settings_location_battery_saving_label">Akut säästev</string>
+ <string name="quick_settings_location_gps_only_label">Ainult seade</string>
+ <string name="quick_settings_location_high_accuracy_label">Kõrge täpsusega</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Asukoha teavitus muudetud aku säästmise režiimi.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Asukoha teavitus muudetud vaid sensorite režiimi.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Asukoha teavitus muudetud kõrge täpsusega režiimi.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/cm_arrays.xml b/packages/SystemUI/res/values-eu-rES/cm_arrays.xml
new file mode 100644
index 0000000..969a4d1
--- /dev/null
+++ b/packages/SystemUI/res/values-eu-rES/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>I</item>
+ <item>IE</item>
+ <item>E</item>
+ <item>HE</item>
+ <item>H</item>
+ <item>HM</item>
+ <item>M</item>
+ <item>IM</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/cm_strings.xml b/packages/SystemUI/res/values-eu-rES/cm_strings.xml
new file mode 100644
index 0000000..ac12c88
--- /dev/null
+++ b/packages/SystemUI/res/values-eu-rES/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Pasatu hatza eskumara: %1$s</string>
+ <string name="right_shortcut_hint">Pasatu hatza ezkerrera: %1$s</string>
+ <string name="lockscreen_message">Sakatu ezker edo eskuineko ikono bat blokeo-pantailako lasterbide bat aldatzeko.</string>
+ <string name="lockscreen_default_target">Lehenetsia</string>
+ <string name="select_application">Hautatu aplikazioa</string>
+ <string name="lockscreen_choose_action_title">Aukeratu ekintza</string>
+ <string name="lockscreen_none_target">Bat ere ez</string>
+ <string name="navbar_dialog_title">Hautatu esleituko zaion ekintza</string>
+ <string name="navbar_home_button">Hasiera botoia</string>
+ <string name="navbar_recent_button">Azkenak botoia</string>
+ <string name="navbar_search_button">Bilaketa botoia</string>
+ <string name="navbar_back_button">Atzera botoia</string>
+ <string name="navbar_empty_button">Botoi hutsa</string>
+ <string name="navbar_menu_conditional_button">Menu botoia (automatikoki ezkutatu)</string>
+ <string name="navbar_menu_always_button">Menu botoia (beti erakutsi)</string>
+ <string name="navbar_menu_big_button">Menu botoia</string>
+ <string name="accessibility_dpad_left">Kurtsorea ezkerrean</string>
+ <string name="accessibility_dpad_right">Kurtsorea eskuman</string>
+ <string name="advanced_dev_option_wipe_app">Ezabatu aplikazioaren datuak</string>
+ <string name="advanced_dev_option_force_stop">Gelditzera behartu</string>
+ <string name="advanced_dev_option_uninstall">Desinstalatu</string>
+ <string name="accessibility_notification_brightness">Argiaren distira</string>
+ <string name="accessibility_quick_settings_profiles_off">Profilak ezgaituta.</string>
+ <string name="accessibility_quick_settings_profiles">Profila: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profilak ezgaituta.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil honetara aldatu da: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Hasieratzen\u2026</string>
+ <string name="led_notification_title">Argi ezarpenak</string>
+ <string name="led_notification_text">LED argia ezarpenetan gaituta</string>
+ <string name="qs_tile_edit_header_instruction">Sakatu eta mantendu lauzak berrantolatzeko</string>
+ <string name="quick_settings_edit_label">Editatu lauzak</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Ezin da Editatu lauza ezabatu</string>
+ <string name="qs_tiles_reset_confirmation">Berrezarri ezarpen azkarretako lauzak lehenetsitako konfiguraziora?</string>
+ <string name="quick_settings_tile_reset_to_default">Itzuli lehenetsitako diseinura</string>
+ <string name="quick_settings_title_header">Goiburua</string>
+ <string name="quick_settings_title_tiles">Lauzak</string>
+ <string name="quick_settings_title_show_weather">Bistaratu eguraldia</string>
+ <string name="quick_settings_title_show_brightness_slider">Bistaratu distira graduatzailea</string>
+ <string name="quick_settings_title_enlarge_first_row">Handitu lehen lerroa</string>
+ <string name="screen_pinning_description_no_navbar">Honek bistan mantenduko du desiltzatzen duzun arte. Sakatu eta mantendu atzera botoia desiltzatzeko.</string>
+ <string name="quick_settings_custom_tile_detail_title">Lauza pertsonalizatua</string>
+ <string name="quick_settings_remove">Ezabatu lauza</string>
+ <string name="quick_settings_network_adb_label">Sare gaineko ADB</string>
+ <string name="quick_settings_compass_label">Iparrorratza</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Sistema profilak</string>
+ <string name="quick_settings_profiles_off">Profilak ezgaituta</string>
+ <string name="quick_settings_heads_up_label">Jakinarazpen flotatzaileak</string>
+ <string name="quick_settings_battery_saver_label">Bateria aurrezlea</string>
+ <string name="quick_settings_caffeine_label">Kafeina</string>
+ <string name="accessibility_quick_settings_sync_off">Sinkronizazioa ezgaituta.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinkronizazioa gaituta.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sinkronizazioa ezgaituta.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sinkronizazioa gaituta.</string>
+ <string name="quick_settings_sync_label">Sinkronizazioa</string>
+ <string name="quick_settings_volume_panel_label">Bolumen panela</string>
+ <string name="quick_settings_usb_tether_label">USB tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Pantailaren denbora-muga</string>
+ <string name="quick_settings_lockscreen_label">Blokeo-pantaila</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Blokeo-pantaila behartuta</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Profilak desgaituta</string>
+ <string name="accessibility_quick_settings_screen_timeout">Pantailaren denbora-muga: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Pantailaren denbora-muga aldatu da: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Bateria modua</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Bateria modua: energia aurrezteko modua.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Bateria modua: modu orekatua.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Bateria modua: Errendimendu modua.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Bateria modua: modu eraginkorra.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Bateria modua: modu azkarra.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Bateria modua energia aurrezteko modura aldatu da.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Bateria modua modu orekatura aldatu da.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Bateria modua errendimendu modura aldatu da.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Bateria modua modu eraginkorrera aldatu da.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Bateria modua modu azkarrera aldatu da.</string>
+ <string name="quick_settings_performance_profile_detail_title">Bateria modua</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Blokeo-pantaila ezgaituta.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Blokeo-pantaila gaituta.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Blokeo pantaila ezgaituta.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Blokeo pantaila gaituta.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display itzalita.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display piztuta.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient display itzalita.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display piztuta.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Jakinarazpen flotatzaileak ezgaituta.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Jakinarazpen flotatzaileak gaituta.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Jakinarazpen flotatzaileak ezgaituta.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Jakinarazpen flotatzaileak gaituta.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kafeina ez.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kafeina bai.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Bateria aurrezlea itzalita.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Bateria aurrezlea piztuta.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Bateria aurrezlea itzalita.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Bateria aurrezlea piztuta.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Lauza dinamikoa</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Hurrengo alarma</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME hautatzailea</string>
+ <string name="dynamic_qs_tile_su_label">Root sarbidea</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay ezgaituta.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modu automatikoa.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: eguna modua.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: gaua modua.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: kaleko modua.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay ezgaituta.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay modu automatikora aldatu da.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay eguna modura aldatu da.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay gaua modura aldatu da.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay kaleko modura aldatu da.</string>
+ <string name="quick_settings_title_advanced_location">Hiru egoeratako kokapena</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Kokaleku txostena: bateria aurrezteko modua.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Kokaleku txostena: sentsoreak besterik ez modua.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Kokaleku txostena: Zehaztasun handiko modua.</string>
+ <string name="quick_settings_location_detail_title">Kokaleku modua</string>
+ <string name="quick_settings_location_battery_saving_label">Bateria aurreztea</string>
+ <string name="quick_settings_location_gps_only_label">Gailua bakarrik</string>
+ <string name="quick_settings_location_high_accuracy_label">Zehaztasun handia</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Kokaleku txostena bateria aurrezteko modura aldatu da.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Kokaleku txostena sentsoreak besterik ez modura aldatu da.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Kokaleku txostena zehaztasun handiko modura aldatu da.</string>
+ <string name="quick_settings_tiles_category_system">Sistemaren lauzak</string>
+ <string name="quick_settings_tiles_add_tiles">Gehitu lauza bat</string>
+ <string name="hotspot_apm_message">Ezin da sare mugikorretara konektatu hegaldi modua gaituta dagoenean. Desgaitu hegaldi modua eta saiatu berriro.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Linterna piztuta dago</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Sakatu itzaltzeko</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fa/cm_arrays.xml b/packages/SystemUI/res/values-fa/cm_arrays.xml
new file mode 100644
index 0000000..7f3d065
--- /dev/null
+++ b/packages/SystemUI/res/values-fa/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>ش</item>
+ <item>ش خ</item>
+ <item>خ</item>
+ <item>ج خ</item>
+ <item>ج</item>
+ <item>ج ب</item>
+ <item>ب</item>
+ <item>ش ب</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-fa/cm_strings.xml b/packages/SystemUI/res/values-fa/cm_strings.xml
new file mode 100644
index 0000000..030560e
--- /dev/null
+++ b/packages/SystemUI/res/values-fa/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s </xliff:g> - <xliff:g id="condition">%2$s </xliff:g></string>
+ <string name="left_shortcut_hint">برای %1$s به راست بکشید</string>
+ <string name="right_shortcut_hint">برای %1$s به چپ بکشید</string>
+ <string name="select_application">انتخاب برنامه</string>
+ <string name="lockscreen_choose_action_title">انتخاب عملکرد</string>
+ <string name="lockscreen_none_target">هیچ‌کدام</string>
+ <string name="navbar_dialog_title">انتخاب عملکرد</string>
+ <string name="navbar_home_button">دکمه صفحه اصلی</string>
+ <string name="navbar_recent_button">دکمه برنامه‌های اخیر</string>
+ <string name="navbar_search_button">دکمه جستجو</string>
+ <string name="navbar_back_button">دکمه بازگشت</string>
+ <string name="navbar_empty_button">دکمه خالی</string>
+ <string name="navbar_menu_conditional_button">دکمه منو (پنهان)</string>
+ <string name="navbar_menu_always_button">دکمه منو (نمایش همیشگی)</string>
+ <string name="navbar_menu_big_button">دکمه منو</string>
+ <string name="accessibility_dpad_left">نشانگر چپ</string>
+ <string name="accessibility_dpad_right">نشانگر راست</string>
+ <string name="advanced_dev_option_wipe_app">پاک کردن داده‌های برنامه</string>
+ <string name="advanced_dev_option_force_stop">توقف اجباری</string>
+ <string name="advanced_dev_option_uninstall">لغو نصب</string>
+ <string name="accessibility_quick_settings_profiles_off">پروفایل‌ها خاموش.</string>
+ <string name="accessibility_quick_settings_profiles">پروفایل: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">پروفایل‌ها خاموش شدند.</string>
+ <string name="accessibility_quick_settings_profiles_changed">پروفایل به <xliff:g id="profile" example="Default">%s</xliff:g> تغییر یافت.</string>
+ <string name="quick_settings_compass_init">مقداردهی اولیه\u2026</string>
+ <string name="screen_pinning_description_no_navbar">این صفحه تا زمانی که آن را از سنجاق درآورید نمایش داده می‌شود. برای از سنجاق درآوردن دکمه بازگشت را نگه دارید.</string>
+ <string name="quick_settings_custom_tile_detail_title">کاشی سفارشی</string>
+ <string name="quick_settings_remove">حذف کاشی</string>
+ <string name="quick_settings_network_adb_label">ای‌دی‌بی از طریق شبکه</string>
+ <string name="quick_settings_compass_label">قطب‌نما</string>
+ <string name="quick_settings_nfc_label">ان‌اف‌سی</string>
+ <string name="quick_settings_profiles">پروفایل‌ها</string>
+ <string name="quick_settings_profiles_off">پروفایل‌ها غیرفعالند</string>
+ <string name="quick_settings_heads_up_label">اعلان فوری</string>
+ <string name="quick_settings_battery_saver_label">بهینه‌ساز باتری</string>
+ <string name="accessibility_quick_settings_sync_off">همگام‌سازی خاموش.</string>
+ <string name="accessibility_quick_settings_sync_on">همگام‌سازی روشن.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">همگام‌سازی خاموش شد.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">همگام‌سازی روشن شد.</string>
+ <string name="quick_settings_sync_label">همگام‌‌سازی</string>
+ <string name="quick_settings_volume_panel_label">پنل صدا</string>
+ <string name="quick_settings_usb_tether_label">تترینگ یو‌اس‌بی</string>
+ <string name="quick_settings_screen_timeout_detail_title">ﺯﻣﺎﻥ خاموش شدن صفحه</string>
+ <string name="quick_settings_lockscreen_label">قفل صفحه</string>
+ <string name="quick_settings_ambient_display_label">نمایش حساس به محیط</string>
+ <string name="quick_settings_lockscreen_label_enforced">اجرای قفل صفحه</string>
+ <string name="accessibility_quick_settings_screen_timeout">زمان خاموش شدن صفحه: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">زمان خاموش شدن صفحه به <xliff:g id="timeout" example="30 seconds">%s</xliff:g> تغییر یافت.</string>
+ <string name="qs_tile_performance">حالت باتری</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">حالت باتری: ذخیره نیرو.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">حالت باتری: متعادل.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">حالت باتری: کارایی.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">حالت باتری: بازدهی.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">حالت باتری: سریع.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">حالت باتری به ذخیره نیرو تغییر یافت.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">حالت باتری به متعادل تغییر یافت.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">حالت باتری به کارایی تغییر یافت.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">حالت باتری به بازدهی تغییر یافت.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">حالت باتری به سریع تغییر یافت.</string>
+ <string name="quick_settings_performance_profile_detail_title">حالت باتری</string>
+ <string name="accessibility_quick_settings_lock_screen_off">قفل صفحه خاموش.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">قفل صفحه روشن.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">قفل صفحه خاموش شد.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">قفل صفحه روشن شد.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">نمایش حساس به محیط خاموش.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">نمایش حساس به محیط روشن.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">نمایش حساس به محیط خاموش شد.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">نمایش حساس به محیط روشن شد.</string>
+ <string name="accessibility_quick_settings_heads_up_off">اعلان فوری خاموش.</string>
+ <string name="accessibility_quick_settings_heads_up_on">اعلان فوری روشن.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">اعلان فوری خاموش شد.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">اعلان فوری روشن شد.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">بهینه‌ساز باتری خاموش.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">بهینه‌ساز باتری روشن.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">بهینه‌ساز باتری خاموش شد.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">بهینه‌ساز باتری روشن شد.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">کاشی پویا</string>
+ <string name="dynamic_qs_tile_next_alarm_label">هشدار بعدی</string>
+ <string name="dynamic_qs_tile_ime_selector_label">انتخابگر تغییر روش ورودی</string>
+ <string name="dynamic_qs_tile_su_label">دسترسی روت</string>
+ <string name="accessibility_quick_settings_live_display_off">نمایش پویا خاموش.</string>
+ <string name="accessibility_quick_settings_live_display_auto">نمایش پویا: حالت خودکار.</string>
+ <string name="accessibility_quick_settings_live_display_day">نمایش پویا: حالت روز.</string>
+ <string name="accessibility_quick_settings_live_display_night">نمایش پویا: حالت شب.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">نمایش پویا: حالت فضای باز.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">نمایش پویا خاموش شد.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">نمایش پویا به حالت خودکار تغییر کرد.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">نمایش پویا به حالت روز تغییر کرد.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">نمایش پویا به حالت شب تغییر کرد.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">نمایش پویا به حالت فضای باز تغییر کرد.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">گزارش مکان: حالت صرفه‌جویی در باتری.</string>
+ <string name="accessibility_quick_settings_location_gps_only">گزارش مکان: حالت فقط حسگرها.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">گزارش مکان: حالت دقت بالا.</string>
+ <string name="quick_settings_location_detail_title">حالت مکان</string>
+ <string name="quick_settings_location_battery_saving_label">صرفه‌جویی در باتری</string>
+ <string name="quick_settings_location_gps_only_label">فقط دستگاه</string>
+ <string name="quick_settings_location_high_accuracy_label">دقت بالا</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">گزارش مکان به حالت صرفه‌جویی در باتری تغییر یافت.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">گزارش مکان به حالت فقط حسگرها تغییر یافت.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">گزارش مکان به حالت دقت بالا تغییر یافت.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fi/cm_arrays.xml b/packages/SystemUI/res/values-fi/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-fi/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-fi/cm_strings.xml b/packages/SystemUI/res/values-fi/cm_strings.xml
new file mode 100644
index 0000000..56d12e7
--- /dev/null
+++ b/packages/SystemUI/res/values-fi/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Pyyhkäise oikealle %1$s kertaa</string>
+ <string name="right_shortcut_hint">Pyyhkäise vasemmalle %1$s kertaa</string>
+ <string name="lockscreen_message">Napauta vasenta tai oikeaa kuvaketta määrittääksesi lukitusnäytön pikakuvakkeen.</string>
+ <string name="lockscreen_default_target">Oletus</string>
+ <string name="select_application">Valitse sovellus</string>
+ <string name="lockscreen_choose_action_title">Valitse tehtävä</string>
+ <string name="lockscreen_none_target">Ei mitään</string>
+ <string name="navbar_dialog_title">Valitse käytettävä toiminto</string>
+ <string name="navbar_home_button">Kotinäppäin</string>
+ <string name="navbar_recent_button">Viimeisimmät-näppäin</string>
+ <string name="navbar_search_button">Hakunäppäin</string>
+ <string name="navbar_back_button">Takaisin-näppäin</string>
+ <string name="navbar_empty_button">Tyhjä näppäin</string>
+ <string name="navbar_menu_conditional_button">Valikkonäppäin (piilota)</string>
+ <string name="navbar_menu_always_button">Valikkonäppäin (näytä aina)</string>
+ <string name="navbar_menu_big_button">Valikkonäppäin</string>
+ <string name="accessibility_dpad_left">Kohdistin vasemmalle</string>
+ <string name="accessibility_dpad_right">Kohdistin oikealle</string>
+ <string name="advanced_dev_option_wipe_app">Tyhjennä tiedot</string>
+ <string name="advanced_dev_option_force_stop">Pakota lopetus</string>
+ <string name="advanced_dev_option_uninstall">Poista</string>
+ <string name="accessibility_notification_brightness">Valon kirkkaus</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiilit pois.</string>
+ <string name="accessibility_quick_settings_profiles">Profiili: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiilit pois päältä.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profiili <xliff:g id="profile" example="Default">%s</xliff:g> otettiin käyttöön.</string>
+ <string name="quick_settings_compass_init">Alustetaan\u2026</string>
+ <string name="led_notification_title">Valoasetukset</string>
+ <string name="led_notification_text">LED-valo otettu käyttöön asetuksissa</string>
+ <string name="qs_tile_edit_header_instruction">Paina tiiltä ja pidä pohjassa järjestääksesi</string>
+ <string name="quick_settings_edit_label">Muokkaa tiiliä</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Et voi poistaa Muokkaa-tiiltä</string>
+ <string name="qs_tiles_reset_confirmation">Palauta pika-asetustiilet oletusasetuksiinsa?</string>
+ <string name="quick_settings_tile_reset_to_default">Palauta oletusasettelu</string>
+ <string name="quick_settings_title_header">Ylärivi</string>
+ <string name="quick_settings_title_tiles">Tiilet</string>
+ <string name="quick_settings_title_show_weather">Näytä sää</string>
+ <string name="quick_settings_title_show_brightness_slider">Näytä kirkkauden liukusäädin</string>
+ <string name="quick_settings_title_enlarge_first_row">Pienennä ensimmäinen rivi</string>
+ <string name="screen_pinning_description_no_navbar">Tämä pitää sen näkyvissä, kunnes poistat kiinnityksen. Paina ja pidä Takasin-näppäintä pohjassa irrottaaksesi.</string>
+ <string name="quick_settings_custom_tile_detail_title">Mukautettu tiili</string>
+ <string name="quick_settings_remove">Poista tiili</string>
+ <string name="quick_settings_network_adb_label">ADB verkon yli</string>
+ <string name="quick_settings_compass_label">Kompassi</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Järjestelmäprofiilit</string>
+ <string name="quick_settings_profiles_off">Profiilit pois käytöstä</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Virransäästö</string>
+ <string name="quick_settings_caffeine_label">Kofeiini</string>
+ <string name="accessibility_quick_settings_sync_off">Synkronointi pois.</string>
+ <string name="accessibility_quick_settings_sync_on">Synkronointi päällä.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synkronointi pois päältä.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synkronointi päällä.</string>
+ <string name="quick_settings_sync_label">Synkronointi</string>
+ <string name="quick_settings_volume_panel_label">Äänenvoimakkuuspaneeli</string>
+ <string name="quick_settings_usb_tether_label">USB-jakaminen</string>
+ <string name="quick_settings_screen_timeout_detail_title">Näytön aikakatkaisu</string>
+ <string name="quick_settings_lockscreen_label">Lukitusnäyttö</string>
+ <string name="quick_settings_ambient_display_label">Ambient-näyttö</string>
+ <string name="quick_settings_lockscreen_label_enforced">Lukitusnäyttö pakotettu</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Profiili poistanut käytöstä</string>
+ <string name="accessibility_quick_settings_screen_timeout">Näytön aikakatkaisu: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Näytön aikakatkaisu asettiin aikaan <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Akkutila</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Akkutila: virransäästötila.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Akkutila: tasapainotettu-tila.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Akkutila: suorituskykytila.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Akkutila: virransäästö.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Akkutila: suorituskyky.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Akkutila asetettiin virransäästötilaan.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Akkutila asetettiin tasapainotettu-tilaan.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Akkutila asetettiin suorituskykytilaan.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Akkutila vaihdettu virransäästötilaan.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Akkutila vaihdettu suorituskykytilaan.</string>
+ <string name="quick_settings_performance_profile_detail_title">Akkutila</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Lukitusnäyttö pois.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Lukitusnäyttö päällä.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Lukitusnäyttö pois päältä.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Lukitusnäyttö päällä.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient-näyttö pois.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient-näyttö päällä.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient-näyttö pois päältä.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient-näyttö päällä.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up pois.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up päällä.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up pois päältä.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up päällä.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kofeiini pois.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kofeiini päällä.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Virransäästö pois.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Virransäästö päällä.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Virransäästö pois käytöstä.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Virransäästö käytössä.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynaamiset tiilet</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Seuraava hälytys</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Syöttötavan valitsin</string>
+ <string name="dynamic_qs_tile_su_label">Root-oikeudet</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay pois.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automaattitila.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: päivätila.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: yötila.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: ulkoilmatila.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay pois päältä.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay asetettu automaattitilaan.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay asetettu päivätilaan.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay asetettu yötilaan.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay asetettu ulkoilmatilaan.</string>
+ <string name="quick_settings_title_advanced_location">Sijainnin lisäasetukset</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Sijainnin raportointi: virransäästötila.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Sijainti: Vain laite.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Sijainnin raportointi: korkea tarkkuus.</string>
+ <string name="quick_settings_location_detail_title">Sijaintitilat</string>
+ <string name="quick_settings_location_battery_saving_label">Virransäästö</string>
+ <string name="quick_settings_location_gps_only_label">Vain laite</string>
+ <string name="quick_settings_location_high_accuracy_label">Korkea tarkkuus</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Sijaintitila asetettu virransäästötilaan.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Sijaintitila asetettu vain laite-tilaan.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Sijaintitila asetettu korkean tarkkuuden tilaan.</string>
+ <string name="quick_settings_tiles_category_system">Järjestelmätiilet</string>
+ <string name="quick_settings_tiles_add_tiles">Lisää tiili</string>
+ <string name="hotspot_apm_message">Yhteyden muodostaminen mobiiliverkkoihin lentokonetilan aikana ei onnistu. Poista lentokonetila käytöstä ja yritä uudelleen.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Taskulamppu on päällä</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Paina sammuttaaksesi</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr/cm_arrays.xml b/packages/SystemUI/res/values-fr/cm_arrays.xml
new file mode 100644
index 0000000..cb6fbec
--- /dev/null
+++ b/packages/SystemUI/res/values-fr/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-fr/cm_strings.xml b/packages/SystemUI/res/values-fr/cm_strings.xml
new file mode 100644
index 0000000..ffcb7e1
--- /dev/null
+++ b/packages/SystemUI/res/values-fr/cm_strings.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Balayer à droite pour %1$s</string>
+ <string name="right_shortcut_hint">Balayer à gauche pour %1$s</string>
+ <string name="lockscreen_message">Appuyez sur une icône à gauche ou à droite pour réattribuer un raccourci sur l\'écran de verrouillage.</string>
+ <string name="lockscreen_default_target">Par défaut</string>
+ <string name="select_application">Sélectionner une application</string>
+ <string name="lockscreen_choose_action_title">Choisir une action</string>
+ <string name="lockscreen_none_target">Aucune</string>
+ <string name="navbar_dialog_title">Choisir l\'action à assigner</string>
+ <string name="navbar_home_button">Bouton d\'accueil</string>
+ <string name="navbar_recent_button">Bouton d\'applications récentes</string>
+ <string name="navbar_search_button">Bouton de recherche</string>
+ <string name="navbar_back_button">Bouton retour</string>
+ <string name="navbar_empty_button">Bouton vide</string>
+ <string name="navbar_menu_conditional_button">Bouton menu (masqué automatiquement)</string>
+ <string name="navbar_menu_always_button">Bouton menu (toujours affiché)</string>
+ <string name="navbar_menu_big_button">Bouton menu</string>
+ <string name="accessibility_dpad_left">Curseur gauche</string>
+ <string name="accessibility_dpad_right">Curseur droit</string>
+ <string name="advanced_dev_option_wipe_app">Effacer les données de l\'application</string>
+ <string name="advanced_dev_option_force_stop">Forcer l\'arrêt</string>
+ <string name="advanced_dev_option_uninstall">Désinstaller</string>
+ <string name="accessibility_notification_brightness">Luminosité</string>
+ <string name="accessibility_quick_settings_profiles_off">Profils désactivés.</string>
+ <string name="accessibility_quick_settings_profiles">Profil : <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profils désactivés.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil changé en <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Initialisation\u2026</string>
+ <string name="led_notification_title">Paramètres de la DEL</string>
+ <string name="led_notification_text">DEL activée par les paramètres</string>
+ <string name="qs_tile_edit_header_instruction">Appuyez et maintenez les raccourcis pour les réorganiser</string>
+ <string name="quick_settings_edit_label">Modifier les raccourcis</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Impossible de supprimer le raccourci modifié</string>
+ <string name="qs_tiles_reset_confirmation">Réinitialiser les raccourcis à la configuration par défaut ?</string>
+ <string name="quick_settings_tile_reset_to_default">Réinitialiser à la disposition par défaut</string>
+ <string name="quick_settings_title_header">En-tête</string>
+ <string name="quick_settings_title_tiles">Raccourcis</string>
+ <string name="quick_settings_title_show_weather">Afficher la météo</string>
+ <string name="quick_settings_title_enlarge_first_row">Agrandir la première ligne</string>
+ <string name="screen_pinning_description_no_navbar">Cela le laisse en vue jusqu\'à ce que vous le détachiez. Appuyez et maintenez le bouton retour pour détacher.</string>
+ <string name="quick_settings_custom_tile_detail_title">Raccourci personnalisé</string>
+ <string name="quick_settings_remove">Supprimer le raccourci</string>
+ <string name="quick_settings_network_adb_label">ADB par réseau</string>
+ <string name="quick_settings_compass_label">Boussole</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Profils système</string>
+ <string name="quick_settings_profiles_off">Profils désactivés</string>
+ <string name="quick_settings_heads_up_label">Notifications flottantes</string>
+ <string name="quick_settings_battery_saver_label">Économiseur de batterie</string>
+ <string name="accessibility_quick_settings_sync_off">Synchronisation désactivée.</string>
+ <string name="accessibility_quick_settings_sync_on">Synchronisation activée.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchronisation désactivée.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchronisation activée.</string>
+ <string name="quick_settings_sync_label">Synchroniser</string>
+ <string name="quick_settings_volume_panel_label">Panneau de volume</string>
+ <string name="quick_settings_usb_tether_label">Modem USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Veille de l\'écran</string>
+ <string name="quick_settings_lockscreen_label">Écran de verrouillage</string>
+ <string name="quick_settings_ambient_display_label">Affichage en mode veille</string>
+ <string name="quick_settings_lockscreen_label_enforced">Écran de verrouillage forcé</string>
+ <string name="accessibility_quick_settings_screen_timeout">Veille de l\'écran : <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Veille de l\'écran changée à <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Mode batterie</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Mode batterie : économie d\'énergie.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Mode batterie : équilibré.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Mode batterie : haute performance.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Mode batterie : efficace.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Mode batterie : rapide.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">La batterie est maintenant en mode économie d\'énergie.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">La batterie est maintenant en mode équilibré.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">La batterie est maintenant en mode performances.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Mode batterie changé en mode efficace.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Mode batterie changé en mode rapide.</string>
+ <string name="quick_settings_performance_profile_detail_title">Mode batterie</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Écran de verrouillage désactivé.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Écran de verrouillage activé.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Verrouillage d\'écran désactivé.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Verrouillage d\'écran activé.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Affichage en mode veille désactivé.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Affichage en mode veille activé.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Affichage en mode veille désactivé.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Affichage en mode veille activé.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Notifications flottantes désactivées.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Notifications flottantes activées.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Notifications flottantes désactivées.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Notifications flottantes activées.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Économiseur de batterie désactivé.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Économiseur de batterie activé.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">L\'économiseur de batterie a été désactivé.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">L\'économiseur de batterie a été activé.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Raccourcis dynamiques</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Prochaine alarme</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Sélecteur de mode de saisie</string>
+ <string name="dynamic_qs_tile_su_label">Accès root</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay désactivé.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay : mode automatique.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay : mode jour.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay : mode nuit.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay : mode plein air.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay désactivé.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay changé en mode automatique.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay changé en mode jour.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay changé en mode nuit.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay changé en mode plein air.</string>
+ <string name="quick_settings_title_advanced_location">Localisation par triangulation</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Localisation : mode économie de batterie.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Localisation : mode appareil uniquement.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Localisation : mode haute précision.</string>
+ <string name="quick_settings_location_detail_title">Mode de localisation</string>
+ <string name="quick_settings_location_battery_saving_label">Économie de batterie</string>
+ <string name="quick_settings_location_gps_only_label">Appareil uniquement</string>
+ <string name="quick_settings_location_high_accuracy_label">Haute précision</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Localisation changée en mode économie de batterie.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Localisation changée en mode appareil uniquement.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Localisation changée en mode haute précision.</string>
+ <string name="quick_settings_tiles_category_system">Raccourcis système</string>
+ <string name="quick_settings_tiles_add_tiles">Ajouter un raccourci</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fy-rNL/cm_strings.xml b/packages/SystemUI/res/values-fy-rNL/cm_strings.xml
new file mode 100644
index 0000000..5c05f67
--- /dev/null
+++ b/packages/SystemUI/res/values-fy-rNL/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="quick_settings_nfc_label">NFC</string>
+</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/cm_arrays.xml b/packages/SystemUI/res/values-gl-rES/cm_arrays.xml
new file mode 100644
index 0000000..3d34bbb
--- /dev/null
+++ b/packages/SystemUI/res/values-gl-rES/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NL</item>
+ <item>L</item>
+ <item>SL</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/cm_strings.xml b/packages/SystemUI/res/values-gl-rES/cm_strings.xml
new file mode 100644
index 0000000..ef89e4c
--- /dev/null
+++ b/packages/SystemUI/res/values-gl-rES/cm_strings.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Arrastra á dereita para %1$s</string>
+ <string name="right_shortcut_hint">Arrastra á esquerda para %1$s</string>
+ <string name="lockscreen_message">Toque nunha icona na dereita ou na esquerda para volver a asignar un atallo da pantalla de bloqueo.</string>
+ <string name="lockscreen_default_target">Predeterminado</string>
+ <string name="select_application">Seleccionar aplicación</string>
+ <string name="lockscreen_choose_action_title">Escoller acción</string>
+ <string name="lockscreen_none_target">Ningunha</string>
+ <string name="navbar_dialog_title">Escoller unha acción que asignar</string>
+ <string name="navbar_home_button">Botón de inicio</string>
+ <string name="navbar_recent_button">Botón de recentes</string>
+ <string name="navbar_search_button">Botón de buscas</string>
+ <string name="navbar_back_button">Botón de retroceso</string>
+ <string name="navbar_empty_button">Botón baleiro</string>
+ <string name="navbar_menu_conditional_button">Botón de menú (autoagochar)</string>
+ <string name="navbar_menu_always_button">Botón de menú (amosar sempre)</string>
+ <string name="navbar_menu_big_button">Botón do menú</string>
+ <string name="accessibility_dpad_left">Cursor á esquerda</string>
+ <string name="accessibility_dpad_right">Cursor á dereita</string>
+ <string name="advanced_dev_option_wipe_app">Borrar os datos da aplicación</string>
+ <string name="advanced_dev_option_force_stop">Forzar a parada</string>
+ <string name="advanced_dev_option_uninstall">Desinstalar</string>
+ <string name="accessibility_notification_brightness">Brillo da luz</string>
+ <string name="accessibility_quick_settings_profiles_off">Perfís desactivados.</string>
+ <string name="accessibility_quick_settings_profiles">Perfil: <xliff:g id="profile" example="Predeterminado">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Perfís desactivados.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Perfil cambiado a <xliff:g id="profile" example="Predeterminado">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicializando\u2026</string>
+ <string name="led_notification_title">Configuración de luz</string>
+ <string name="led_notification_text">Luz LED activada por configuración</string>
+ <string name="qs_tile_edit_header_instruction">Prema e sosteña as baldosas para reorganizalas</string>
+ <string name="quick_settings_edit_label">Editar baldosas</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Non foi posíbel eliminar a baldosa Editar</string>
+ <string name="qs_tiles_reset_confirmation">Restabelecer a configuración rápida de baldosas á configuración predeterminada?</string>
+ <string name="quick_settings_tile_reset_to_default">Restabelecer coa disposición predeterminada</string>
+ <string name="quick_settings_title_header">Cabeceira</string>
+ <string name="quick_settings_title_tiles">Baldosas</string>
+ <string name="quick_settings_title_show_weather">Amosar o prognóstico</string>
+ <string name="quick_settings_title_enlarge_first_row">Ampliar a primeira fila</string>
+ <string name="screen_pinning_description_no_navbar">Amosarase mentres esté fixado. Para deixar de fixalo, mantén tocado o botón Atrás.</string>
+ <string name="quick_settings_custom_tile_detail_title">Botón personalizado</string>
+ <string name="quick_settings_remove">Retirar botón</string>
+ <string name="quick_settings_network_adb_label">ADB na rede</string>
+ <string name="quick_settings_compass_label">Compás</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Perfís do sistema</string>
+ <string name="quick_settings_profiles_off">Perfís desactivados</string>
+ <string name="quick_settings_heads_up_label">Notificacións emerxentes</string>
+ <string name="quick_settings_battery_saver_label">Economizador da bateria</string>
+ <string name="accessibility_quick_settings_sync_off">Sincronización apagada.</string>
+ <string name="accessibility_quick_settings_sync_on">Sincronización acesa.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">A sincronización foi apagada.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">A sincronización foi acendida.</string>
+ <string name="quick_settings_sync_label">Sincronización</string>
+ <string name="quick_settings_volume_panel_label">Panel de volume</string>
+ <string name="quick_settings_usb_tether_label">Compartir conexión USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Tempo de espera da pantalla</string>
+ <string name="quick_settings_lockscreen_label">Bloqueo de pantalla</string>
+ <string name="quick_settings_ambient_display_label">Visualización de ambiente</string>
+ <string name="quick_settings_lockscreen_label_enforced">Bloqueo de pantalla estabelecido</string>
+ <string name="accessibility_quick_settings_screen_timeout">Tempo de espera da pantalla: <xliff:g id="timeout" example="30 segundos">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Tempo de espera da pantalla cambiado a <xliff:g id="timeout" example="30 segundos">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Modo da batería</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Modo da batería: modo de aforro de enerxía.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Modo da batería: modo equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Modo da batería: modo rendemento.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Modo da bateria: modo eficiente.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Modo da bateria: modo rápido.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">O modo da batería cambiou a modo de aforro de enerxía.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">O modo da batería cambiou a modo equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">O modo da batería cambiou a modo rendemento.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">O modo da batería cambiou a modo eficiente.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">O modo da batería cambiou a modo rápido.</string>
+ <string name="quick_settings_performance_profile_detail_title">Modo da batería</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Bloqueo de pantalla desactivado.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Bloqueo de pantalla activado.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Bloqueo de pantalla desactivado.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Bloqueo de pantalla activado.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Visualización de ambiente desactivada.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Visualización de ambiente activada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">A visualización de ambiente foi desactivada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">A visualización de ambiente foi activada.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Notificacións emerxentes desactivadas.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Notificacións emerxentes activadas.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">As notificacións emerxentes foron desactivadas.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">As notificacións emerxentes foron activadas.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Economizador da batería apagado.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Economizador da bateria aceso.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">O economizador da batería foi apagado.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">O economizador da batería foi acendido.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Botón dinámico</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Próxima alarma</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Selector IME</string>
+ <string name="dynamic_qs_tile_su_label">Acceso de superusuario</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay desactivado.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modo día.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modo noite.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modo exteriores.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay desactivado.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay cambiado a modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay cambiado a modo día.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay cambiado a modo noite.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay cambiado a modo exteriores.</string>
+ <string name="quick_settings_title_advanced_location">Localización por triangulación</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Informe de localización: en modo aforro de batería.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Informe de localización: en modo de sensores.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Informe de localización: en modo de alta precisión.</string>
+ <string name="quick_settings_location_detail_title">Modo de localización</string>
+ <string name="quick_settings_location_battery_saving_label">Aforro de batería</string>
+ <string name="quick_settings_location_gps_only_label">Só dispositivo</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precisión</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Informe de localización cambiado a modo aforro de batería.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Informe de localización cambiado a modo sensores.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Informe de localización cambiado a modo alta precisión.</string>
+ <string name="hotspot_apm_message">Non é posíbel conectar a rede móbil mentres o modo Avión está activado. Desactívao e téntao de novo.</string>
+ <string name="quick_settings_tile_flashlight_not_title">A lanterna está acesa</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Toca para apagala</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hdpi/cm_dimens.xml b/packages/SystemUI/res/values-hdpi/cm_dimens.xml
new file mode 100644
index 0000000..404f22f
--- /dev/null
+++ b/packages/SystemUI/res/values-hdpi/cm_dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<resources>
+ <dimen name="weather_text_size">10sp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-hi/cm_arrays.xml b/packages/SystemUI/res/values-hi/cm_arrays.xml
new file mode 100644
index 0000000..e44502d
--- /dev/null
+++ b/packages/SystemUI/res/values-hi/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>उ</item>
+ <item>उपू</item>
+ <item>पू</item>
+ <item>दपू</item>
+ <item>द</item>
+ <item>दप</item>
+ <item>प</item>
+ <item>उप</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-hi/cm_strings.xml b/packages/SystemUI/res/values-hi/cm_strings.xml
new file mode 100644
index 0000000..fd86432
--- /dev/null
+++ b/packages/SystemUI/res/values-hi/cm_strings.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">%1$s के लिए दायाँ स्वाइप करें</string>
+ <string name="right_shortcut_hint">%1$s के लिए बायाँ स्वाइप करें</string>
+ <string name="select_application">अनुप्रयोग चुनें</string>
+ <string name="lockscreen_choose_action_title">कार्य चुनें</string>
+ <string name="lockscreen_none_target">कोई नहीं</string>
+ <string name="navbar_dialog_title">निर्दिष्ट करने के लिए कार्य चुनें</string>
+ <string name="navbar_home_button">होम बटन</string>
+ <string name="navbar_recent_button">हाल का बटन</string>
+ <string name="navbar_search_button">खोज बटन</string>
+ <string name="navbar_back_button">पीछे बटन</string>
+ <string name="navbar_empty_button">खाली बटन</string>
+ <string name="navbar_menu_conditional_button">मेनू (स्वतः छिपाएँ) बटन</string>
+ <string name="navbar_menu_always_button">मेनू (हमेशा दिखाएँ) बटन</string>
+ <string name="navbar_menu_big_button">मेनू बटन</string>
+ <string name="accessibility_dpad_left">कर्सर बायाँ</string>
+ <string name="accessibility_dpad_right">कर्सर दायाँ</string>
+ <string name="advanced_dev_option_wipe_app">ऐप डेटा को साफ़ करें</string>
+ <string name="advanced_dev_option_force_stop">ज़बर्दस्ती बंद करें</string>
+ <string name="advanced_dev_option_uninstall">विस्थापित करें</string>
+ <string name="accessibility_quick_settings_profiles_off">प्रोफ़ाइलें बंद है।</string>
+ <string name="accessibility_quick_settings_profiles">प्रोफ़ाइल: <xliff:g id="profile" example="Default">%s</xliff:g>।</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">प्रोफाइलों को बंद किया गया है।</string>
+ <string name="accessibility_quick_settings_profiles_changed">प्रोफ़ाइल को <xliff:g id="profile" example="Default">%s</xliff:g> में बदला गया।</string>
+ <string name="quick_settings_compass_init">प्रारंभ कर रहे हैं\u2026</string>
+ <string name="screen_pinning_description_no_navbar">यह इसे तब तक दृश्य में रखता है जब तक आप अनपिन नहीं करते। अनपिन करने के लिए बैक बटन को कुछ देर छूते रहें।</string>
+ <string name="quick_settings_custom_tile_detail_title">मनपसंद टाइल</string>
+ <string name="quick_settings_remove">टाइल हटाएँ</string>
+ <string name="quick_settings_network_adb_label">नेटवर्क पर एडीबी</string>
+ <string name="quick_settings_compass_label">कुतुबनुमा</string>
+ <string name="quick_settings_nfc_label">एनएफसी</string>
+ <string name="quick_settings_profiles">सिस्टम प्रोफ़ाइलें</string>
+ <string name="quick_settings_profiles_off">प्रोफ़ाइलें अक्षम हैं</string>
+ <string name="quick_settings_heads_up_label">हेड्स अप।</string>
+ <string name="accessibility_quick_settings_sync_off">संकालन बंद है।</string>
+ <string name="accessibility_quick_settings_sync_on">संकालन चालू है।</string>
+ <string name="accessibility_quick_settings_sync_changed_off">संकालन को बंद किया गया है।</string>
+ <string name="accessibility_quick_settings_sync_changed_on">संकालन को चालू किया गया है।</string>
+ <string name="quick_settings_sync_label">संकालन</string>
+ <string name="quick_settings_usb_tether_label">यूएसबी टेदरिंग</string>
+ <string name="quick_settings_screen_timeout_detail_title">स्क्रीन समय समाप्त</string>
+ <string name="quick_settings_lockscreen_label">स्क्रीन को लॉक करें</string>
+ <string name="quick_settings_ambient_display_label">परिवेशी प्रदर्शन</string>
+ <string name="quick_settings_lockscreen_label_enforced">स्क्रीन को लॉक करें प्रवर्तित</string>
+ <string name="accessibility_quick_settings_screen_timeout">स्क्रीन समय-समाप्ति: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>।</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">स्क्रीन समय-समाप्ति को <xliff:g id="timeout" example="30 seconds">%s</xliff:g> में बदला गया।</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">बैटरी मोड: पावर बचाव मोड।</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">बैटरी मोड: संतुलित मोड।</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">बैटरी मोड: निष्पादन मोड।</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">बैटरी मोड को पावर बचाव मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">बैटरी मोड को संतुलित मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">बैटरी मोड को निष्पादन मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_lock_screen_off">स्क्रीन को लॉक करें बंद है।</string>
+ <string name="accessibility_quick_settings_lock_screen_on">स्क्रीन को लॉक करें चालू है।</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">स्क्रीन को लॉक करें को बंद किया गया है।</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">स्क्रीन को लॉक करें को चालू किया गया है।</string>
+ <string name="accessibility_quick_settings_ambient_display_off">परिवेशी प्रदर्शन बंद है।</string>
+ <string name="accessibility_quick_settings_ambient_display_on">परिवेशी प्रदर्शन चालू है।</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">परिवेशी प्रदर्शन को बंद किया गया है।</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">परिवेशी प्रदर्शन को चालू किया गया।</string>
+ <string name="accessibility_quick_settings_heads_up_off">हेड्स अप बंद है।</string>
+ <string name="accessibility_quick_settings_heads_up_on">हेड्स अप चालू है।</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">हेड्स अप को बंद किया गया है।</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">हेड्स अप को चालू किया गया।</string>
+ <string name="quick_settings_dynamic_tile_detail_title">गतिशील टाइल</string>
+ <string name="dynamic_qs_tile_next_alarm_label">अलगा अलार्म</string>
+ <string name="dynamic_qs_tile_ime_selector_label">आईएमई चयनक</string>
+ <string name="dynamic_qs_tile_su_label">मूल पहुँच</string>
+ <string name="accessibility_quick_settings_live_display_off">लाइवडिस्प्ले बंद है।</string>
+ <string name="accessibility_quick_settings_live_display_auto">लाइवडिस्प्ले: स्वतः मोड।</string>
+ <string name="accessibility_quick_settings_live_display_day">लाइवडिस्प्ले: दिन मोड।</string>
+ <string name="accessibility_quick_settings_live_display_night">लाइवडिस्प्ले: रात मोड।</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">लाइवडिस्प्ले: बाहरी मोड।</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">लाइवडिस्प्ले को बंद किया गया है।</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">लाइवडिस्प्ले को स्वतः मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">लाइवडिस्प्ले को दिन मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">लाइवडिस्प्ले को रात मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">लाइवडिस्प्ले को बाहरी मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_location_battery_saving">स्थान रिपोर्टिंग: बैटरी बचानेवाला मोड।</string>
+ <string name="accessibility_quick_settings_location_gps_only">स्थान रिपोर्टिंग: केवल सेंसर मोड।</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">स्थान रिपोर्टिंग: उच्च सटीकता मोड।</string>
+ <string name="quick_settings_location_detail_title">स्थान मोड</string>
+ <string name="quick_settings_location_battery_saving_label">बैटरी बचानेवाला</string>
+ <string name="quick_settings_location_gps_only_label">केवल उपकरण</string>
+ <string name="quick_settings_location_high_accuracy_label">उच्च सटीकता</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">स्थान रिपोर्टिंग को बैटरी बचाव मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">स्थान रिपोर्टिंग में केवल संवेदक मोड में बदला गया।</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">स्थान रिपोर्टिंग को उच्च सटीकता मोड में बदला गया।</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hr/cm_arrays.xml b/packages/SystemUI/res/values-hr/cm_arrays.xml
new file mode 100644
index 0000000..f4c09d0
--- /dev/null
+++ b/packages/SystemUI/res/values-hr/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>S</item>
+ <item>SI</item>
+ <item>I</item>
+ <item>JI</item>
+ <item>J</item>
+ <item>JZ</item>
+ <item>Z</item>
+ <item>SZ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-hr/cm_strings.xml b/packages/SystemUI/res/values-hr/cm_strings.xml
new file mode 100644
index 0000000..5edba96
--- /dev/null
+++ b/packages/SystemUI/res/values-hr/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Kliznite desno za %1$s</string>
+ <string name="right_shortcut_hint">Kliznite lijevo za %1$s</string>
+ <string name="lockscreen_message">Dodirnite ikonu na lijevo ili desno kako bi preraspodijelili prečac zaključanog zaslona.</string>
+ <string name="lockscreen_default_target">Zadano</string>
+ <string name="select_application">Odaberite aplikaciju</string>
+ <string name="lockscreen_choose_action_title">Odaberite radnju</string>
+ <string name="lockscreen_none_target">Nijedan</string>
+ <string name="navbar_dialog_title">Odaberi radnju</string>
+ <string name="navbar_home_button">Home tipka</string>
+ <string name="navbar_recent_button">Tipka nedavno</string>
+ <string name="navbar_search_button">Tipka za pretraživanje</string>
+ <string name="navbar_back_button">Tipka nazad</string>
+ <string name="navbar_empty_button">Prazna tipka</string>
+ <string name="navbar_menu_conditional_button">Tipka izbornika (automatsko sakrivanje)</string>
+ <string name="navbar_menu_always_button">Tipka izbornika (uvijek prikaži)</string>
+ <string name="navbar_menu_big_button">Tipka izbornika</string>
+ <string name="accessibility_dpad_left">Kursor lijevo</string>
+ <string name="accessibility_dpad_right">Kursor desno</string>
+ <string name="advanced_dev_option_wipe_app">Izbriši podatke aplikacije</string>
+ <string name="advanced_dev_option_force_stop">Prisilno zaustavi</string>
+ <string name="advanced_dev_option_uninstall">Deinstaliraj</string>
+ <string name="accessibility_notification_brightness">Osvjetljenje svjetla</string>
+ <string name="accessibility_quick_settings_profiles_off">Profili isklučeni.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profili su isključeni.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil promijenjen u <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicijalizacija\u2026</string>
+ <string name="led_notification_title">Postavke svjetla</string>
+ <string name="led_notification_text">LED svjetlo omogućeno postavkama</string>
+ <string name="qs_tile_edit_header_instruction">Pritisnite i držite pločicu za uređivanje</string>
+ <string name="quick_settings_edit_label">Uredi pločice</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Nije moguće obrisati Uredi pločice</string>
+ <string name="qs_tiles_reset_confirmation">Vratiti pločice brzih postavki na zadano?</string>
+ <string name="quick_settings_tile_reset_to_default">Vraćanje na zadani izgled</string>
+ <string name="quick_settings_title_header">Zaglavlje</string>
+ <string name="quick_settings_title_tiles">Pločice</string>
+ <string name="quick_settings_title_show_weather">Pokaži prognozu</string>
+ <string name="quick_settings_title_show_brightness_slider">Pokaži klizač osvjetljenja</string>
+ <string name="quick_settings_title_enlarge_first_row">Povećaj prvi red</string>
+ <string name="screen_pinning_description_no_navbar">Ovo drži u pogledu dok ne otkvačite. Dodirnite i držite gumb natrag da bi otkvačili.</string>
+ <string name="quick_settings_custom_tile_detail_title">Prilagodljive pločice</string>
+ <string name="quick_settings_remove">Uklanjanje pločice</string>
+ <string name="quick_settings_network_adb_label">ADB preko mreže</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Profili sustava</string>
+ <string name="quick_settings_profiles_off">Profili onemogućeni</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Ušteda baterije</string>
+ <string name="quick_settings_caffeine_label">Kofein</string>
+ <string name="accessibility_quick_settings_sync_off">Sinkronizacija isključena.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinkronizacija uključena.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sinkronizacija je isključena.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sinkronizacija je uključena.</string>
+ <string name="quick_settings_sync_label">Sinkroniziranje</string>
+ <string name="quick_settings_volume_panel_label">Zvučna ploča</string>
+ <string name="quick_settings_usb_tether_label">USB dijeljenje veze</string>
+ <string name="quick_settings_screen_timeout_detail_title">Vrijeme do gašenja zaslona</string>
+ <string name="quick_settings_lockscreen_label">Zaključani zaslon</string>
+ <string name="quick_settings_ambient_display_label">Ambijentni zaslon</string>
+ <string name="quick_settings_lockscreen_label_enforced">Provođenje zaključavanja zaslona</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Onemogućeno od strane profila</string>
+ <string name="accessibility_quick_settings_screen_timeout">Isključivanje zaslona: <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Isključivanje zaslona promijenjeno u <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="qs_tile_performance">Način rada baterije</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Baterija: način uštede energije.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Baterija: uravnoteženo.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Baterija: performanse.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Baterija: učinkoviti način.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Baterija: brzo.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Rad baterije promijenjen u način uštede.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Rad baterije promijenjen u uravnotežen način.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Rad baterije promijenjen u performanse.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Način baterije promijenjen u učinkoviti.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Način baterije promijenjen u brzi.</string>
+ <string name="quick_settings_performance_profile_detail_title">Način rada baterije</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Zaključani zaslon isključen.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Zaključani zaslon uključen.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Zaključani zaslon je isključen.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Zaključani zaslon je uključen.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambijentni zaslon isključen.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambijentni zaslon uključen.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambijentni zaslon je isključen.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambijentni zaslon je uključen.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up isključen.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up uključen.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up je isključen.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up je uključen.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kofein isključen.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kofein uključen.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Ušteda baterije isključena.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Ušteda baterije uključena.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Ušteda baterije je isključena.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Ušteda baterije je uključena.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamične pločice</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Sljedeći alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME za odabir</string>
+ <string name="dynamic_qs_tile_su_label">Root pristup</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay isključen.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: auto.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: dnevni način.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: noćni način.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: vanjski način.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay isključen.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay promijenjen u auto.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay promijenjen u dnevni način.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay promijenjen u noćni način rada.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay promijenjen u vanjski način.</string>
+ <string name="quick_settings_title_advanced_location">Način lokacije</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Prijavljivanje lokacije: štednja baterije.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Prijavljivanje lokacije: samo senzori.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Prijavljivanje lokacije: visoka preciznost.</string>
+ <string name="quick_settings_location_detail_title">Način rada lokacije</string>
+ <string name="quick_settings_location_battery_saving_label">Štednja baterije</string>
+ <string name="quick_settings_location_gps_only_label">Samo uređaj</string>
+ <string name="quick_settings_location_high_accuracy_label">Visoka preciznost</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Prijavljivanje lokacije promijenjeno u način uštede baterije.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Prijavljivanje lokacije promijenjeno u samo senzori.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Prijavljivanje lokacije promijenjeno u način visoke preciznosti.</string>
+ <string name="quick_settings_tiles_category_system">Sistemske pločice</string>
+ <string name="quick_settings_tiles_add_tiles">Dodaj pločicu</string>
+ <string name="hotspot_apm_message">Nije moguće povezivanje s mobilnim mrežama dok je omogućen način rada u zrakoplovu. Onemogućite način rada u zrakoplovu i pokušajte ponovno.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Svjetiljka je uključena</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Dodirnite za isključivanje</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hu/cm_arrays.xml b/packages/SystemUI/res/values-hu/cm_arrays.xml
new file mode 100644
index 0000000..60b4d1b
--- /dev/null
+++ b/packages/SystemUI/res/values-hu/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>É</item>
+ <item>ÉK</item>
+ <item>K</item>
+ <item>DK</item>
+ <item>D</item>
+ <item>DNy</item>
+ <item>Ny</item>
+ <item>ÉNy</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-hu/cm_strings.xml b/packages/SystemUI/res/values-hu/cm_strings.xml
new file mode 100644
index 0000000..5a3f211
--- /dev/null
+++ b/packages/SystemUI/res/values-hu/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Csúsztasson jobbra ezért: %1$s</string>
+ <string name="right_shortcut_hint">Csúsztasson balra ezért: %1$s</string>
+ <string name="lockscreen_message">Érintsen meg egy ikont jobb vagy bal oldalt a zárképernyő hivatkozások ismételt hozzárendeléséhez.</string>
+ <string name="lockscreen_default_target">Alapértelmezett</string>
+ <string name="select_application">Válasszon alkalmazást</string>
+ <string name="lockscreen_choose_action_title">Válasszon eseményt</string>
+ <string name="lockscreen_none_target">Nincs</string>
+ <string name="navbar_dialog_title">Válasszon eseményt</string>
+ <string name="navbar_home_button">Kezdőgomb</string>
+ <string name="navbar_recent_button">Alkalmazás előzmények gomb</string>
+ <string name="navbar_search_button">Keresés gomb</string>
+ <string name="navbar_back_button">Vissza gomb</string>
+ <string name="navbar_empty_button">Üres gomb</string>
+ <string name="navbar_menu_conditional_button">Menü (auto elrejtés)</string>
+ <string name="navbar_menu_always_button">Menü (mindig látszik)</string>
+ <string name="navbar_menu_big_button">Menü gomb</string>
+ <string name="accessibility_dpad_left">Kurzor balra</string>
+ <string name="accessibility_dpad_right">Kurzor jobbra</string>
+ <string name="advanced_dev_option_wipe_app">Alkalmazások adatok törlése</string>
+ <string name="advanced_dev_option_force_stop">Kényszerített leállítás</string>
+ <string name="advanced_dev_option_uninstall">Eltávolítás</string>
+ <string name="accessibility_notification_brightness">LED fényereje</string>
+ <string name="accessibility_quick_settings_profiles_off">Profilok ki.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profilok kikapcsolva.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil megváltoztatva: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicializálás\u2026</string>
+ <string name="led_notification_title">LED beállítások</string>
+ <string name="led_notification_text">LED fény engedélyezve</string>
+ <string name="qs_tile_edit_header_instruction">Nyomja meg és tartsa nyomva a csempéket az átrendezéséhez</string>
+ <string name="quick_settings_edit_label">Csempék szerkesztése</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Szerkesztési csempe nem távolítható el</string>
+ <string name="qs_tiles_reset_confirmation">Gyors beállítások csempéinek visszaállítása alapértelmezett konfigurációra?</string>
+ <string name="quick_settings_tile_reset_to_default">Visszaállítás az alapértelmezett elrendezésre</string>
+ <string name="quick_settings_title_header">Fejléc</string>
+ <string name="quick_settings_title_tiles">Csempék</string>
+ <string name="quick_settings_title_show_weather">Időjárás megjelenítése</string>
+ <string name="quick_settings_title_show_brightness_slider">Fényerő csúszka megjelenítése</string>
+ <string name="quick_settings_title_enlarge_first_row">Első sor nagyítása</string>
+ <string name="screen_pinning_description_no_navbar">Ez a nézetben tartja, amíg a rögzítést fel nem oldja. Érintse meg és tartsa nyomva a Vissza gombot a rögzítés feloldásához.</string>
+ <string name="quick_settings_custom_tile_detail_title">Egyéni csempe</string>
+ <string name="quick_settings_remove">Csempe eltávolítása</string>
+ <string name="quick_settings_network_adb_label">ADB hálózaton keresztül</string>
+ <string name="quick_settings_compass_label">Iránytű</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Rendszer profilok</string>
+ <string name="quick_settings_profiles_off">Profilok letiltva</string>
+ <string name="quick_settings_heads_up_label">Lebegő értesítés</string>
+ <string name="quick_settings_battery_saver_label">Akkumulátor kímélő</string>
+ <string name="quick_settings_caffeine_label">Caffeine</string>
+ <string name="accessibility_quick_settings_sync_off">Szinkronizálás ki.</string>
+ <string name="accessibility_quick_settings_sync_on">Szinkronizálás be.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Szinkronizálás kikapcsolva.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Szinkronizálás bekapcsolva.</string>
+ <string name="quick_settings_sync_label">Szinkronizálás</string>
+ <string name="quick_settings_volume_panel_label">Hangerőszabályzás</string>
+ <string name="quick_settings_usb_tether_label">USB megosztás</string>
+ <string name="quick_settings_screen_timeout_detail_title">Képernyő időkorlátja</string>
+ <string name="quick_settings_lockscreen_label">Képernyő zárolás</string>
+ <string name="quick_settings_ambient_display_label">Környezeti kijelző</string>
+ <string name="quick_settings_lockscreen_label_enforced">A képernyő zárolásának kényszerítése</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Profil által letiltva</string>
+ <string name="accessibility_quick_settings_screen_timeout">Képernyő időkorlát: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Képernyő időkorlátja megváltoztatva: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Akkumulátor mód</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Akkumulátor mód: energiatakarékos.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Akkumulátor mód: kiegyensúlyozott.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Akkumulátor mód: teljesítménycentrikus.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Akkumulátor mód: hatékony mód.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Akkumulátor mód: teljesítmény mód.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Akkumulátor mód energiatakarékosra változtatva.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Akkumulátor mód kiegyensúlyozottra változtatva.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Akkumulátor mód teljesítménycentrikusra változtatva.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Akkumulátor mód átváltva hatékony módra.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Akkumulátor mód átváltva teljesítmény módra.</string>
+ <string name="quick_settings_performance_profile_detail_title">Akkumulátor mód</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Képernyőzár ki.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Képernyőzár be.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Képernyőzár kikapcsolva.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Képernyőzár bekapcsolva.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Környezeti kijelző ki.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Környezeti kijelző be.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Környezeti kijelző kikapcsolva.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Környezeti kijelző bekapcsolva.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Lebegő értesítés ki.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Lebegő értesítés be.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Lebegő értesítés kikapcsolva.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Lebegő értesítés bekapcsolva.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Caffeine ki.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Caffeine be.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Akkumulátor kímélő ki.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Akkumulátor kímélő be.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Akkumulátor kímélő kikapcsolva.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Akkumulátor kímélő bekapcsolva.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamikus csempe</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Következő riasztás</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME választó</string>
+ <string name="dynamic_qs_tile_su_label">Rendszergazda hozzáférés</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay ki.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automatikus mód.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: nappali mód.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: éjszakai mód.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: szabadtéri mód.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay kikapcsolva.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay automatikus módra változtatva.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay nappali módra változtatva.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay éjszakai módra változtatva.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay szabadtéri módra változtatva.</string>
+ <string name="quick_settings_title_advanced_location">Bővített helymeghatározás</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Helymeghatározás jelentése: energiatakarékos.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Helymeghatározás jelentése: csak GPS.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Helymeghatározás jelentése: nagyon pontos.</string>
+ <string name="quick_settings_location_detail_title">Helymeghatározási módok</string>
+ <string name="quick_settings_location_battery_saving_label">Energiatakarékos</string>
+ <string name="quick_settings_location_gps_only_label">Csak készülék</string>
+ <string name="quick_settings_location_high_accuracy_label">Nagy pontosság</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Helymeghatározás jelentése energiatakarékosra változtatva.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Helymeghatározás jelentése csak GPS-re változtatva.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Helymeghatározás jelentése nagyon pontosra változtatva.</string>
+ <string name="quick_settings_tiles_category_system">Rendszer csempék</string>
+ <string name="quick_settings_tiles_add_tiles">Csempe hozzáadása</string>
+ <string name="hotspot_apm_message">Nem lehet csatlakozni a mobil hálózatokra, míg a repülőgép üzemmód engedélyezve van. Tiltsa le a repülőgép üzemmódot és próbálja újra.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Zseblámpa bekapcsolva</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Kikapcsoláshoz érintse meg</string>
+</resources>
diff --git a/packages/SystemUI/res/values-in/cm_arrays.xml b/packages/SystemUI/res/values-in/cm_arrays.xml
new file mode 100644
index 0000000..be24560
--- /dev/null
+++ b/packages/SystemUI/res/values-in/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>U</item>
+ <item>TL</item>
+ <item>T</item>
+ <item>TG</item>
+ <item>S</item>
+ <item>BD</item>
+ <item>B</item>
+ <item>BL</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-in/cm_strings.xml b/packages/SystemUI/res/values-in/cm_strings.xml
new file mode 100644
index 0000000..f7c1570
--- /dev/null
+++ b/packages/SystemUI/res/values-in/cm_strings.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Geser ke kanan untuk %1$s</string>
+ <string name="right_shortcut_hint">Geser ke kiri untuk %1$s</string>
+ <string name="select_application">Pilih aplikasi</string>
+ <string name="lockscreen_choose_action_title">Pilih tindakan</string>
+ <string name="lockscreen_none_target">Tidak Ada</string>
+ <string name="navbar_dialog_title">Pilih tindakan untuk ditambahkan</string>
+ <string name="navbar_home_button">Tombol home</string>
+ <string name="navbar_recent_button">Tombol recent</string>
+ <string name="navbar_search_button">Tombol cari</string>
+ <string name="navbar_back_button">Tombol kembali</string>
+ <string name="navbar_empty_button">Tombol kosong</string>
+ <string name="navbar_menu_conditional_button">Tombol menu (sembunyi otomatis)</string>
+ <string name="navbar_menu_always_button">Tombol menu (selalu tampil)</string>
+ <string name="navbar_menu_big_button">Tombol menu</string>
+ <string name="accessibility_dpad_left">Kursor kiri</string>
+ <string name="accessibility_dpad_right">Kursor kanan</string>
+ <string name="advanced_dev_option_wipe_app">Hapus data aplikasi</string>
+ <string name="advanced_dev_option_force_stop">Paksa berhenti</string>
+ <string name="advanced_dev_option_uninstall">Copot pemasangan</string>
+ <string name="accessibility_quick_settings_profiles_off">Profil mati.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profil dimatikan.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil diubah menjadi <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Menginisialisasi\u2026</string>
+ <string name="screen_pinning_description_no_navbar">Hal ini membuatnya tetap dalam pandangan sampai anda melepas sematan. Sentuh dan tahan tombol kembali untuk melepas sematan.</string>
+ <string name="quick_settings_custom_tile_detail_title">Tile kustom</string>
+ <string name="quick_settings_remove">Hapus tile</string>
+ <string name="quick_settings_network_adb_label">ADB melalui jaringan</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Profil sistem</string>
+ <string name="quick_settings_profiles_off">Profil dinonaktifkan</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="accessibility_quick_settings_sync_off">Singkron mati.</string>
+ <string name="accessibility_quick_settings_sync_on">Singkron aktif.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Singkron dimatikan.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Singkron diaktifkan.</string>
+ <string name="quick_settings_sync_label">Singkron</string>
+ <string name="quick_settings_usb_tether_label">Peranggitan USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Waktu layar mati</string>
+ <string name="quick_settings_lockscreen_label">Kunci layar</string>
+ <string name="quick_settings_ambient_display_label">Tampilan Ambient</string>
+ <string name="quick_settings_lockscreen_label_enforced">Kunci layar diterapkan</string>
+ <string name="accessibility_quick_settings_screen_timeout">Batas waktu layar: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Batas waktu layar diubah menjadi <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Modus baterai: modus hemat daya.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Modus Baterai: modus seimbang.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Modus Baterai: Modus Performa.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Modus baterai diubah menjadi modus hemat daya.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Modus baterai diubah menjadi modus seimbang.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Modus baterai diubah menjadi modus performa.</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Kunci layar mati.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Kunci layar aktif.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Kunci layar dimatikan.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Kunci layar diaktifkan.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Tampilan Ambient nonaktif.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Tampilan Ambient aktif.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Tampilan Ambient dinonaktifkan.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Tampilan Ambient diaktifkan.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up nonaktif.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up aktif.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up dinonaktifkan.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up diaktifkan.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Petak Dinamis</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Alarm selanjutnya</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Pemilih IME</string>
+ <string name="dynamic_qs_tile_su_label">Akses Root</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay mati.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modus otomatis.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modus pagi.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modus malam.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modus luar ruangan.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay dimatikan.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay diubah menjadi modus otomatis.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay diubah menjadi modus pagi.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay diubah menjadi modus malam.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay diubah menjadi modus luar ruangan.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Laporan Lokasi: mode hemat baterai.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Laporan Lokasi: hanya mode sensor.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Laporan Lokasi: mode akurasi tinggi.</string>
+ <string name="quick_settings_location_detail_title">Mode lokasi</string>
+ <string name="quick_settings_location_battery_saving_label">Hemat baterai</string>
+ <string name="quick_settings_location_gps_only_label">Hanya perangkat</string>
+ <string name="quick_settings_location_high_accuracy_label">Akurasi tinggi</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Pelaporan lokasi diubah menjadi modus hemat baterai.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Pelaporan lokasi diubah menjadi modus hanya sensor.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Pelaporan lokasi diubah menjadi modus akurasi tinggi.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-it/cm_arrays.xml b/packages/SystemUI/res/values-it/cm_arrays.xml
new file mode 100644
index 0000000..cb6fbec
--- /dev/null
+++ b/packages/SystemUI/res/values-it/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-it/cm_strings.xml b/packages/SystemUI/res/values-it/cm_strings.xml
new file mode 100644
index 0000000..bc2e384
--- /dev/null
+++ b/packages/SystemUI/res/values-it/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Scorri a destra per %1$s</string>
+ <string name="right_shortcut_hint">Scorri a sinistra per %1$s</string>
+ <string name="lockscreen_message">Tocca un\'icona alla sinistra per riassegnare un collegamento alla schermata di sblocco.</string>
+ <string name="lockscreen_default_target">Predefinito</string>
+ <string name="select_application">Seleziona applicazione</string>
+ <string name="lockscreen_choose_action_title">Scegli un\'azione</string>
+ <string name="lockscreen_none_target">Nessuno</string>
+ <string name="navbar_dialog_title">Azione da associare</string>
+ <string name="navbar_home_button">Pulsante Home</string>
+ <string name="navbar_recent_button">Pulsante Recenti</string>
+ <string name="navbar_search_button">Pulsante Cerca</string>
+ <string name="navbar_back_button">Pulsante Indietro</string>
+ <string name="navbar_empty_button">Pulsante vuoto</string>
+ <string name="navbar_menu_conditional_button">Pulsante Menu (automatico)</string>
+ <string name="navbar_menu_always_button">Pulsante Menu (fisso)</string>
+ <string name="navbar_menu_big_button">Pulsante Menu</string>
+ <string name="accessibility_dpad_left">Cursore a sinistra</string>
+ <string name="accessibility_dpad_right">Cursore a destra</string>
+ <string name="advanced_dev_option_wipe_app">Cancella dati</string>
+ <string name="advanced_dev_option_force_stop">Arresto forzato</string>
+ <string name="advanced_dev_option_uninstall">Disinstalla</string>
+ <string name="accessibility_notification_brightness">Luminosità</string>
+ <string name="accessibility_quick_settings_profiles_off">Profili OFF.</string>
+ <string name="accessibility_quick_settings_profiles">Profilo: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profili disattivati.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profilo cambiato in <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inizializzazione\u2026</string>
+ <string name="led_notification_title">Impostazioni luci</string>
+ <string name="led_notification_text">Luce notifica attivata dalle impostazioni</string>
+ <string name="qs_tile_edit_header_instruction">Premi e trascina i tile per riordinarli</string>
+ <string name="quick_settings_edit_label">Modifica tile</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Non puoi rimuovere Modifica tile</string>
+ <string name="qs_tiles_reset_confirmation">Ripristinare la configurazione dei tiles predefinita?</string>
+ <string name="quick_settings_tile_reset_to_default">Ripristina il layout predefinito</string>
+ <string name="quick_settings_title_header">Intestazione</string>
+ <string name="quick_settings_title_tiles">Tile</string>
+ <string name="quick_settings_title_show_weather">Mostra meteo</string>
+ <string name="quick_settings_title_show_brightness_slider">Visualizza selettore luminosità</string>
+ <string name="quick_settings_title_enlarge_first_row">Allarga la prima riga</string>
+ <string name="screen_pinning_description_no_navbar">Tienilo in vista fino a quando non sblocchi. Tieni premuto il tasto Indietro per sbloccare.</string>
+ <string name="quick_settings_custom_tile_detail_title">Tile personalizzato</string>
+ <string name="quick_settings_remove">Rimuovi tile</string>
+ <string name="quick_settings_network_adb_label">ADB attraverso la rete</string>
+ <string name="quick_settings_compass_label">Bussola</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Profili di sistema</string>
+ <string name="quick_settings_profiles_off">Profili disattivati</string>
+ <string name="quick_settings_heads_up_label">Heads Up</string>
+ <string name="quick_settings_battery_saver_label">Risparmio batteria</string>
+ <string name="quick_settings_caffeine_label">Caffeina</string>
+ <string name="accessibility_quick_settings_sync_off">Sincronia OFF</string>
+ <string name="accessibility_quick_settings_sync_on">Sincronia ON.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sincronizzazione spenta.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sincronizzazione attivata.</string>
+ <string name="quick_settings_sync_label">Sincronizzazione</string>
+ <string name="quick_settings_volume_panel_label">Pannello volume</string>
+ <string name="quick_settings_usb_tether_label">Tethering USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Sospensione schermo</string>
+ <string name="quick_settings_lockscreen_label">Schermata di blocco</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Schermata di blocco forzata</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Disattivato da profilo</string>
+ <string name="accessibility_quick_settings_screen_timeout">Sospensione schermo: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Sospensione schermo cambiato in <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Modalità batteria</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Modalità batteria: modalità risparmio energetico.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Modalità batteria: modalità bilanciato.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Modalità batteria: modalità prestazioni.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Modalità batteria: modalità efficienza.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Modalità batteria: modalità prestazioni.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Modalità batteria cambiato in risparmio energetico.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Modalità batteria cambiato in modalità bilanciato.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Modalità batteria cambiato in modalità prestazioni.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">La batteria è ora in modalità efficienza.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">La batteria è ora in modalità prestazioni.</string>
+ <string name="quick_settings_performance_profile_detail_title">Modalità batteria</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Blocco schermo OFF.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Blocco schermo ON.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Blocco schermo disattivato.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Blocco schermo attivato.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display disattivato.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display attivato.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient display disattivato.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display attivato.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads Up disattivato.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads Up attivo.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads Up disattivato.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads Up attivato.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Caffeina off.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Caffeina on.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Risparmio batteria OFF.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Risparmio batteria ON.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Risparmio batteria disattivato.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Risparmio batteria attivato.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Tile dinamici</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Prossima sveglia</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Selettore IME</string>
+ <string name="dynamic_qs_tile_su_label">Accesso root</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay OFF.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modalità automatica.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modalità giorno.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modalità notte.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modalità esterno.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay disattivato.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay cambiato in modalità automatica.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay cambiato in modalità giorno.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay cambiato in modalità notte.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay cambiato in modalità esterno.</string>
+ <string name="quick_settings_title_advanced_location">Localizzazione avanzata</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Geolocalizzazione: modalità risparmio batteria.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Geolocalizzazione: modalità solo sensori.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Geolocalizzazione: modalità alta precisione.</string>
+ <string name="quick_settings_location_detail_title">Geolocalizzazione</string>
+ <string name="quick_settings_location_battery_saving_label">Risparmio batteria</string>
+ <string name="quick_settings_location_gps_only_label">Solo dispositivo</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precisione</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Segnalatore posizione cambiato in modalità risparmio batteria.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Segnalatore posizione cambiato in modalità solo sensori.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Segnalatore posizione cambiato in modalità alta precisione.</string>
+ <string name="quick_settings_tiles_category_system">Tile di sistema</string>
+ <string name="quick_settings_tiles_add_tiles">Aggiungi tile</string>
+ <string name="hotspot_apm_message">Impossibile connettersi alle reti mobili quando la modalità aereo è attiva. Disattiva la modalità aereo e riprova.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Torcia accesa</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Tocca per spegnere</string>
+</resources>
diff --git a/packages/SystemUI/res/values-iw/cm_arrays.xml b/packages/SystemUI/res/values-iw/cm_arrays.xml
new file mode 100644
index 0000000..ecf2e20
--- /dev/null
+++ b/packages/SystemUI/res/values-iw/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>צפ\'</item>
+ <item>צפ\'-מז\'</item>
+ <item>מז\'</item>
+ <item>דר\'-מז\'</item>
+ <item>דר\'</item>
+ <item>דר\'-מע\'</item>
+ <item>מע\'</item>
+ <item>צפ\'-מע\'</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-iw/cm_strings.xml b/packages/SystemUI/res/values-iw/cm_strings.xml
new file mode 100644
index 0000000..0975891
--- /dev/null
+++ b/packages/SystemUI/res/values-iw/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">החלק ימינה בשביל %1$s</string>
+ <string name="right_shortcut_hint">החלק שמאלה בשביל %1$s</string>
+ <string name="lockscreen_message">הקש על סמל בצד שמאל או ימין כדי להקצות מחדש קיצור דרך של מסך הנעילה.</string>
+ <string name="lockscreen_default_target">ברירת מחדל</string>
+ <string name="select_application">בחר יישום</string>
+ <string name="lockscreen_choose_action_title">בחר פעולה</string>
+ <string name="lockscreen_none_target">ללא</string>
+ <string name="navbar_dialog_title">בחר את הפעולה להקצאה</string>
+ <string name="navbar_home_button">לחצן הבית</string>
+ <string name="navbar_recent_button">לחצן יישומים אחרונים</string>
+ <string name="navbar_search_button">לחצן חיפוש</string>
+ <string name="navbar_back_button">לחצן \"הקודם\"</string>
+ <string name="navbar_empty_button">לחצן ריק</string>
+ <string name="navbar_menu_conditional_button">לחצן התפריט (הסתר אוטומטית)</string>
+ <string name="navbar_menu_always_button">לחצן התפריט (הצג תמיד)</string>
+ <string name="navbar_menu_big_button">לחצן התפריט</string>
+ <string name="accessibility_dpad_left">סמן שמאלה</string>
+ <string name="accessibility_dpad_right">סמן ימינה</string>
+ <string name="advanced_dev_option_wipe_app">מחק נתוני יישום</string>
+ <string name="advanced_dev_option_force_stop">אלץ עצירה</string>
+ <string name="advanced_dev_option_uninstall">הסרה</string>
+ <string name="accessibility_notification_brightness">בהירות נורית</string>
+ <string name="accessibility_quick_settings_profiles_off">פרופילים כבויים.</string>
+ <string name="accessibility_quick_settings_profiles">פרופיל: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">פרופילים כובו.</string>
+ <string name="accessibility_quick_settings_profiles_changed">פרופיל שונה ל-<xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">מאתחל\u2026</string>
+ <string name="led_notification_title">הגדרות נורית</string>
+ <string name="led_notification_text">נורית LED מופעלת בידי ההגדרות</string>
+ <string name="qs_tile_edit_header_instruction">יש לגעת ולהחזיק את האריחים לסידור מחדש</string>
+ <string name="quick_settings_edit_label">ערוך אריחים</string>
+ <string name="quick_settings_cannot_delete_edit_tile">לא ניתן למחוק את אריח העריכה</string>
+ <string name="qs_tiles_reset_confirmation">האם לאפס את אריחי ההגדרות המהירות לברירת המחדל?</string>
+ <string name="quick_settings_tile_reset_to_default">איפוס לפריסת ברירת המחדל</string>
+ <string name="quick_settings_title_header">כותרת</string>
+ <string name="quick_settings_title_tiles">אריחים</string>
+ <string name="quick_settings_title_show_weather">הצג מזג אוויר</string>
+ <string name="quick_settings_title_show_brightness_slider">הצג מד בהירות</string>
+ <string name="quick_settings_title_enlarge_first_row">הגדל את השורה הראשונה</string>
+ <string name="screen_pinning_description_no_navbar">פעולה זאת תשמור אותו מוצג עד שתבטל את ההצמדה. לחץ והחזק את כפתור \"הקודם\" כדי לבטל את ההצמדה.</string>
+ <string name="quick_settings_custom_tile_detail_title">אריח מותאם אישית</string>
+ <string name="quick_settings_remove">הסר אריח</string>
+ <string name="quick_settings_network_adb_label">ADB דרך רשת</string>
+ <string name="quick_settings_compass_label">מצפן</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">פרופילי מערכת</string>
+ <string name="quick_settings_profiles_off">פרופילים מושבתים</string>
+ <string name="quick_settings_heads_up_label">התראות קופצת</string>
+ <string name="quick_settings_battery_saver_label">שומר סוללה</string>
+ <string name="quick_settings_caffeine_label">קפאין</string>
+ <string name="accessibility_quick_settings_sync_off">סנכרון כבוי.</string>
+ <string name="accessibility_quick_settings_sync_on">סנכרון פעיל.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">סנכרון כובה.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">סנכרון הופעל.</string>
+ <string name="quick_settings_sync_label">סנכרון</string>
+ <string name="quick_settings_volume_panel_label">לוח עוצמות שמע</string>
+ <string name="quick_settings_usb_tether_label">קשירת USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">משך זמן מסך</string>
+ <string name="quick_settings_lockscreen_label">מסך נעילה</string>
+ <string name="quick_settings_ambient_display_label">התראות ברקע</string>
+ <string name="quick_settings_lockscreen_label_enforced">מסך הנעילה נאכף</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">מושבת על ידי הפרופיל</string>
+ <string name="accessibility_quick_settings_screen_timeout">משך זמן מסך: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">משך זמן מסך השתנה ל-<xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">מצב סוללה</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">מצב סוללה: מצב חיסכון סוללה.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">מצב סוללה: מצב מאוזן.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">מצב סוללה: מצב ביצועים.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">מצב סוללה: מצב יעילות.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">מצב סוללה: מצב מהיר.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">מצב הסוללה שונה למצב חיסכון סוללה.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">מצב הסוללה שונה למצב מאוזן.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">מצב הסוללה שונה למצב ביצועים.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">מצב סוללה שונה למצב יעילות.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">מצב סוללה שונה למצב מהיר.</string>
+ <string name="quick_settings_performance_profile_detail_title">מצב סוללה</string>
+ <string name="accessibility_quick_settings_lock_screen_off">מסך נעילה כבוי.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">מסך נעילה פעיל.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">מסך נעילה כובה.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">מסך נעילה הופעל.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">תצוגת התראות ברקע כבויה.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">תצוגת התראות ברקע פעילה.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">תצוגת התראות ברקע כובתה.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">תצוגת התראות ברקע הופעלה.</string>
+ <string name="accessibility_quick_settings_heads_up_off">התראות קופצות כבויות.</string>
+ <string name="accessibility_quick_settings_heads_up_on">התראות קופצות פעילות.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">התראות קופצות כובו.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">התראות קופצות הופעלו.</string>
+ <string name="accessibility_quick_settings_caffeine_off">קפאין כבוי.</string>
+ <string name="accessibility_quick_settings_caffeine_on">קפאין פועל.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">שומר סוללה כבוי.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">שומר סוללה פעיל.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">שומר סוללה כובה.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">שומר סוללה הופעל.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">אריחים דינמיים</string>
+ <string name="dynamic_qs_tile_next_alarm_label">ההתראה הבאה</string>
+ <string name="dynamic_qs_tile_ime_selector_label">בורר שיטות קלט</string>
+ <string name="dynamic_qs_tile_su_label">גישת שורש</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay כבוי.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: מצב אוטומטי.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: מצב יום.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: מצב לילה.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: מצב חוץ.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay כובה.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay שונה למצב אוטומטי.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay שונה למצב יום.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay שונה למצב לילה.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay שונה למצב חוץ.</string>
+ <string name="quick_settings_title_advanced_location">שלושה מצבי מיקום</string>
+ <string name="accessibility_quick_settings_location_battery_saving">דיווח מיקום: מצב חיסכון בסוללה.</string>
+ <string name="accessibility_quick_settings_location_gps_only">דיווח מיקום: מצב חיישנים בלבד.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">דיווח מיקום: מצב רמת דיוק גבוהה.</string>
+ <string name="quick_settings_location_detail_title">מצב מיקום</string>
+ <string name="quick_settings_location_battery_saving_label">חיסכון בסוללה</string>
+ <string name="quick_settings_location_gps_only_label">התקן בלבד</string>
+ <string name="quick_settings_location_high_accuracy_label">דיוק מרבי</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">דיווח מיקום השתנה למצב חיסכון סוללה.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">דיווח מיקום השתנה למצב חיישנים בלבד.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">דיווח מיקום השתנה למצב דיוק גבוה.</string>
+ <string name="quick_settings_tiles_category_system">אריחי מערכת</string>
+ <string name="quick_settings_tiles_add_tiles">הוסף אריח</string>
+ <string name="hotspot_apm_message">לא ניתן להתחבר לרשתות סלולריות כאשר מצב טיסה פעיל. בטל את מצב הטיסה ונסה שנית.</string>
+ <string name="quick_settings_tile_flashlight_not_title">פנס מופעל</string>
+ <string name="quick_settings_tile_flashlight_not_summary">לחץ לכיבוי</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ja/cm_arrays.xml b/packages/SystemUI/res/values-ja/cm_arrays.xml
new file mode 100644
index 0000000..ca179e3
--- /dev/null
+++ b/packages/SystemUI/res/values-ja/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>北</item>
+ <item>北東</item>
+ <item>東</item>
+ <item>南東</item>
+ <item>南</item>
+ <item>南西</item>
+ <item>西</item>
+ <item>北西</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ja/cm_strings.xml b/packages/SystemUI/res/values-ja/cm_strings.xml
new file mode 100644
index 0000000..910111e
--- /dev/null
+++ b/packages/SystemUI/res/values-ja/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">右にスワイプして%1$s</string>
+ <string name="right_shortcut_hint">左にスワイプして%1$s</string>
+ <string name="lockscreen_message">左右のアイコンをタップしてロック画面のショートカットを変更します。</string>
+ <string name="lockscreen_default_target">デフォルト</string>
+ <string name="select_application">アプリケーションを選択</string>
+ <string name="lockscreen_choose_action_title">動作を選択</string>
+ <string name="lockscreen_none_target">なし</string>
+ <string name="navbar_dialog_title">設定する動作を選択</string>
+ <string name="navbar_home_button">ホームボタン</string>
+ <string name="navbar_recent_button">最近使ったアプリボタン</string>
+ <string name="navbar_search_button">検索ボタン</string>
+ <string name="navbar_back_button">戻るボタン</string>
+ <string name="navbar_empty_button">ボタンなし</string>
+ <string name="navbar_menu_conditional_button">メニューボタン(自動非表示)</string>
+ <string name="navbar_menu_always_button">メニューボタン(常時表示)</string>
+ <string name="navbar_menu_big_button">メニューボタン</string>
+ <string name="accessibility_dpad_left">カーソルを左へ</string>
+ <string name="accessibility_dpad_right">カーソルを右へ</string>
+ <string name="advanced_dev_option_wipe_app">アプリのデータを消去</string>
+ <string name="advanced_dev_option_force_stop">強制停止</string>
+ <string name="advanced_dev_option_uninstall">アンインストール</string>
+ <string name="accessibility_notification_brightness">ライトの明るさ</string>
+ <string name="accessibility_quick_settings_profiles_off">プロファイルはOFFです。</string>
+ <string name="accessibility_quick_settings_profiles">プロファイル: <xliff:g id="profile" example="Default">%s</xliff:g>です。</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">プロファイルがOFFになりました。</string>
+ <string name="accessibility_quick_settings_profiles_changed">プロファイルが<xliff:g id="profile" example="Default">%s</xliff:g>に変更されました。</string>
+ <string name="quick_settings_compass_init">初期化中\u2026</string>
+ <string name="led_notification_title">ライトの設定</string>
+ <string name="led_notification_text">LEDライトが設定によって有効になっています</string>
+ <string name="qs_tile_edit_header_instruction">タイルを長押しして並べ替えます</string>
+ <string name="quick_settings_edit_label">タイルを編集</string>
+ <string name="quick_settings_cannot_delete_edit_tile">編集タイルは削除できません</string>
+ <string name="qs_tiles_reset_confirmation">クイック設定タイルをデフォルトの設定に戻しますか?</string>
+ <string name="quick_settings_tile_reset_to_default">デフォルトのレイアウトに戻す</string>
+ <string name="quick_settings_title_header">ヘッダー</string>
+ <string name="quick_settings_title_tiles">タイル</string>
+ <string name="quick_settings_title_show_weather">天気を表示</string>
+ <string name="quick_settings_title_show_brightness_slider">明るさスライダーを表示</string>
+ <string name="quick_settings_title_enlarge_first_row">1行目を拡大</string>
+ <string name="screen_pinning_description_no_navbar">固定を解除するまで表示し続けます。固定を解除するには戻るボタンを押し続けます。</string>
+ <string name="quick_settings_custom_tile_detail_title">カスタムタイル</string>
+ <string name="quick_settings_remove">タイルを削除</string>
+ <string name="quick_settings_network_adb_label">ネットワーク経由のADB</string>
+ <string name="quick_settings_compass_label">コンパス</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">システムプロファイル</string>
+ <string name="quick_settings_profiles_off">プロファイル無効</string>
+ <string name="quick_settings_heads_up_label">ヘッドアップ</string>
+ <string name="quick_settings_battery_saver_label">バッテリーセーバー</string>
+ <string name="quick_settings_caffeine_label">カフェイン</string>
+ <string name="accessibility_quick_settings_sync_off">同期はOFFです。</string>
+ <string name="accessibility_quick_settings_sync_on">同期はONです。</string>
+ <string name="accessibility_quick_settings_sync_changed_off">同期がOFFになりました。</string>
+ <string name="accessibility_quick_settings_sync_changed_on">同期がONになりました。</string>
+ <string name="quick_settings_sync_label">同期</string>
+ <string name="quick_settings_volume_panel_label">音量パネル</string>
+ <string name="quick_settings_usb_tether_label">USBテザリング</string>
+ <string name="quick_settings_screen_timeout_detail_title">画面のタイムアウト</string>
+ <string name="quick_settings_lockscreen_label">ロック画面</string>
+ <string name="quick_settings_ambient_display_label">アンビエント表示</string>
+ <string name="quick_settings_lockscreen_label_enforced">ロック画面強制</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">プロファイルによって無効になっています</string>
+ <string name="accessibility_quick_settings_screen_timeout">画面のタイムアウト: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>です。</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">画面のタイムアウトが<xliff:g id="timeout" example="30 seconds">%s</xliff:g>に変更されました。</string>
+ <string name="qs_tile_performance">バッテリーモード</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">バッテリーモード: 省電力モードです。</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">バッテリーモード: バランスモードです。</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">バッテリーモード: パフォーマンスモードです。</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">バッテリーモード: 効率モードです。</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">バッテリーモード: クイックモードです。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">バッテリーモードが省電力モードに変更されました。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">バッテリーモードがバランスモードに変更されました。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">バッテリーモードがパフォーマンスモードに変更されました。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">バッテリーモードが効率モードに変更されました。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">バッテリーモードがクイックモードに変更されました。</string>
+ <string name="quick_settings_performance_profile_detail_title">バッテリーモード</string>
+ <string name="accessibility_quick_settings_lock_screen_off">ロック画面はOFFです。</string>
+ <string name="accessibility_quick_settings_lock_screen_on">ロック画面はONです。</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">ロック画面がOFFになりました。</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">ロック画面がONになりました。</string>
+ <string name="accessibility_quick_settings_ambient_display_off">アンビエント表示はOFFです。</string>
+ <string name="accessibility_quick_settings_ambient_display_on">アンビエント表示はONです。</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">アンビエント表示がOFFになりました。</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">アンビエント表示がONになりました。</string>
+ <string name="accessibility_quick_settings_heads_up_off">ヘッドアップはOFFです。</string>
+ <string name="accessibility_quick_settings_heads_up_on">ヘッドアップはONです。</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">ヘッドアップがOFFになりました。</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">ヘッドアップがONになりました。</string>
+ <string name="accessibility_quick_settings_caffeine_off">カフェインはOFFです。</string>
+ <string name="accessibility_quick_settings_caffeine_on">カフェインはONです。</string>
+ <string name="accessibility_quick_settings_battery_saver_off">バッテリーセーバーはOFFです。</string>
+ <string name="accessibility_quick_settings_battery_saver_on">バッテリーセーバーはONです。</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">バッテリーセーバーがOFFになりました。</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">バッテリーセーバーがONになりました。</string>
+ <string name="quick_settings_dynamic_tile_detail_title">自動タイル</string>
+ <string name="dynamic_qs_tile_next_alarm_label">次のアラーム</string>
+ <string name="dynamic_qs_tile_ime_selector_label">入力方法の選択</string>
+ <string name="dynamic_qs_tile_su_label">ルートアクセス</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplayはOFFです。</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: 自動モードです。</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: 昼モードです。</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: 夜モードです。</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: 屋外モードです。</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplayがOFFになりました。</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplayが自動モードに変更されました。</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplayが昼モードに変更されました。</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplayが夜モードに変更されました。</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplayが屋外モードに変更されました。</string>
+ <string name="quick_settings_title_advanced_location">3種類の位置情報</string>
+ <string name="accessibility_quick_settings_location_battery_saving">位置情報レポート: バッテリー節約モードです。</string>
+ <string name="accessibility_quick_settings_location_gps_only">位置情報レポート: 端末のみモードです。</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">位置情報レポート: 高精度モードです。</string>
+ <string name="quick_settings_location_detail_title">位置情報モード</string>
+ <string name="quick_settings_location_battery_saving_label">バッテリー節約</string>
+ <string name="quick_settings_location_gps_only_label">端末のみ</string>
+ <string name="quick_settings_location_high_accuracy_label">高精度</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">位置情報レポートがバッテリー節約モードに変更されました。</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">位置情報レポートが端末のみモードに変更されました。</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">位置情報レポートが高精度モードに変更されました。</string>
+ <string name="quick_settings_tiles_category_system">システムのタイル</string>
+ <string name="quick_settings_tiles_add_tiles">タイルを追加</string>
+ <string name="hotspot_apm_message">機内モードが有効になっている間はモバイルネットワークに接続することはできません。機内モードを無効にしてから再試行してください。</string>
+ <string name="quick_settings_tile_flashlight_not_title">フラッシュライトが点灯しています</string>
+ <string name="quick_settings_tile_flashlight_not_summary">タップして消灯する</string>
+</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/cm_arrays.xml b/packages/SystemUI/res/values-kn-rIN/cm_arrays.xml
new file mode 100644
index 0000000..00014e3
--- /dev/null
+++ b/packages/SystemUI/res/values-kn-rIN/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>ಉ</item>
+ <item>ಈಶಾ</item>
+ <item>ಪೂ</item>
+ <item>ಆಗ್ನೇ</item>
+ <item>ದ</item>
+ <item>ನೈಋ</item>
+ <item>ಪ</item>
+ <item>ವಾಯು</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/cm_strings.xml b/packages/SystemUI/res/values-kn-rIN/cm_strings.xml
new file mode 100644
index 0000000..396cb3a
--- /dev/null
+++ b/packages/SystemUI/res/values-kn-rIN/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">%1$sಗಾಗಿ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ</string>
+ <string name="right_shortcut_hint">%1$sಗಾಗಿ ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ</string>
+ <string name="select_application">ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ</string>
+ <string name="lockscreen_choose_action_title">ಕ್ರಿಯೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
+ <string name="lockscreen_none_target">ಶೂನ್ಯ</string>
+ <string name="navbar_dialog_title">ನಿಯೋಜಿಸಲು ಕ್ರಿಯೆಯನ್ನು ಆರಿಸಿ</string>
+ <string name="navbar_home_button">ಹೋಮ್ ಬಟನ್</string>
+ <string name="navbar_recent_button">ಇತ್ತೀಚಿನ ಬಟನ್</string>
+ <string name="navbar_search_button">ಹುಡುಕು ಬಟನ್</string>
+ <string name="navbar_back_button">ಹಿಂದಕ್ಕೆ ಬಟನ್</string>
+ <string name="navbar_empty_button">ಖಾಲಿ ಬಟನ್</string>
+ <string name="navbar_menu_conditional_button">ಮೆನು (ಸ್ವಯಂಮರೆಯಾಗು) ಬಟನ್</string>
+ <string name="navbar_menu_always_button">ಮೆನು (ಎಂದಿಗುಪ್ರದರ್ಶಿಸು) ಬಟನ್</string>
+ <string name="navbar_menu_big_button">ಮೆನು ಬಟನ್</string>
+ <string name="accessibility_dpad_left">ಕರ್ಸರ್ ಎಡ</string>
+ <string name="accessibility_dpad_right">ಕರ್ಸರ್ ಬಲ</string>
+ <string name="advanced_dev_option_wipe_app">ಆಪ್ ಡೇಟಾ ಅಳಿಸಿಹಾಕು</string>
+ <string name="advanced_dev_option_force_stop">ಬಲವಂತ ನಿಲ್ಲಿಸು</string>
+ <string name="advanced_dev_option_uninstall">ಅಸ್ಥಾಪಿಸು</string>
+ <string name="accessibility_quick_settings_profiles_off">ಪ್ರೊಫೈಲ್ಸ್ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_profiles">ಪ್ರೊಫೈಲ್: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">ಪ್ರೊಫೈಲ್ಸ್ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_profiles_changed">ಪ್ರೊಫೈಲ್ <xliff:g id="profile" example="Default">%s</xliff:g>ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="quick_settings_compass_init">ಆರಂಭಿಸುತ್ತಿದೆ\u2026</string>
+ <string name="screen_pinning_description_no_navbar">ಇದು ನೀವು ಅನ್‍ಪಿನ್ ಮಾಡುವವರೆಗೂ ವೀಕ್ಷಣೆಯಲ್ಲಿ ಇಡುತ್ತದೆ. ಅನ್‍ಪಿನ್ ಮಾಡಲು ಬ್ಯಾಕ್ ಬಟನ್ ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿಯಿರಿ.</string>
+ <string name="quick_settings_custom_tile_detail_title">ಕಸ್ಟಮ್ ಟೈಲ್</string>
+ <string name="quick_settings_remove">ಟೈಲ್ ತೆಗೆ</string>
+ <string name="quick_settings_network_adb_label">ನೆಟ್‍ವರ್ಕ್ ಮೇಲೆ ಎಡಿಬಿ</string>
+ <string name="quick_settings_compass_label">ದಿಕ್ಸೂಚಿ</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">ಸಿಸ್ಟಂ ಪ್ರೊಫೈಲ್ಸ್</string>
+ <string name="quick_settings_profiles_off">ಪ್ರೊಫೈಲ್ಸ್ ನಿಷ್ಕ್ರೀಯಗೊಂಡಿದೆ</string>
+ <string name="quick_settings_heads_up_label">ಹೆಡ್ಸ್ ಅಪ್</string>
+ <string name="quick_settings_battery_saver_label">ಬ್ಯಾಟರಿ ಉಳಿತಾಯ</string>
+ <string name="accessibility_quick_settings_sync_off">ಸಿಂಕ್ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_sync_on">ಸಿಂಕ್ ಆನ್.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">ಸಿಂಕ್ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">ಸಿಂಕ್ ಆನ್ ಆಗಿದೆ.</string>
+ <string name="quick_settings_sync_label">ಸಿಂಕ್</string>
+ <string name="quick_settings_volume_panel_label">ವಾಲ್ಯೂಂ ಪ್ಯಾನೆಲ್</string>
+ <string name="quick_settings_usb_tether_label">ಯುಎಸ್‍ಬಿ ಟೆಥರಿಂಗ್</string>
+ <string name="quick_settings_screen_timeout_detail_title">ಪರದೆ ಅವಧಿಸಮಾಪ್ತಿ</string>
+ <string name="quick_settings_lockscreen_label">ಲಾಕ್ ಪರದೆ</string>
+ <string name="quick_settings_ambient_display_label">ಆವರಿಸಿದ ಪರದೆ</string>
+ <string name="quick_settings_lockscreen_label_enforced">ಒತ್ತಾಯವಾದ ಲಾಕ್ ಪರದೆ</string>
+ <string name="accessibility_quick_settings_screen_timeout">ಪರದೆ ಅವಧಿಸಮಾಪ್ತಿ: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">ಪರದೆ ಅವಧಿಸಮಾಪ್ತಿ <xliff:g id="timeout" example="30 seconds">%s</xliff:g>ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="qs_tile_performance">ಬ್ಯಾಟರಿ ಮೋಡ್</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">ಬ್ಯಾಟರಿ ಮೋಡ್: ವಿದ್ಯುತ್ ಉಳಿತಾಯ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">ಬ್ಯಾಟರಿ ಮೋಡ್: ಸಮತೋಲಿತ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">ಬ್ಯಾಟರಿ ಮೋಡ್: ಪರ್ಫಾರ್ಮೆನ್ಸ್ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">ಬ್ಯಾಟರಿ ಮೋಡ್: ದಕ್ಷತೆ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">ಬ್ಯಾಟರಿ ಮೋಡ್: ತ್ವರಿತ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">ಬ್ಯಾಟರಿ ಮೋಡ್ ವಿದ್ಯುತ್ ಉಳಿತಾಯ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">ಬ್ಯಾಟರಿ ಮೋಡ್ ಸಮತೋಲಿತ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">ಬ್ಯಾಟರಿ ಮೋಡ್ ಪರ್ಫಾರ್ಮೆನ್ಸ್ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">ಬ್ಯಾಟರಿ ಮೋಡ್ ದಕ್ಷತೆ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">ಬ್ಯಾಟರಿ ಮೋಡ್ ತ್ವರಿತ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="quick_settings_performance_profile_detail_title">ಬ್ಯಾಟರಿ ಮೋಡ್</string>
+ <string name="accessibility_quick_settings_lock_screen_off">ಲಾಕ್ ಪರದೆ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">ಲಾಕ್ ಪರದೆ ಆನ್.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">ಲಾಕ್ ಪರದೆ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">ಲಾಕ್ ಪರದೆ ಆನ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">ಆವರಿಸಿದ ಪರದೆ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">ಆವರಿಸಿದ ಪರದೆ ಆನ್.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">ಆವರಿಸಿದ ಪರದೆ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">ಆವರಿಸಿದ ಪರದೆ ಆನ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_heads_up_off">ಹೆಡ್ಸ್ ಅಪ್ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_heads_up_on">ಹೆಡ್ಸ್ ಅಪ್ ಆನ್.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">ಹೆಡ್ಸ್ ಅಪ್ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">ಹೆಡ್ಸ್ ಅಪ್ ಆನ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆನ್.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆನ್ ಆಗಿದೆ.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">ಕ್ರಿಯಾತ್ಮಕ ಟೈಲ್</string>
+ <string name="dynamic_qs_tile_next_alarm_label">ಮುಂದಿನ ಅಲಾರಂ</string>
+ <string name="dynamic_qs_tile_ime_selector_label">ಇಎಂಇ ಆಯ್ಕೆ</string>
+ <string name="dynamic_qs_tile_su_label">ರೂಟ್ ಪ್ರವೇಶ</string>
+ <string name="accessibility_quick_settings_live_display_off">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ ಆಫ್.</string>
+ <string name="accessibility_quick_settings_live_display_auto">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ: ಸ್ವಯಂ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_live_display_day">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ: ಹಗಲು ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_live_display_night">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ: ರಾತ್ರಿ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ: ಹೊರಾಂಗಣ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ ಆಫ್ ಆಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ ಸ್ವಯಂ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ ಹಗಲು ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ ರಾತ್ರಿ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">ಲೈವ್‍ಡಿಸ್ಪ್ಲೇ ಹೊರಾಂಗಣ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">ಸ್ಥಳ ವರದಿಸಲ್ಲಿಸುವಿಕೆ: ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_location_gps_only">ಸ್ಥಳ ವರದಿ ಸಲ್ಲಿಸುವಿಕೆ: ಸಂವೇದಕಗಳು ಮಾತ್ರ ಮೋಡ್.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">ಸ್ಥಳ ವರದಿಸಲ್ಲಿಸುವಿಕೆ: ಗರಿಷ್ಟ ನಿಖರತೆ ಮೋಡ್.</string>
+ <string name="quick_settings_location_detail_title">ಸ್ಥಳ ಮೋಡ್</string>
+ <string name="quick_settings_location_battery_saving_label">ಬ್ಯಾಟರಿ ಉಳಿತಾಯ</string>
+ <string name="quick_settings_location_gps_only_label">ಸಾಧನ ಮಾತ್ರ</string>
+ <string name="quick_settings_location_high_accuracy_label">ಗರಿಷ್ಠ ನಿಖರತೆ</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">ಸ್ಥಳ ವರದಿಸಲ್ಲಿಸುವಿಕೆ ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">ಸ್ಥಳ ವರದಿಸಲ್ಲಿಸುವಿಕೆ ಸಂವೇದಕಗಳು ಮಾತ್ರ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">ಸ್ಥಳ ವರದಿಸಲ್ಲಿಸುವಿಕೆ ಗರಿಷ್ಠ ನಿಖರತೆ ಮೋಡ್‍ಗೆ ಬದಲಾಗಿದೆ.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ko/cm_arrays.xml b/packages/SystemUI/res/values-ko/cm_arrays.xml
new file mode 100644
index 0000000..e5df957
--- /dev/null
+++ b/packages/SystemUI/res/values-ko/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>북</item>
+ <item>북동</item>
+ <item>동</item>
+ <item>남동</item>
+ <item>남</item>
+ <item>남서</item>
+ <item>서</item>
+ <item>북서</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ko/cm_strings.xml b/packages/SystemUI/res/values-ko/cm_strings.xml
new file mode 100644
index 0000000..42509f9
--- /dev/null
+++ b/packages/SystemUI/res/values-ko/cm_strings.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">오른쪽으로 밀어서 %1$s</string>
+ <string name="right_shortcut_hint">왼쪽으로 밀어서 %1$s</string>
+ <string name="lockscreen_message">잠금화면 바로가기를 다시 지정하려면 왼쪽이나 오른쪽의 아이콘을 탭하세요.</string>
+ <string name="lockscreen_default_target">기본</string>
+ <string name="select_application">앱 선택</string>
+ <string name="lockscreen_choose_action_title">동작 선택</string>
+ <string name="lockscreen_none_target">없음</string>
+ <string name="navbar_dialog_title">할당할 작업을 선택</string>
+ <string name="navbar_home_button">홈 버튼</string>
+ <string name="navbar_recent_button">최근 버튼</string>
+ <string name="navbar_search_button">검색 버튼</string>
+ <string name="navbar_back_button">뒤로 버튼</string>
+ <string name="navbar_empty_button">버튼 없음</string>
+ <string name="navbar_menu_conditional_button">메뉴 버튼 (자동 숨기기)</string>
+ <string name="navbar_menu_always_button">메뉴 버튼 (항상 보이기)</string>
+ <string name="navbar_menu_big_button">메뉴 버튼</string>
+ <string name="accessibility_dpad_left">커서 왼쪽</string>
+ <string name="accessibility_dpad_right">커서 오른쪽</string>
+ <string name="advanced_dev_option_wipe_app">앱 데이터 삭제</string>
+ <string name="advanced_dev_option_force_stop">강제 종료</string>
+ <string name="advanced_dev_option_uninstall">제거</string>
+ <string name="accessibility_notification_brightness">조명 밝기</string>
+ <string name="accessibility_quick_settings_profiles_off">프로필 꺼짐.</string>
+ <string name="accessibility_quick_settings_profiles">현재 프로필: <xliff:g id="profile" example="Default">%s</xliff:g></string>
+ <string name="accessibility_quick_settings_profiles_changed_off">프로필이 이제 꺼짐.</string>
+ <string name="accessibility_quick_settings_profiles_changed">프로필이 <xliff:g id="profile" example="Default">%s</xliff:g>으(로) 바뀜.</string>
+ <string name="quick_settings_compass_init">초기화 중\u2026</string>
+ <string name="led_notification_title">조명 설정</string>
+ <string name="led_notification_text">설정에 의해 LED 전등이 활성화됨</string>
+ <string name="qs_tile_edit_header_instruction">다시 배치하려면 타일을 길게 누름</string>
+ <string name="quick_settings_edit_label">타일 편집</string>
+ <string name="quick_settings_cannot_delete_edit_tile">타일 편집 삭제 불가</string>
+ <string name="qs_tiles_reset_confirmation">빠른 설정 타일 배치를 기본으로 재설정</string>
+ <string name="quick_settings_tile_reset_to_default">기본 레이아웃으로 재설정</string>
+ <string name="quick_settings_title_header">헤더</string>
+ <string name="quick_settings_title_tiles">타일</string>
+ <string name="quick_settings_title_show_weather">날씨 표시</string>
+ <string name="quick_settings_title_show_brightness_slider">화면 밝기 조정 표시</string>
+ <string name="quick_settings_title_enlarge_first_row">첫번째 타일을 크게</string>
+ <string name="screen_pinning_description_no_navbar">고정을 해제할 때까지 계속 표시합니다. 뒤로 버튼을 계속 눌러 고정을 해제하세요.</string>
+ <string name="quick_settings_custom_tile_detail_title">개인설정 타일</string>
+ <string name="quick_settings_remove">타일 제거</string>
+ <string name="quick_settings_network_adb_label">네트워크 ADB</string>
+ <string name="quick_settings_compass_label">나침반</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">시스템 프로필</string>
+ <string name="quick_settings_profiles_off">프로필 사용 안 함</string>
+ <string name="quick_settings_heads_up_label">헤드업 알림</string>
+ <string name="quick_settings_battery_saver_label">배터리 절약</string>
+ <string name="accessibility_quick_settings_sync_off">동기화 꺼짐</string>
+ <string name="accessibility_quick_settings_sync_on">동기화 켜짐</string>
+ <string name="accessibility_quick_settings_sync_changed_off">동기화가 해제되었습니다.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">동기화가 설정되었습니다.</string>
+ <string name="quick_settings_sync_label">동기화</string>
+ <string name="quick_settings_volume_panel_label">볼륨 패널</string>
+ <string name="quick_settings_usb_tether_label">USB 테더링</string>
+ <string name="quick_settings_screen_timeout_detail_title">화면 자동 꺼짐</string>
+ <string name="quick_settings_lockscreen_label">잠금 화면</string>
+ <string name="quick_settings_ambient_display_label">절전 모드 자동 해제</string>
+ <string name="quick_settings_lockscreen_label_enforced">잠금 화면 사용됨</string>
+ <string name="accessibility_quick_settings_screen_timeout">화면 시간 제한: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">화면 시간 제한이 <xliff:g id="timeout" example="30 seconds">%s</xliff:g>으(로) 바뀜.</string>
+ <string name="qs_tile_performance">배터리 모드</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">배터리 모드: 전원 절약 모드.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">배터리 모드: 균형 모드.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">배터리 모드: 성능 모드.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">배터리 모드: 효율 모드.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">배터리 모드: 성능 모드.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">배터리 모드가 이제 절전 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">베터리 모드가 이제 균형 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">배터리 모드가 성능 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">배터리 모드가 효율 모드로 변경되었습니다.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">배터리 모드가 성능 모드로 변환되었습니다.</string>
+ <string name="quick_settings_performance_profile_detail_title">배터리 모드</string>
+ <string name="accessibility_quick_settings_lock_screen_off">잠금 화면 꺼짐.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">잠금 화면 켜짐.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">잠금 화면이 이제 꺼짐.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">잠금 화면이 이제 켜짐.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">절전 모드 자동 해제가 꺼짐.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">절전 모드 자동 해제가 켜짐.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">절전 모드 자동 해제가 꺼졌습니다.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">절전 모드 자동 해제가 켜졌습니다.</string>
+ <string name="accessibility_quick_settings_heads_up_off">헤드업 알림이 꺼짐.</string>
+ <string name="accessibility_quick_settings_heads_up_on">헤드업 알림이 켜짐.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">헤드업 알림이 꺼졌습니다.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">헤드업 알림이 켜졌습니다.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">배터리 절약 끔.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">배터리 절약 킴.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">배터리 절약이 꺼졌습니다.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">배터리 절약이 켜졌습니다.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">동적 타일</string>
+ <string name="dynamic_qs_tile_next_alarm_label">다음 알람</string>
+ <string name="dynamic_qs_tile_ime_selector_label">입력 방법 선택</string>
+ <string name="dynamic_qs_tile_su_label">루트 권한</string>
+ <string name="accessibility_quick_settings_live_display_off">라이브 디스플레이 꺼짐.</string>
+ <string name="accessibility_quick_settings_live_display_auto">라이브 디스플레이: 자동 모드.</string>
+ <string name="accessibility_quick_settings_live_display_day">라이브 디스플레이: 낮 모드.</string>
+ <string name="accessibility_quick_settings_live_display_night">라이브 디스플레이: 밤 모드.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">라이브 디스플레이: 야외 모드.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">라이브 디스플레이 꺼짐.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">라이브 디스플레이가 자동 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">라이브 디스플레이가 낮 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">라이브 디스플레이가 밤 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">라이브 디스플레이가 야외 모드로 바뀜.</string>
+ <string name="quick_settings_title_advanced_location">3가지 위치 설정</string>
+ <string name="accessibility_quick_settings_location_battery_saving">위치 보고: 배터리 절약 모드.</string>
+ <string name="accessibility_quick_settings_location_gps_only">위치 보고: 기기 전용 모드.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">위치 보고: 높은 정확성 모드.</string>
+ <string name="quick_settings_location_detail_title">위치 모드</string>
+ <string name="quick_settings_location_battery_saving_label">배터리 절약</string>
+ <string name="quick_settings_location_gps_only_label">기기 전용</string>
+ <string name="quick_settings_location_high_accuracy_label">높은 정확도</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">위치 보고가 배터리 절약 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">위치 보고가 기기 전용 모드로 바뀜.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">위치 보고가 높은 정확도 모드로 바뀜.</string>
+ <string name="quick_settings_tiles_category_system">시스템 타일</string>
+ <string name="quick_settings_tiles_add_tiles">타일 추가</string>
+ <string name="hotspot_apm_message">비행기 모드가 활성화되어 있어 셀룰러 네트워크에 연결할 수 없습니다. 비행기 모드를 해제하고 다시 시도하세요.</string>
+ <string name="quick_settings_tile_flashlight_not_title">손전등 켜짐</string>
+ <string name="quick_settings_tile_flashlight_not_summary">탭하여 끄기</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ku/cm_arrays.xml b/packages/SystemUI/res/values-ku/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-ku/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ku/cm_strings.xml b/packages/SystemUI/res/values-ku/cm_strings.xml
new file mode 100644
index 0000000..59f8c53
--- /dev/null
+++ b/packages/SystemUI/res/values-ku/cm_strings.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">رایکێشە بۆلای ڕاست بۆ %1$s</string>
+ <string name="right_shortcut_hint">ڕایکێشە بۆلای چەپ بۆ %1$s</string>
+ <string name="select_application">دیاریکردنی بەرنامە</string>
+ <string name="lockscreen_choose_action_title">چالاکیه‌ک هه‌ڵبژێره‌</string>
+ <string name="lockscreen_none_target">هیچیان</string>
+ <string name="navbar_dialog_title">کارێك هەڵبژێرە بۆ ئەنجام دان </string>
+ <string name="navbar_home_button">دوگمەی سەرەتا</string>
+ <string name="navbar_recent_button">دوگمەی پێشینە</string>
+ <string name="navbar_search_button">دوگمەی گەڕان</string>
+ <string name="navbar_back_button">دوگمەی گەڕانەوە</string>
+ <string name="navbar_empty_button">دوگمەی بەتاڵ</string>
+ <string name="navbar_menu_conditional_button">دوگمەی مینو (شاردنەوەی خۆکار) </string>
+ <string name="navbar_menu_always_button">دوگمەی مینو (نیشاندانی خۆکار) </string>
+ <string name="navbar_menu_big_button">دوگمەی مینو</string>
+ <string name="accessibility_dpad_left">جێنیشانده‌ر بۆ لای چه‌پ</string>
+ <string name="accessibility_dpad_right">جێنیشانده‌ر بۆ لای ڕاست</string>
+ <string name="advanced_dev_option_wipe_app">سڕینەوەی داواکاریەکانی بەرنامە</string>
+ <string name="advanced_dev_option_force_stop">وەستاندی بێهۆکار</string>
+ <string name="advanced_dev_option_uninstall">سڕینەوە</string>
+ <string name="quick_settings_compass_init">سه‌ره‌تایکردن\u2026</string>
+ <string name="screen_pinning_description_no_navbar">ئەمە لەسەر پیشاندان ئەمێنێتەوە تاوەکو لەیەکدادەبڕێن. دەستلێدە و دووگمەی دواوە هەڵبگرە بۆ لێدابڕان.</string>
+ <string name="quick_settings_custom_tile_detail_title">خشتەی دروستکراو</string>
+ <string name="quick_settings_remove">سڕینه‌وه‌ی خشتە</string>
+ <string name="quick_settings_network_adb_label">ADB لەڕێی تۆڕەوە</string>
+ <string name="quick_settings_compass_label">قیبلە نما</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">زانیاری تایبەتیەکانی سیستەم</string>
+ <string name="quick_settings_profiles_off">زانیاری تایبەتی ناچالاکە</string>
+ <string name="quick_settings_heads_up_label">فه‌رمووه‌کان</string>
+ <string name="quick_settings_usb_tether_label">گرتنەدەستی USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">کاتی شاشە</string>
+ <string name="quick_settings_lockscreen_label">قفڵی شاشە</string>
+ <string name="quick_settings_ambient_display_label">پیشاندەری دەوروبەر</string>
+ <string name="quick_settings_lockscreen_label_enforced">قفڵکردنی شاشە بەزۆر</string>
+ <string name="accessibility_quick_settings_location_battery_saving">دۆزینەوەی شوێن: شێوازی پاراستنی ووزە.</string>
+ <string name="accessibility_quick_settings_location_gps_only">دۆزینەوەی شوێن: تەنیا هەستەوەرەکان.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">دۆزینەوەی شوێن: شێوازی بەکارهێنانی تەواو.</string>
+ <string name="quick_settings_location_detail_title">شێوازی شوێن</string>
+ <string name="quick_settings_location_battery_saving_label">پاراستنی ووزە</string>
+ <string name="quick_settings_location_gps_only_label">تەنها ئامێر</string>
+ <string name="quick_settings_location_high_accuracy_label">بەکارهێنانی زۆر</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ku/strings.xml b/packages/SystemUI/res/values-ku/strings.xml
new file mode 100644
index 0000000..099eb52
--- /dev/null
+++ b/packages/SystemUI/res/values-ku/strings.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">سیستەم UI</string>
+ <string name="status_bar_clear_all_button">پاچالاککردن</string>
+ <string name="status_bar_recent_remove_item_title">لە لیستەکە بیسڕەوە</string>
+ <string name="status_bar_recent_inspect_item_title">زانیاری دەربارەی بەرنامە</string>
+ <string name="status_bar_accessibility_dismiss_recents">پشتگوێ خستنی بەرنامەی تازە</string>
+ <string name="status_bar_no_notifications_title">تێبینی نیە</string>
+ <string name="status_bar_ongoing_events_title">چونە</string>
+ <string name="status_bar_latest_events_title">تێبینی</string>
+ <string name="invalid_charger">USB پاڵپشتی ناکات .\nتەنها بارگەکەر بەکاربهێنە.</string>
+ <string name="battery_low_why">ڕێکخستنه‌کان</string>
+ <string name="battery_saver_confirmation_title">باتری پارێز چالاک ئەکەیت?</string>
+ <string name="battery_saver_confirmation_ok">کردنە کار</string>
+ <string name="battery_saver_start_action">باتری پارێز چالاک ئەکەیت</string>
+ <string name="status_bar_settings_settings_button">ڕێکخستن</string>
+ <string name="status_bar_settings_wifi_button">Wi-Fi</string>
+ <string name="status_bar_settings_auto_rotation">خۆکارانە-سوڕانەوەی شاشە</string>
+ <string name="status_bar_settings_mute_label">کپکردن</string>
+ <string name="status_bar_settings_auto_brightness_label">خۆکارانە</string>
+ <string name="status_bar_settings_notifications">ئاگادارییه‌کان</string>
+ <string name="bluetooth_tethered">بلوتوس تێزەر</string>
+ <string name="status_bar_input_method_settings_configure_input_methods">دامەزراندن ڕێگەکان</string>
+ <string name="status_bar_use_physical_keyboard">تەختەکلیلی فیزیکی</string>
+ <string name="usb_device_permission_prompt">ڕێگەدان بە بەرنامەکە <xliff:g id="application">%1$s</xliff:g> بۆ بەکارهێنانیUSB?</string>
+ <string name="usb_accessory_permission_prompt">ڕێگەدان بەبەرنامەکە <xliff:g id="application">%1$s</xliff:g> بەکارهێنانیUSB ?</string>
+ <string name="usb_device_confirm_prompt">چالاککردن <xliff:g id="activity">%1$s</xliff:g>کاتێک ئامێرەکە پەیوەندە بە USB?</string>
+ <string name="usb_accessory_confirm_prompt">کراوە <xliff:g id="activity">%1$s</xliff:g> کاتێک ئەو USB yیە پەیوەندکراوە?</string>
+ <string name="usb_accessory_uri_prompt">هیچ بەرنامەیەک دانەمەزراوە ئیش بکات لەسەر USB زیاتر فێربە دەربارەی <xliff:g id="url">%1$s</xliff:g></string>
+ <string name="title_usb_accessory">USB</string>
+ <string name="label_view">پیشاندان</string>
+ <string name="always_use_device">لە بنەڕەتەوە بەکاری بهێنە بۆ USB </string>
+ <string name="always_use_accessory">بنەڕەتی بەکاربهێنە بۆ USB</string>
+ <string name="usb_debugging_title">ڕێگە دان بە هەڵدۆزی USB?</string>
+ <string name="usb_debugging_message">چاپکەری پەنجە کلیل لە RSA :\n<xliff:g id="fingerprint">%1$s</xliff:g></string>
+ <string name="usb_debugging_always">هەمیشە ڕێگە بدە لەسەر ئەم کۆمپیوتەرە</string>
+ <string name="compat_mode_on">زوومکردن بۆ پڕ شاشە</string>
+ <string name="compat_mode_off">درێژبونەوە بۆ پڕشاشە</string>
+ <string name="screenshot_saving_ticker">پاشەکەوتکردنی وێنه‌ی شاشە\u2026</string>
+ <string name="screenshot_saving_title">پاشەکەوتکردنی شاشەوێنە\u2026</string>
+ <string name="screenshot_saving_text">وێنەی شاشەکە پاشەکەوتکرا.</string>
+ <string name="screenshot_saved_title">وێنەی شاشە گیرا.</string>
+ <string name="screenshot_saved_text">دەست لێدە بۆ پیشاندانی وێنەی شاشە.</string>
+ <string name="screenshot_failed_title">ناتوانێت وێنەی شاشەبگرێت.</string>
+ <string name="usb_preference_title">هەڵبژاردەی usb بۆ گواستنەوەی فایلەکان</string>
+ <string name="use_mtp_button_title">جێگیركردن وەکو لێدەرە ڕاگه‌یێنه‌کان(MTP)</string>
+ <string name="use_ptp_button_title">جێگیرکردن وەکو کامێرا(PTP)</string>
+ <string name="installer_cd_button_title">دامەزراندنی فایلەکان ئەندرۆید لەسەر ماک</string>
+ <string name="accessibility_back">گەڕانەوە</string>
+ <string name="accessibility_home">ماڵەوە</string>
+ <string name="accessibility_menu">پێڕست</string>
+ <string name="accessibility_recent">پیشاندانی گشتی</string>
+ <string name="accessibility_search_light">گەڕان</string>
+ <string name="accessibility_camera_button">کامێرا</string>
+ <string name="accessibility_phone_button">تەلەفۆن</string>
+ <string name="accessibility_unlock_button">کردنەوە</string>
+ <string name="unlock_label">كردنەوە</string>
+ <string name="phone_label">کردنەوەی تەلەفۆن</string>
+ <string name="camera_label">کردنەوەی کامێرا</string>
+ <string name="accessibility_compatibility_zoom_button">دوگمەی زومی توانای.</string>
+ <string name="accessibility_compatibility_zoom_example">زومکردن لە بچوکەوە بۆ شاشەی گەورە.</string>
+ <string name="accessibility_bluetooth_connected">بلوتوس پەیوەندکراوە.</string>
+ <string name="accessibility_bluetooth_disconnected">بلوتوس نەبەستراوە.</string>
+ <string name="accessibility_no_battery">باتری نیە.</string>
+ <string name="accessibility_battery_one_bar">شریتی یەک باتری.</string>
+ <string name="accessibility_battery_two_bars">دوو شریتی باتری.</string>
+ <string name="accessibility_battery_three_bars">سێ شریتی باتری.</string>
+ <string name="accessibility_battery_full">باتری پڕە.</string>
+ <string name="accessibility_no_phone">تەلەفۆن نیە.</string>
+ <string name="accessibility_phone_one_bar">شریتی یەک تەلەفۆن.</string>
+ <string name="accessibility_phone_two_bars">شریتی دوو تەلەفۆن.</string>
+ <string name="accessibility_phone_three_bars">شریتی سێ تەلەفۆن.</string>
+ <string name="accessibility_phone_signal_full">تەلەفۆن پڕ نیشانه‌.</string>
+ <string name="accessibility_no_data">داتای نیە.</string>
+ <string name="accessibility_data_one_bar">شریتی یەک داتا.</string>
+ <string name="accessibility_data_two_bars">شریتی دوو داتا.</string>
+ <string name="accessibility_data_three_bars">شریتی سێ دراوه.</string>
+ <string name="accessibility_data_signal_full">پڕ نیشانە داتا.</string>
+ <string name="accessibility_wifi_name">پەیوەندکراوە بە <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
+ <string name="accessibility_bluetooth_name">پەیوەندکراوە بە <xliff:g id="bluetooth" example="Car Audio">%s</xliff:g>.</string>
+ <string name="accessibility_no_wimax">نەخێر WiMAX.</string>
+ <string name="accessibility_wimax_one_bar">WiMAX یەک شریت.</string>
+ <string name="accessibility_wimax_two_bars">WiMAX یەک شریت.</string>
+ <string name="accessibility_wimax_three_bars">WiMAX سێ شریت.</string>
+ <string name="accessibility_wimax_signal_full">WiMAX پڕ نیشانە.</string>
+ <string name="accessibility_no_signal">نیشانە نیە.</string>
+ <string name="accessibility_not_connected">نەبەستراوەتەوە.</string>
+ <string name="accessibility_zero_bars">شریتی سفر.</string>
+ <string name="accessibility_one_bar">یەک شریت.</string>
+ <string name="accessibility_two_bars">دوو شریت.</string>
+ <string name="accessibility_three_bars">سێ شریت.</string>
+ <string name="accessibility_signal_full">پڕ نیشانە.</string>
+ <string name="accessibility_desc_on">چالاککردن.</string>
+ <string name="accessibility_desc_off">ناچالاککردن.</string>
+ <string name="accessibility_desc_connected">پەیوەندکرا.</string>
+ <string name="accessibility_desc_connecting">په‌یوه‌ندیكردن.</string>
+ <string name="accessibility_data_connection_gprs">GPRS</string>
+ <string name="accessibility_data_connection_1x">1 X</string>
+ <string name="accessibility_data_connection_hspa">HSPA</string>
+ <string name="accessibility_data_connection_3g">3G</string>
+ <string name="accessibility_data_connection_3.5g">3.5G</string>
+ <string name="accessibility_data_connection_4g">4G</string>
+ <string name="accessibility_data_connection_lte">LTE</string>
+ <string name="accessibility_data_connection_cdma">CDMA</string>
+ <string name="accessibility_data_connection_roaming">سوڕانەوە</string>
+ <string name="accessibility_data_connection_edge">لێوار</string>
+ <string name="accessibility_data_connection_wifi">Wi-Fi</string>
+ <string name="accessibility_no_sim">سیمکارتی تیا نیە.</string>
+ <string name="accessibility_bluetooth_tether">بلوتوس وایەر.</string>
+ <string name="accessibility_airplane_mode">باری فڕۆکە.</string>
+ <string name="accessibility_battery_level">باتری <xliff:g id="number">%d</xliff:g> لەسەدا.</string>
+ <string name="accessibility_settings_button">ڕێکخستنی سیستەم.</string>
+ <string name="accessibility_notifications_button">تێبینیه‌کان.</string>
+ <string name="accessibility_remove_notification">پاکردنەوەی تێبینیەکان.</string>
+ <string name="accessibility_gps_enabled">GPS چالاکرا.</string>
+ <string name="accessibility_gps_acquiring">GPS وەرگرتنی.</string>
+ <string name="accessibility_tty_enabled">TeleTypewriter چالاکرا.</string>
+ <string name="accessibility_ringer_vibrate">لەرینەوەی زەنگ.</string>
+ <string name="accessibility_ringer_silent">بێدەنگ زەنگ.</string>
+ <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> لەدەست چوو.</string>
+ <string name="accessibility_notification_dismissed">تێبینیەکە لەدەستچوو.</string>
+ <string name="accessibility_desc_notification_shade">سێبەری تێبینی.</string>
+ <string name="accessibility_desc_quick_settings">خێرا ڕێکخستن.</string>
+ <string name="accessibility_desc_lock_screen">قوفڵکردنی ڕوونما.</string>
+ <string name="accessibility_desc_settings">ڕێکخستنه‌کان</string>
+ <string name="accessibility_desc_recent_apps">پیشاندانی گشتی.</string>
+ <string name="accessibility_quick_settings_user">بەکارهێنەر <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_wifi_changed_off">کوژانەوەی وایفای.</string>
+ <string name="accessibility_quick_settings_wifi_changed_on">کردنەوەی وایفای.</string>
+ <string name="accessibility_quick_settings_mobile">مۆبایل <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_battery">باتری <xliff:g id="state" example="50% charging">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_airplane_off">کوژانەوەی باری فڕۆکە.</string>
+ <string name="accessibility_quick_settings_airplane_on">کردنەوەی باری فڕۆکە.</string>
+ <string name="accessibility_quick_settings_airplane_changed_off">باری فڕۆکە ناچالاکرا.</string>
+ <string name="accessibility_quick_settings_airplane_changed_on">باری فڕۆکە چالاکرا.</string>
+ <string name="accessibility_quick_settings_bluetooth_off">بلوتوس کوژایەوە.</string>
+ <string name="accessibility_quick_settings_bluetooth_on">چالاکردنی بلوتوس.</string>
+ <string name="accessibility_quick_settings_bluetooth_connecting">پەیوەندکردنی بلوتوس.</string>
+ <string name="accessibility_quick_settings_bluetooth_connected">بلوتوس پەیوەندکراوە.</string>
+ <string name="accessibility_quick_settings_bluetooth_changed_off">بلوتوس ناچالاکە.</string>
+ <string name="accessibility_quick_settings_bluetooth_changed_on">بلوتوس ناچالاکە.</string>
+ <string name="accessibility_quick_settings_location_off">کوژانەوەی ڕاپۆرتی ناوەکی.</string>
+ <string name="accessibility_quick_settings_location_on">کردنەوەی ڕاپۆرتی ناوەکی.</string>
+ <string name="accessibility_quick_settings_location_changed_off">ڕاپۆرتی ناوەکی کوژایەوە.</string>
+ <string name="accessibility_quick_settings_location_changed_on">ڕاپۆرتی ناوەکی چالاکرا.</string>
+ <string name="accessibility_quick_settings_alarm">دانانی بیرخەرەوە بۆ <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_close">داخستنی پەڕە.</string>
+ <string name="accessibility_quick_settings_more_time">کاتی زیاتر.</string>
+ <string name="accessibility_quick_settings_less_time">کاتی کەمتر.</string>
+ <string name="accessibility_quick_settings_flashlight_off">کوژانەوەی لایت.</string>
+ <string name="accessibility_quick_settings_flashlight_on">چالاکردنی لایت.</string>
+ <string name="status_bar_settings_signal_meter_disconnected">ئەنتەرنێت به‌ستنه‌وه نیە</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi بەستراوە</string>
+ <string name="gps_notification_searching_text">گەڕان بۆ GPS</string>
+ <string name="gps_notification_found_text">ناوچەکە دانراوە لە GPS</string>
+ <string name="accessibility_location_active">ناوچە داواکراوە بۆ چالاککردن</string>
+ <string name="accessibility_clear_all">پاکردنەوەی تێبنیەکان.</string>
+ <string name="accessibility_rotation_lock_off">شاشەکە خۆکارانە ئەخولێتەوە.</string>
+ <string name="accessibility_rotation_lock_on_landscape">شاشەکە بە لایە قوفڵ ئەبێت.</string>
+ <string name="accessibility_rotation_lock_on_portrait">شاشەکە بە ڕاستە قوفڵ ئەبێت.</string>
+ <string name="dessert_case">شیرینی بابەت</string>
+ <string name="start_dreams">ڕۆژی خەون</string>
+ <string name="ethernet_label">ئێسه‌رنێت</string>
+ <string name="quick_settings_bluetooth_label">بلوتوس</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label">بلوتوس (<xliff:g id="number">%d</xliff:g> ئامێرەکان)</string>
+ <string name="quick_settings_bluetooth_off_label">بلوتوس کوژاوه‌یه‌</string>
+ <string name="quick_settings_brightness_label">ڕوناکی</string>
+ <string name="quick_settings_ime_label">دانانی ڕێگە</string>
+ <string name="quick_settings_location_label">ناوچه‌</string>
+ <string name="quick_settings_location_off_label">کوژاندنەوەی شوێندۆزەرەوە</string>
+ <string name="quick_settings_media_device_label">ئامێری ڕاگه‌یێنه‌کان </string>
+ <string name="quick_settings_rssi_label">RSSI</string>
+ <string name="quick_settings_rssi_emergency_only">ته‌نها په‌یوه‌ندی كتوپڕ</string>
+ <string name="quick_settings_settings_label">ڕێکخستنه‌کان</string>
+ <string name="quick_settings_time_label">کات</string>
+ <string name="quick_settings_user_label">من</string>
+ <string name="quick_settings_wifi_label">Wi-Fi</string>
+ <string name="quick_settings_wifi_not_connected">نەبەستراوە</string>
+ <string name="quick_settings_wifi_no_network">تۆڕ نیە</string>
+ <string name="quick_settings_wifi_off_label">Wi-Fi ناچالاکه‌</string>
+ <string name="quick_settings_brightness_dialog_title">ڕۆشنایی</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label">خۆکارانە</string>
+ <string name="quick_settings_connecting">په‌یوه‌ندیكردن...</string>
+ <string name="quick_settings_notifications_label">تێبینیه‌کان</string>
+ <string name="quick_settings_flashlight_label">لایتی فلاش</string>
+ <string name="battery_meter_very_low_overlay_symbol">!</string>
+ <string name="ssl_ca_cert_warning">تۆڕه‌که‌ مۆنیته‌ر کراوه‌</string>
+ <string name="status_bar_ethernet">ئێسه‌رنێت</string>
+ <string name="status_bar_airplane">شێوازی فڕۆکە</string>
+ <string name="enable_bluetooth_confirmation_ok">کردنە کار</string>
+</resources>
diff --git a/packages/SystemUI/res/values-land/cm_dimens.xml b/packages/SystemUI/res/values-land/cm_dimens.xml
new file mode 100644
index 0000000..e996f02
--- /dev/null
+++ b/packages/SystemUI/res/values-land/cm_dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2015, The CyanogenMod 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.
+*/
+-->
+<resources>
+ <dimen name="phone_height">210dp</dimen>
+ <dimen name="phone_width">420dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-lb/cm_arrays.xml b/packages/SystemUI/res/values-lb/cm_arrays.xml
new file mode 100644
index 0000000..b156d8e
--- /dev/null
+++ b/packages/SystemUI/res/values-lb/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NO</item>
+ <item>O</item>
+ <item>SO</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-lb/cm_strings.xml b/packages/SystemUI/res/values-lb/cm_strings.xml
new file mode 100644
index 0000000..d69da04
--- /dev/null
+++ b/packages/SystemUI/res/values-lb/cm_strings.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">No riets wësche fir %1$s</string>
+ <string name="right_shortcut_hint">No lénks wësche fir %1$s</string>
+ <string name="lockscreen_message">Dréck e Symbol op der lénkser oder rietser Säit fir d\'Spärschierm-Ofkierzungen nei ze definéieren.</string>
+ <string name="lockscreen_default_target">Standard</string>
+ <string name="select_application">App auswielen</string>
+ <string name="lockscreen_choose_action_title">Aktioun auswielen</string>
+ <string name="lockscreen_none_target">Keen</string>
+ <string name="navbar_dialog_title">Funktioun zouweisen</string>
+ <string name="navbar_home_button">Startsäit-Knäppchen</string>
+ <string name="navbar_recent_button">Verlafknäppchen</string>
+ <string name="navbar_search_button">Sichknäppchen</string>
+ <string name="navbar_back_button">Zréckknäppchen</string>
+ <string name="navbar_empty_button">Net beluecht</string>
+ <string name="navbar_menu_conditional_button">Knäppche fir de Menü automatesch ze verstoppen</string>
+ <string name="navbar_menu_always_button">Knäppche fir de Menü ëmmer unzeweisen</string>
+ <string name="navbar_menu_big_button">Menüknäppchen</string>
+ <string name="accessibility_dpad_left">Cursor lénks</string>
+ <string name="accessibility_dpad_right">Cursor riets</string>
+ <string name="advanced_dev_option_wipe_app">Applikatiounsdate läschen</string>
+ <string name="advanced_dev_option_force_stop">Zoumaachen zwéngen</string>
+ <string name="advanced_dev_option_uninstall">Desinstalléieren</string>
+ <string name="accessibility_notification_brightness">Hellegkeet</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiller aus.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiller ausgeschalt.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil op <xliff:g id="profile" example="Default">%s</xliff:g> geännert.</string>
+ <string name="quick_settings_compass_init">Initialiséieren\u2026</string>
+ <string name="led_notification_title">Hellegkeetsastellungen</string>
+ <string name="led_notification_text">Notifikatiounsluucht duerch Astellungen aktivéieren</string>
+ <string name="qs_tile_edit_header_instruction">Dréck an haalt d\'Kachelen, fir se nei zouzeuerdnen</string>
+ <string name="quick_settings_edit_label">Kachelen änneren</string>
+ <string name="quick_settings_cannot_delete_edit_tile">\"Kachelen änneren\" kann net geläscht ginn</string>
+ <string name="qs_tiles_reset_confirmation">Kachele vun de Séieren Astellungen op de Standardlayout zrécksetzen?</string>
+ <string name="quick_settings_tile_reset_to_default">Zréck op den Standardlayout setzen</string>
+ <string name="quick_settings_title_header">Entête</string>
+ <string name="quick_settings_title_tiles">Kachelen</string>
+ <string name="quick_settings_title_show_weather">Wieder uweisen</string>
+ <string name="quick_settings_title_enlarge_first_row">Éischt Rei vergréisseren</string>
+ <string name="screen_pinning_description_no_navbar">Doduerch bleift d\'App visibel bis se lassgeléist gëtt. Dréck den Zréck-Knäppchen an hal e gedréckt fir d\'App lasszeléisen.</string>
+ <string name="quick_settings_custom_tile_detail_title">Eege Kachel</string>
+ <string name="quick_settings_remove">Kachel läschen</string>
+ <string name="quick_settings_network_adb_label">ADB iwwer Netzwierk</string>
+ <string name="quick_settings_compass_label">Kompass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systemprofiller</string>
+ <string name="quick_settings_profiles_off">Profiller desaktivéiert</string>
+ <string name="quick_settings_heads_up_label">Pop-Up-Notifikatiounen</string>
+ <string name="quick_settings_battery_saver_label">Akkuschouner</string>
+ <string name="accessibility_quick_settings_sync_off">Synchronisatioun aus.</string>
+ <string name="accessibility_quick_settings_sync_on">Synchronisatioun un.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchronisatioun ausgeschalt.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchronisatioun ugeschalt.</string>
+ <string name="quick_settings_sync_label">Synchronisatioun</string>
+ <string name="quick_settings_volume_panel_label">Lautstäerktpanneau</string>
+ <string name="quick_settings_usb_tether_label">USB-Tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Schierm-Timeout</string>
+ <string name="quick_settings_lockscreen_label">Schiermspär</string>
+ <string name="quick_settings_ambient_display_label">Ambiente Schierm</string>
+ <string name="quick_settings_lockscreen_label_enforced">Spärschierm forcéiert</string>
+ <string name="accessibility_quick_settings_screen_timeout">Rouzoustand no <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Zäit bis zum Rouzoustand op <xliff:g id="timeout" example="30 seconds">%s</xliff:g> geännert.</string>
+ <string name="qs_tile_performance">Akkumodus</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Akkumodus: Energie spueren.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Akkumodus: Equilibréiert.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Akkumodus: Héich Leeschtung.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Akkumodus: effiziente Modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Akkumodus: séiere Modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Akkumodus op \"Energie spueren\" geännert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Akkumodus op \"Equilibréiert\" geännert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Akkumodus op \"Héich Leeschtung\" geännert.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Akkumodus geännert op den effiziente Modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Akkumodus geännert op de séiere Modus.</string>
+ <string name="quick_settings_performance_profile_detail_title">Akkumodus</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Schiermspär aus.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Schiermspär un.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Schiermspär ausgeschalt.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Schiermspär ugeschalt.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambiente Schierm aus.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambiente Schierm un.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambiente Schierm ausgeschalt.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambiente Schierm ugeschalt.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Pop-Up-Notifikatiounen aus.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Pop-Up-Notifikatiounen un.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Pop-Up-Notifikatiounen ausgeschalt.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Pop-Up-Notifikatiounen ugeschalt.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Akkuschouner aus.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Akkuschouner un.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Akkuschouner ausgeschalt.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Akkuschouner ugeschalt.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamesch Kachelen</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Nächste Wecker</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Method fir anzeginn</string>
+ <string name="dynamic_qs_tile_su_label">Root-Zougrëff</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay aus.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: Automatesch.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: Dag.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: Nuecht.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: Dobaussen.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay ausgeschalt.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay-Modus op \"Automatesch\" geännert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay-Modus op \"Dag\" geännert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay-Modus op \"Nuecht\" geännert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay-Modus op \"Dobaussen\" geännert.</string>
+ <string name="quick_settings_title_advanced_location">Standuert mat dräi Zoustänn</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Standuertbericht: Akku spueren.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Standuertbericht: Just Sensoren.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Standuertbericht: Héich Genauegkeet.</string>
+ <string name="quick_settings_location_detail_title">Standuertmodus</string>
+ <string name="quick_settings_location_battery_saving_label">Akku spueren</string>
+ <string name="quick_settings_location_gps_only_label">Just Apparat</string>
+ <string name="quick_settings_location_high_accuracy_label">Héich Genauegkeet</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Standuertbericht op \"Akku spueren\" geännert.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Standuertbericht op \"Just Sensoren\" geännert.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Standuertbericht op \"Héich Genauegkeet\" geännert.</string>
+ <string name="quick_settings_tiles_category_system">System-Kachelen</string>
+ <string name="quick_settings_tiles_add_tiles">Kachelen dobäisetzen</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lb/strings.xml b/packages/SystemUI/res/values-lb/strings.xml
new file mode 100644
index 0000000..2a11376
--- /dev/null
+++ b/packages/SystemUI/res/values-lb/strings.xml
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">System-UI</string>
+ <string name="status_bar_clear_all_button">Eidel maachen</string>
+ <string name="status_bar_recent_remove_item_title">Aus der Lëscht eraushuelen</string>
+ <string name="status_bar_recent_inspect_item_title">App-Info</string>
+ <string name="status_bar_no_recent_apps">Deng rezent Schiermer erschéngen hei</string>
+ <string name="status_bar_accessibility_dismiss_recents">Rezent Appe verwerfen</string>
+ <string name="status_bar_no_notifications_title">Keng Notifikatiounen</string>
+ <string name="status_bar_ongoing_events_title">Am Gaang</string>
+ <string name="status_bar_latest_events_title">Notifikatiounen</string>
+ <string name="battery_low_title">Akku niddreg</string>
+ <string name="battery_low_percent_format"><xliff:g id="percentage">%s</xliff:g> iwwreg</string>
+ <string name="battery_low_percent_format_saver_started"><xliff:g id="percentage">%s</xliff:g> iwwreg. Akkuschouner ass un.</string>
+ <string name="invalid_charger">Oplueden iwwer USB net ënnerstëtzt.\nBenotz just de matgeliwwerten Oplueder.</string>
+ <string name="invalid_charger_title">Oplueden iwwer USB net ënnerstëtzt.</string>
+ <string name="invalid_charger_text">Benotz just de matgeliwwerten Oplueder.</string>
+ <string name="battery_low_why">Astellungen</string>
+ <string name="battery_saver_confirmation_title">Akkuschouner uschalten?</string>
+ <string name="battery_saver_confirmation_ok">Uschalten</string>
+ <string name="battery_saver_start_action">Akkuschouner uschalten</string>
+ <string name="status_bar_settings_settings_button">Astellungen</string>
+ <string name="status_bar_settings_wifi_button">WLAN</string>
+ <string name="status_bar_settings_auto_rotation">Schierm automatesch rotéieren</string>
+ <string name="status_bar_settings_mute_label">STOMM</string>
+ <string name="status_bar_settings_auto_brightness_label">AUTO</string>
+ <string name="status_bar_settings_notifications">Notifikatiounen</string>
+ <string name="bluetooth_tethered">Bluetooth ugebonnen</string>
+ <string name="status_bar_input_method_settings_configure_input_methods">Methode fir anzeginn astellen</string>
+ <string name="status_bar_use_physical_keyboard">Physesch Tastatur</string>
+ <string name="usb_device_permission_prompt">Der App <xliff:g id="application">%1$s</xliff:g> erlaben op den USB-Apparat zouzegräifen?</string>
+ <string name="usb_accessory_permission_prompt">Der App <xliff:g id="application">%1$s</xliff:g> erlaben op den USB-Accessoire zouzegräifen?</string>
+ <string name="usb_device_confirm_prompt"><xliff:g id="activity">%1$s</xliff:g> opmaache wann dësen USB-Apparat connectéiert ass?</string>
+ <string name="usb_accessory_confirm_prompt"><xliff:g id="activity">%1$s</xliff:g> opmaache wann dësen USB-Accessoire connectéiert ass?</string>
+ <string name="usb_accessory_uri_prompt">Keng installéiert App fir dësen USB-Accessoire. Méi iwwer dësen Accessoire gewuer ginn op <xliff:g id="url">%1$s</xliff:g></string>
+ <string name="title_usb_accessory">USB-Accessoire</string>
+ <string name="label_view">Ukucken</string>
+ <string name="always_use_device">Standartméisseg fir dësen USB-Apparat benotzen</string>
+ <string name="always_use_accessory">Standartméisseg fir dësen USB-Accessoire benotzen</string>
+ <string name="usb_debugging_title">USB-Debugging erlaben?</string>
+ <string name="usb_debugging_message">Den RSA-Fangerofdrock vum Computer ass:\n<xliff:g id="fingerprint">%1$s</xliff:g></string>
+ <string name="usb_debugging_always">Ëmmer vun dësem Computer erlaben</string>
+ <string name="compat_mode_on">Zoom op d\'Schiermgréisst</string>
+ <string name="compat_mode_off">Un d\'Schiermgréisst upassen</string>
+ <string name="screenshot_saving_ticker">Schiermfoto gëtt gespäichert\u2026</string>
+ <string name="screenshot_saving_title">Schiermfoto gëtt gespäichert\u2026</string>
+ <string name="screenshot_saving_text">Schiermfoto gëtt gespäichert.</string>
+ <string name="screenshot_saved_title">Schiermfoto opgeholl.</string>
+ <string name="screenshot_saved_text">Drécke fir d\'Schiermfoto unzekucken.</string>
+ <string name="screenshot_failed_title">Schiermfoto konnt net opgeholl ginn.</string>
+ <string name="screenshot_failed_text">Wéinst ze wéineg Späicherplaz oder wéinst feelender Berechtegung ka keng Schiermfoto gespäichert ginn.</string>
+ <string name="usb_preference_title">USB-Dateiiwwerdroungsoptiounen</string>
+ <string name="use_mtp_button_title">Als Medieplayer (MTP) abannen</string>
+ <string name="use_ptp_button_title">Als Kamera (PTP) abannen</string>
+ <string name="installer_cd_button_title">D\'Fichiersiwwerdroungs-App fir Android um Mac installéieren</string>
+ <string name="accessibility_back">Zréck</string>
+ <string name="accessibility_home">Heem</string>
+ <string name="accessibility_menu">Menü</string>
+ <string name="accessibility_recent">Iwwersiicht</string>
+ <string name="accessibility_search_light">Sichen</string>
+ <string name="accessibility_camera_button">Fotoapparat</string>
+ <string name="accessibility_phone_button">Telefon</string>
+ <string name="accessibility_unlock_button">Entspären</string>
+ <string name="unlock_label">entspären</string>
+ <string name="phone_label">Telefon opmaachen</string>
+ <string name="camera_label">Kamera opmaachen</string>
+ <string name="accessibility_compatibility_zoom_button">Knäppche fir de Kompatibilitéitszoom.</string>
+ <string name="accessibility_compatibility_zoom_example">Zoom op ee méi grousse Schierm.</string>
+ <string name="accessibility_bluetooth_connected">Bluetooth connectéiert.</string>
+ <string name="accessibility_bluetooth_disconnected">Bluetooth deconnectéiert.</string>
+ <string name="accessibility_no_battery">Keen Akku.</string>
+ <string name="accessibility_battery_one_bar">Akku, ee Stréch.</string>
+ <string name="accessibility_battery_two_bars">Akku, zwéi Strécher.</string>
+ <string name="accessibility_battery_three_bars">Akku, dräi Strécher.</string>
+ <string name="accessibility_battery_full">Akku gelueden.</string>
+ <string name="accessibility_no_phone">Keen Telefon.</string>
+ <string name="accessibility_phone_one_bar">Telefonssignal, ee Stréch.</string>
+ <string name="accessibility_phone_two_bars">Telefonssignal, zwéi Strécher.</string>
+ <string name="accessibility_phone_three_bars">Telefonssignal, dräi Strécher.</string>
+ <string name="accessibility_phone_signal_full">Voll Telefonsignalstäerkt.</string>
+ <string name="accessibility_no_data">Keng Daten.</string>
+ <string name="accessibility_data_one_bar">Datesignal, ee Stréch.</string>
+ <string name="accessibility_data_two_bars">Datesignal, zwéi Strécher.</string>
+ <string name="accessibility_data_three_bars">Datesignal, dräi Strécher.</string>
+ <string name="accessibility_data_signal_full">Voll Datesignalstäerkt.</string>
+ <string name="accessibility_wifi_name">Connectéiert mat <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
+ <string name="accessibility_bluetooth_name">Verbonne mat <xliff:g id="bluetooth" example="Car Audio">%s</xliff:g>.</string>
+ <string name="accessibility_no_wimax">Kee WiMAX.</string>
+ <string name="accessibility_wimax_one_bar">WiMAX, ee Stréch.</string>
+ <string name="accessibility_wimax_two_bars">WiMAX zwéi Strécher.</string>
+ <string name="accessibility_wimax_three_bars">WiMAX dräi Strécher.</string>
+ <string name="accessibility_wimax_signal_full">Voll WiMAX-Signalstäerkt.</string>
+ <string name="accessibility_no_signal">Kee Signal.</string>
+ <string name="accessibility_not_connected">Net connectéiert.</string>
+ <string name="accessibility_zero_bars">Null Strécher.</string>
+ <string name="accessibility_one_bar">Ee Stréch.</string>
+ <string name="accessibility_two_bars">Zwéi Strécher.</string>
+ <string name="accessibility_three_bars">Dräi Strécher.</string>
+ <string name="accessibility_signal_full">Voll Signalstäerkt.</string>
+ <string name="accessibility_desc_on">Un.</string>
+ <string name="accessibility_desc_off">Aus.</string>
+ <string name="accessibility_desc_connected">Verbonnen.</string>
+ <string name="accessibility_desc_connecting">Gëtt connectéiert.</string>
+ <string name="accessibility_data_connection_gprs">GPRS</string>
+ <string name="accessibility_data_connection_1x">1 X</string>
+ <string name="accessibility_data_connection_hspa">HSPA</string>
+ <string name="accessibility_data_connection_3g">3G</string>
+ <string name="accessibility_data_connection_3.5g">3.5G</string>
+ <string name="accessibility_data_connection_4g">4G</string>
+ <string name="accessibility_data_connection_lte">LTE</string>
+ <string name="accessibility_data_connection_cdma">CDMA</string>
+ <string name="accessibility_data_connection_roaming">Roaming</string>
+ <string name="accessibility_data_connection_edge">Edge</string>
+ <string name="accessibility_data_connection_wifi">WLAN</string>
+ <string name="accessibility_no_sim">Keng SIM.</string>
+ <string name="accessibility_bluetooth_tether">Bluetooth-Tethering.</string>
+ <string name="accessibility_airplane_mode">Fligermodus.</string>
+ <string name="accessibility_battery_level">Akku <xliff:g id="number">%d</xliff:g> Prozent.</string>
+ <string name="accessibility_settings_button">Systemastellungen.</string>
+ <string name="accessibility_notifications_button">Notifikatiounen.</string>
+ <string name="accessibility_remove_notification">Notifikatioun ewechhuelen.</string>
+ <string name="accessibility_gps_enabled">GPS aktivéiert.</string>
+ <string name="accessibility_gps_acquiring">GPS-Signal gëtt ofgeruff.</string>
+ <string name="accessibility_tty_enabled">Schreiftelefonie aktivéiert.</string>
+ <string name="accessibility_ringer_vibrate">Schellmodus \"Vibratioun\".</string>
+ <string name="accessibility_ringer_silent">Schellmodus \"Roueg\".</string>
+ <string name="accessibility_recents_item_will_be_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> verwerfen.</string>
+ <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> verworf.</string>
+ <string name="accessibility_recents_item_launched"><xliff:g id="app" example="Calendar">%s</xliff:g> gëtt gestart.</string>
+ <string name="accessibility_notification_dismissed">Notifikatioun verworf.</string>
+ <string name="accessibility_desc_notification_shade">Notifikatiounsläischt.</string>
+ <string name="accessibility_desc_quick_settings">Séier Astellungen.</string>
+ <string name="accessibility_desc_lock_screen">Schierm spären.</string>
+ <string name="accessibility_desc_settings">Astellungen</string>
+ <string name="accessibility_desc_recent_apps">Iwwersiicht.</string>
+ <string name="accessibility_quick_settings_user">Benotzer <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_wifi_changed_off">WLAN ausgeschalt.</string>
+ <string name="accessibility_quick_settings_wifi_changed_on">WLAN ugeschalt.</string>
+ <string name="accessibility_quick_settings_mobile">Mobil <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_battery">Akku <xliff:g id="state" example="50% charging">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_airplane_off">Fligermodus aus.</string>
+ <string name="accessibility_quick_settings_airplane_on">Fligermodus un.</string>
+ <string name="accessibility_quick_settings_airplane_changed_off">Fligermodus ausgeschalt.</string>
+ <string name="accessibility_quick_settings_airplane_changed_on">Fligermodus ugeschalt.</string>
+ <string name="accessibility_quick_settings_bluetooth_off">Bluetooth aus.</string>
+ <string name="accessibility_quick_settings_bluetooth_on">Bluetooth un.</string>
+ <string name="accessibility_quick_settings_bluetooth_connecting">Bluetooth gëtt verbonnen.</string>
+ <string name="accessibility_quick_settings_bluetooth_connected">Bluetooth verbonnen.</string>
+ <string name="accessibility_quick_settings_bluetooth_changed_off">Bluetooth ausgeschalt.</string>
+ <string name="accessibility_quick_settings_bluetooth_changed_on">Bluetooth ugeschalt.</string>
+ <string name="accessibility_quick_settings_location_off">Standuertbericht aus.</string>
+ <string name="accessibility_quick_settings_location_on">Standuertbericht un.</string>
+ <string name="accessibility_quick_settings_location_changed_off">Standuertbericht ausgeschalt.</string>
+ <string name="accessibility_quick_settings_location_changed_on">Standuertbericht ugeschalt.</string>
+ <string name="accessibility_quick_settings_alarm">Alarm gesat fir <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_close">Panneau zoumaachen.</string>
+ <string name="accessibility_quick_settings_more_time">Méi Zäit.</string>
+ <string name="accessibility_quick_settings_less_time">Manner Zäit.</string>
+ <string name="accessibility_quick_settings_flashlight_off">Täscheluucht aus.</string>
+ <string name="accessibility_quick_settings_flashlight_on">Täscheluucht un.</string>
+ <string name="accessibility_quick_settings_flashlight_changed_off">Täscheluucht ausgemaach.</string>
+ <string name="accessibility_quick_settings_flashlight_changed_on">Täscheluucht ugemaach.</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_off">Faarfinvertéierung ausgeschalt.</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_on">Faarfinvertéierung ugeschalt.</string>
+ <string name="accessibility_quick_settings_hotspot_changed_off">Mobillen Zougankspunkt ausgeschalt.</string>
+ <string name="accessibility_quick_settings_hotspot_changed_on">Mobillen Zougankspunkt ugeschalt.</string>
+ <string name="accessibility_casting_turned_off">Cast vum Schierm gestoppt.</string>
+ <string name="accessibility_brightness">Schiermhellegkeet</string>
+ <string name="status_bar_settings_signal_meter_disconnected">
+ Keng Internetconnectioun
+    </string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid">WLAN connectéiert</string>
+ <string name="gps_notification_searching_text">GPS gëtt gesicht</string>
+ <string name="gps_notification_found_text">Standuert duerch GPS festgeluecht</string>
+ <string name="accessibility_location_active">Standuertufroen aktiv</string>
+ <string name="accessibility_clear_all">Notifikatiounen eidel maachen.</string>
+ <string name="status_bar_notification_inspect_item_title">Notifikatiounsastellungen</string>
+ <string name="status_bar_notification_app_settings_title"><xliff:g id="app_name" example="Calendar">%s</xliff:g>-Astellungen</string>
+ <string name="accessibility_rotation_lock_off">De Schierm gëtt automatesch rotéiert.</string>
+ <string name="accessibility_rotation_lock_on_landscape">De Schierm ass am Breetformat gespaart.</string>
+ <string name="accessibility_rotation_lock_on_portrait">De Schierm ass am Héichformat gespaart.</string>
+ <string name="accessibility_rotation_lock_off_changed">De Schierm rotéiert elo automatesch.</string>
+ <string name="accessibility_rotation_lock_on_landscape_changed">De Schierm ass am Breetformat gespaart.</string>
+ <string name="accessibility_rotation_lock_on_portrait_changed">De Schierm ass am Héichformat gespaart.</string>
+ <string name="dessert_case">Dessertskëscht</string>
+ <string name="start_dreams">Dagesdram</string>
+ <string name="ethernet_label">Ethernet</string>
+ <string name="quick_settings_bluetooth_label">Bluetooth</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label">Bluetooth (<xliff:g id="number">%d</xliff:g> Apparater)</string>
+ <string name="quick_settings_bluetooth_off_label">Bluetooth Aus</string>
+ <string name="quick_settings_bluetooth_detail_empty_text">Keng gekoppelt Apparater disponibel</string>
+ <string name="quick_settings_brightness_label">Hellegkeet</string>
+ <string name="quick_settings_rotation_unlocked_label">Automatesch rotéieren</string>
+ <string name="quick_settings_rotation_locked_label">Rotéierung gespaart</string>
+ <string name="quick_settings_rotation_locked_portrait_label">Héichformat</string>
+ <string name="quick_settings_rotation_locked_landscape_label">Breetformat</string>
+ <string name="quick_settings_ime_label">Method fir anzeginn</string>
+ <string name="quick_settings_location_label">Standuert</string>
+ <string name="quick_settings_location_off_label">Lokaliséierung aus</string>
+ <string name="quick_settings_media_device_label">Medienapparat</string>
+ <string name="quick_settings_rssi_label">RSSI</string>
+ <string name="quick_settings_rssi_emergency_only">Just Noutriff</string>
+ <string name="quick_settings_settings_label">Astellungen</string>
+ <string name="quick_settings_time_label">Zäit</string>
+ <string name="quick_settings_user_label">Ech</string>
+ <string name="quick_settings_user_title">Benotzer</string>
+ <string name="quick_settings_user_new_user">Neie Benotzer</string>
+ <string name="quick_settings_wifi_label">WLAN</string>
+ <string name="quick_settings_wifi_not_connected">Net Connectéiert</string>
+ <string name="quick_settings_wifi_no_network">Keen Netzwierk</string>
+ <string name="quick_settings_wifi_off_label">WLAN Aus</string>
+ <string name="quick_settings_casting">Casten</string>
+ <string name="quick_settings_cast_device_default_name">Apparat ouni Numm</string>
+ <string name="quick_settings_cast_device_default_description">Prett fir ze casten</string>
+ <string name="quick_settings_cast_detail_empty_text">Keng Apparater disponibel</string>
+ <string name="quick_settings_brightness_dialog_title">Hellegkeet</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label">AUTO</string>
+ <string name="quick_settings_inversion_label">Faarwen invertéieren</string>
+ <string name="quick_settings_color_space_label">Faarfkorrekturmodus</string>
+ <string name="quick_settings_more_settings">Méi Astellungen</string>
+ <string name="quick_settings_done">Fäerdeg</string>
+ <string name="quick_settings_connected">Verbonnen</string>
+ <string name="quick_settings_connecting">Gëtt connectéiert...</string>
+ <string name="quick_settings_tethering_label">Tethering</string>
+ <string name="quick_settings_hotspot_label">Zougankspunkt</string>
+ <string name="quick_settings_notifications_label">Notifikatiounen</string>
+ <string name="quick_settings_flashlight_label">Täscheluucht</string>
+ <string name="quick_settings_cellular_detail_title">Zelldaten</string>
+ <string name="quick_settings_cellular_detail_data_usage">Dateverbrauch</string>
+ <string name="quick_settings_cellular_detail_remaining_data">Iwwreg Daten</string>
+ <string name="quick_settings_cellular_detail_over_limit">Iwwer d\'Limitt</string>
+ <string name="quick_settings_cellular_detail_data_used"><xliff:g id="data_used" example="2.0 GB">%s</xliff:g> benotzt</string>
+ <string name="quick_settings_cellular_detail_data_limit"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g>-Limitt</string>
+ <string name="quick_settings_cellular_detail_data_warning"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> Warnung</string>
+ <string name="recents_empty_message">Deng rezent Schiermer erschéngen hei</string>
+ <string name="recents_app_info_button_label">App-Info</string>
+ <string name="recents_lock_to_app_button_label">Schiermfixéierung</string>
+ <string name="recents_search_bar_label">sichen</string>
+ <string name="recents_launch_error_message">Konnt net <xliff:g id="app" example="Calendar">%s</xliff:g> starten.</string>
+ <string name="expanded_header_battery_charged">Opgelueden</string>
+ <string name="expanded_header_battery_charging">Gëtt opgelueden</string>
+ <string name="expanded_header_battery_charging_with_time"><xliff:g id="charging_time" example="2 hrs 25 min">%s</xliff:g> bis den Akku voll ass</string>
+ <string name="expanded_header_battery_not_charging">Gëtt net opgelueden</string>
+ <string name="battery_meter_very_low_overlay_symbol">!</string>
+ <string name="ssl_ca_cert_warning">D\'Netzwierk kéint\n
+iwwerwaacht sinn</string>
+ <string name="description_target_search">Sichen</string>
+ <string name="description_direction_up">Eropréckele fir ze <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
+ <string name="description_direction_left">No lénks réckele fir ze <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
+ <string name="keyguard_more_overflow_text">+<xliff:g id="number_of_notifications" example="5">%d</xliff:g></string>
+ <string name="speed_bump_explanation">Manner dréngend Notifikatiounen drënner</string>
+ <string name="notification_tap_again">Dréck nees fir opzemaachen</string>
+ <string name="keyguard_unlock">Eropwësche fir z\'entspären</string>
+ <string name="keyguard_indication_charging_time">Akku luet (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> bis e voll ass)</string>
+ <string name="accessibility_multi_user_switch_switcher">Benotzer wiesselen</string>
+ <string name="accessibility_multi_user_switch_switcher_with_current">Benotzer wiesselen, aktuelle Benotzer <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
+ <string name="accessibility_multi_user_switch_quick_contact">Profil uweisen</string>
+ <string name="user_add_user">Benotzer dobäisetzen</string>
+ <string name="user_new_user_name">Neie Benotzer</string>
+ <string name="guest_nickname">Gaascht</string>
+ <string name="guest_new_guest">Gaascht dobäisetzen</string>
+ <string name="guest_exit_guest">Gaascht ewechhuelen</string>
+ <string name="guest_exit_guest_dialog_title">Gaascht ewechhuelen?</string>
+ <string name="guest_exit_guest_dialog_message">All d\'Appen an Daten an dëser Sëtzung gi geläscht.</string>
+ <string name="guest_exit_guest_dialog_remove">Ewechhuelen</string>
+ <string name="guest_wipe_session_title">Wëllkomm zréck, Gaascht!</string>
+ <string name="guest_wipe_session_message">Wëlls du deng Sëtzung weiderféieren?</string>
+ <string name="guest_wipe_session_wipe">Vu vir ufänken</string>
+ <string name="guest_wipe_session_dontwipe">Jo, weidermaachen</string>
+ <string name="user_add_user_title" msgid="2108112641783146007">Neie Benotzer dobäisetzen?</string>
+ <string name="user_add_user_message_short" msgid="1511354412249044381">Wann s du en neie Benotzer dobäisetz, muss déi Persoun hiren Espace amenagéieren.\n\nAll Benotzer kann Appe fir all aner Benotzer aktualiséieren.</string>
+ <string name="battery_saver_notification_title">Den Akkuschouner ass un</string>
+ <string name="battery_saver_notification_text">Reduzéiert d\'Vitess an d\'Hannergronddaten</string>
+ <string name="battery_saver_notification_action_text">Akkuschouner ausschalten</string>
+ <string name="notification_hidden_text">Inhalter verstoppt</string>
+ <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> hëlt alles op dat op dengem Schierm ugewise gëtt.</string>
+ <string name="media_projection_remember_text">Net méi uweisen</string>
+ <string name="clear_all_notifications_text">Alles eidel maachen</string>
+ <string name="media_projection_action_text">Elo starten</string>
+ <string name="empty_shade_text">Keng Notifikatiounen</string>
+ <string name="device_owned_footer">Den Apparat kéint iwwerwaacht sinn</string>
+ <string name="profile_owned_footer">De Profil kéint iwwerwaacht sinn</string>
+ <string name="vpn_footer">D\'Netzwierk kéint iwwerwaacht sinn</string>
+ <string name="monitoring_title_device_owned">Apparat-Iwwerwaachung</string>
+ <string name="monitoring_title_profile_owned">Profil-Iwwerwaachung</string>
+ <string name="monitoring_title">Netzwierk-Iwwerwaachung</string>
+ <string name="disable_vpn">VPN desaktivéieren</string>
+ <string name="disconnect_vpn">VPN deconnectéieren</string>
+ <string name="keyguard_indication_trust_disabled">Den Apparat bleift gespaart, bis e manuell entspaart gëtt</string>
+ <string name="hidden_notifications_title">Notifikatioune méi séier kréien</string>
+ <string name="hidden_notifications_text">Virum Entspären uweisen</string>
+ <string name="hidden_notifications_cancel">Nee Merci</string>
+ <string name="hidden_notifications_setup">Ariichten</string>
+ <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
+ <string name="screen_pinning_title">Schierm ass fixéiert</string>
+ <string name="screen_pinning_description">Dëst gëtt dir ugewisen, bis du d\'Fixéierung ophiefs. Dréck an hal \"Zréck\" an \"Iwwersiicht\" gläichzäiteg un, fir d\'Fixéierung opzehiewen.</string>
+ <string name="screen_pinning_description_accessible">Dëst gëtt dir ugewisen, bis du d\'Fixéierung ophiefs. Dréck an hal \"Zréck\" an \"Iwwersiicht\" un, fir d\'Fixéierung opzehiewen.</string>
+ <string name="screen_pinning_positive">Verstanen</string>
+ <string name="screen_pinning_negative">Nee Merci</string>
+ <string name="quick_settings_reset_confirmation_title"><xliff:g id="tile_label" example="Hotspot">%1$s</xliff:g> verstoppen?</string>
+ <string name="quick_settings_reset_confirmation_message">Dëst gëtt dir d\'nächst Kéier ugewisen, wann s du et an den Astellungen nees aktivéiers.</string>
+ <string name="quick_settings_reset_confirmation_button">Verstoppen</string>
+ <string name="status_bar_ethernet">Ethernet</string>
+ <string name="status_bar_airplane">Fligermodus</string>
+ <string name="accessibility_status_bar_hotspot">Zougankspunkt</string>
+ <string name="got_it">Verstanen</string>
+ <string name="enable_bluetooth_confirmation_ok">Uschalten</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lt/cm_arrays.xml b/packages/SystemUI/res/values-lt/cm_arrays.xml
new file mode 100644
index 0000000..ae2ee65
--- /dev/null
+++ b/packages/SystemUI/res/values-lt/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Š</item>
+ <item>ŠR</item>
+ <item>R</item>
+ <item>PR</item>
+ <item>P</item>
+ <item>PV</item>
+ <item>V</item>
+ <item>ŠV</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-lt/cm_strings.xml b/packages/SystemUI/res/values-lt/cm_strings.xml
new file mode 100644
index 0000000..71a070b
--- /dev/null
+++ b/packages/SystemUI/res/values-lt/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Braukite į dešinę, kad %1$s</string>
+ <string name="right_shortcut_hint">Braukite į kairę, kad %1$s</string>
+ <string name="select_application">Pasirinkti programą</string>
+ <string name="lockscreen_choose_action_title">Pasirinkti veiksmą</string>
+ <string name="lockscreen_none_target">Joks</string>
+ <string name="navbar_dialog_title">Pasirinkite veiksmą, kad jį priskirtumėte</string>
+ <string name="navbar_home_button">Pagrindinis mygtukas</string>
+ <string name="navbar_recent_button">„Naujausių“ mygtukas</string>
+ <string name="navbar_search_button">Paieškos mygtukas</string>
+ <string name="navbar_back_button">Atgal mygtukas</string>
+ <string name="navbar_empty_button">Tuščias mygtukas</string>
+ <string name="navbar_menu_conditional_button">Meniu mygtukas (automatiškai slepiamas)</string>
+ <string name="navbar_menu_always_button">Meniu mygtukas (visada rodomas)</string>
+ <string name="navbar_menu_big_button">Meniu mygtukas</string>
+ <string name="accessibility_dpad_left">Žymeklis kairėje</string>
+ <string name="accessibility_dpad_right">Žymeklis dešinėje</string>
+ <string name="advanced_dev_option_wipe_app">Ištrinti programos duomenis</string>
+ <string name="advanced_dev_option_force_stop">Priverstinai sustabdyti</string>
+ <string name="advanced_dev_option_uninstall">Pašalinti</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiliai išjungti.</string>
+ <string name="accessibility_quick_settings_profiles">Profilis: <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiliai išjungti.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profilis pakeistas į <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicijuojama\u2026</string>
+ <string name="screen_pinning_description_no_navbar">Tai laikys jį matomą iki kol atsegsite. Palieskite ir laikykite mygtuką atgal, kad atsegtumėte.</string>
+ <string name="quick_settings_custom_tile_detail_title">Tinkinta plytelė</string>
+ <string name="quick_settings_remove">Pašalinti plytelę</string>
+ <string name="quick_settings_network_adb_label">„Android“ derinimas per tinklą</string>
+ <string name="quick_settings_compass_label">Kompasas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Sistemos profiliai</string>
+ <string name="quick_settings_profiles_off">Profiliai neleidžiami</string>
+ <string name="quick_settings_heads_up_label">Iššokantys pranešimai</string>
+ <string name="quick_settings_battery_saver_label">Akumuliatoriaus tausojimas</string>
+ <string name="accessibility_quick_settings_sync_off">Sinchronizavimas išjungtas.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinchronizavimas įjungtas.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sinchronizavimas išjungtas.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sinchronizavimas įjungtas.</string>
+ <string name="quick_settings_sync_label">Sinchronizavimas</string>
+ <string name="quick_settings_volume_panel_label">Garsumo skydelis</string>
+ <string name="quick_settings_usb_tether_label">USB susiejimas</string>
+ <string name="quick_settings_screen_timeout_detail_title">Ekrano skirtasis laikas</string>
+ <string name="quick_settings_lockscreen_label">Ekrano užraktas</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Ekrano užraktas vykdomas</string>
+ <string name="accessibility_quick_settings_screen_timeout">Ekrano skirtasis laikas: <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Ekrano skirtasis laikas pakeistas į <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="qs_tile_performance">Akumuliatoriaus režimas</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Akumuliatoriaus režimas: energijos tausojimo režimas.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Akumuliatoriaus režimas: subalansuotas režimas.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Akumuliatoriaus režimas: našumo režimas.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Akumuliatoriaus režimas: efektyvus režimas.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Akumuliatoriaus rėžimas: spartus režimas.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Akumuliatoriaus režimas pakeistas į energijos tausojimo režimą.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Akumuliatoriaus režimas pakeistas į subalansuotą režimą.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Akumuliatoriaus režimas pakeistas į našumo režimą.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Akumuliatoriaus režimas pakeistas į efektyvų režimą.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Akumuliatoriaus režimas pakeistas į spartų režimą.</string>
+ <string name="quick_settings_performance_profile_detail_title">Akumuliatoriaus režimas</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Ekrano užraktas išjungtas.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Ekrano užraktas įjungtas.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Ekrano užraktas išjungtas.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Ekrano užraktas įjungtas.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display išjungta.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display įjungta.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient display išjungta.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display įjungta.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Iššokantys pranešimai išjungti.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Iššokantys pranešimai įjungti.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Iššokantys pranešimai išjungti.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Iššokantys pranešimai įjungti.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Akumuliatoriaus tausojimas išjungtas.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Akumuliatoriaus tausojimas įjungtas.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Akumuliatoriaus tausojimas išjungtas.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Akumuliatoriaus tausojimas įjungtas.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinaminė plytelė</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Kitas signalas</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Įvesties metodas</string>
+ <string name="dynamic_qs_tile_su_label">Prieiga prie „Root“</string>
+ <string name="accessibility_quick_settings_live_display_off">„LiveDisplay“ išjungtas.</string>
+ <string name="accessibility_quick_settings_live_display_auto">„LiveDisplay“: automatinis režimas.</string>
+ <string name="accessibility_quick_settings_live_display_day">„LiveDisplay“: dienos režimas.</string>
+ <string name="accessibility_quick_settings_live_display_night">„LiveDisplay“: nakties režimas.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">„LiveDisplay“: lauko režimas.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">„LiveDisplay“ išjungtas.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">„LiveDisplay“ pakeistas į automatinį režimą.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">„LiveDisplay“ pakeistas į dienos režimą.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">„LiveDisplay“ pakeistas į nakties režimą.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">„LiveDisplay“ pakeistas į lauko režimą.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Vietovės ataskaitos: akumuliatoriaus tausojimo režimas.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Vietovės ataskaitos: tik daviklių režimas.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Vietovės ataskaitos: didelio tikslumo režimas.</string>
+ <string name="quick_settings_location_detail_title">Vietovės režimas</string>
+ <string name="quick_settings_location_battery_saving_label">Akumuliatoriaus tausojimas</string>
+ <string name="quick_settings_location_gps_only_label">Tik įrenginys</string>
+ <string name="quick_settings_location_high_accuracy_label">Didelis tikslumas</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Vietovės ataskaitos pakeistos į akumuliatoriaus tausojimo režimą.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Vietovės ataskaitos pakeistos į tik jutiklių režimą.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Vietovės ataskaitos pakeistos į didelio tikslumo režimą.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lv/cm_arrays.xml b/packages/SystemUI/res/values-lv/cm_arrays.xml
new file mode 100644
index 0000000..3c12c9e
--- /dev/null
+++ b/packages/SystemUI/res/values-lv/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Z</item>
+ <item>ZA</item>
+ <item>A</item>
+ <item>DA</item>
+ <item>D</item>
+ <item>DR</item>
+ <item>R</item>
+ <item>ZR</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-lv/cm_strings.xml b/packages/SystemUI/res/values-lv/cm_strings.xml
new file mode 100644
index 0000000..8f15420
--- /dev/null
+++ b/packages/SystemUI/res/values-lv/cm_strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="navbar_dialog_title">Izvēlieties darbību, ko piešķirt</string>
+ <string name="navbar_home_button">Mājas poga</string>
+ <string name="navbar_recent_button">Nesenā poga</string>
+ <string name="navbar_search_button">Meklēšanas poga</string>
+ <string name="navbar_back_button">Atpakaļ poga</string>
+ <string name="navbar_menu_conditional_button">Izvēlnes (automātiski paslēpt) poga</string>
+ <string name="navbar_menu_always_button">Izvēlnes (vienmēr rādīt) poga</string>
+ <string name="navbar_menu_big_button">Izvēlnes poga</string>
+ <string name="accessibility_dpad_left">Kursoru pa kreisi</string>
+ <string name="accessibility_dpad_right">Kursoru pa labi</string>
+ <string name="advanced_dev_option_wipe_app">Nodzēst lietotnes datus</string>
+ <string name="advanced_dev_option_force_stop">Piespiedu apturēšana</string>
+ <string name="advanced_dev_option_uninstall">Noņemt</string>
+ <string name="quick_settings_compass_init">Inicializē\u2026</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mdpi/cm_dimens.xml b/packages/SystemUI/res/values-mdpi/cm_dimens.xml
new file mode 100644
index 0000000..20d836a
--- /dev/null
+++ b/packages/SystemUI/res/values-mdpi/cm_dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<resources>
+ <dimen name="weather_text_size">9sp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-nb/cm_arrays.xml b/packages/SystemUI/res/values-nb/cm_arrays.xml
new file mode 100644
index 0000000..9763e17
--- /dev/null
+++ b/packages/SystemUI/res/values-nb/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NØ</item>
+ <item>Ø</item>
+ <item>SØ</item>
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>NV</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-nb/cm_strings.xml b/packages/SystemUI/res/values-nb/cm_strings.xml
new file mode 100644
index 0000000..9086450
--- /dev/null
+++ b/packages/SystemUI/res/values-nb/cm_strings.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Sveip til høyre for %1$s</string>
+ <string name="right_shortcut_hint">Sveip til venstre for %1$s</string>
+ <string name="lockscreen_message">Trykk på ikonet på venstre eller høyre for å tilordne en låseskjermsnarvei.</string>
+ <string name="lockscreen_default_target">Standard</string>
+ <string name="select_application">Velg applikasjon</string>
+ <string name="lockscreen_choose_action_title">Velg handling</string>
+ <string name="lockscreen_none_target">Ingen</string>
+ <string name="navbar_dialog_title">Velg handlingen du vil tilordne</string>
+ <string name="navbar_home_button">Hjem-knappen</string>
+ <string name="navbar_recent_button">Siste knappen</string>
+ <string name="navbar_search_button">Søkeknapp</string>
+ <string name="navbar_back_button">Tilbake-knappen</string>
+ <string name="navbar_empty_button">Tom knapp</string>
+ <string name="navbar_menu_conditional_button">Menyknappen (Skjul)</string>
+ <string name="navbar_menu_always_button">Menyknappen (alltid vis)</string>
+ <string name="navbar_menu_big_button">Meny-knappen</string>
+ <string name="accessibility_dpad_left">Markør til venstre</string>
+ <string name="accessibility_dpad_right">Markør til høyre</string>
+ <string name="advanced_dev_option_wipe_app">Slett appdata</string>
+ <string name="advanced_dev_option_force_stop">Tving avslutning</string>
+ <string name="advanced_dev_option_uninstall">Avinstaller</string>
+ <string name="accessibility_notification_brightness">Lys lysstyrke</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiler av.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s </xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiler deaktivert.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil endret til <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Initialiserer\u2026</string>
+ <string name="led_notification_title">Lys innstillinger</string>
+ <string name="led_notification_text">LED lyset aktiveres av innstillingene</string>
+ <string name="qs_tile_edit_header_instruction">Trykk og hold fliser for å omorganisere</string>
+ <string name="quick_settings_edit_label">Rediger fliser</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Kan ikke slette Rediger-flisen</string>
+ <string name="qs_tiles_reset_confirmation">Tilbakestill innstillinger for innstillingsflisene til standardkonfigurasjonen?</string>
+ <string name="quick_settings_tile_reset_to_default">Tilbakestille til standard oppsett</string>
+ <string name="quick_settings_title_header">Topptekst</string>
+ <string name="quick_settings_title_tiles">Fliser</string>
+ <string name="quick_settings_title_show_weather">Vis været</string>
+ <string name="quick_settings_title_show_brightness_slider">Vis lysstyrkeendrer</string>
+ <string name="quick_settings_title_enlarge_first_row">Forstørr første rad</string>
+ <string name="screen_pinning_description_no_navbar">Dette holder den i syne inntill du løsner den. Trykk og hold på tilbake knappen for å løsne.</string>
+ <string name="quick_settings_custom_tile_detail_title">Egendefinerte fliser</string>
+ <string name="quick_settings_remove">Fjern flis</string>
+ <string name="quick_settings_network_adb_label">ADB over nettverk</string>
+ <string name="quick_settings_compass_label">Kompass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">System profiler</string>
+ <string name="quick_settings_profiles_off">Profiler deaktivert</string>
+ <string name="quick_settings_heads_up_label">Flytende notifikasjoner</string>
+ <string name="quick_settings_battery_saver_label">Batterisparing</string>
+ <string name="accessibility_quick_settings_sync_off">Synkronisering av.</string>
+ <string name="accessibility_quick_settings_sync_on">Synkronisering på.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synkronisering avskrudd.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synkronisering aktivert.</string>
+ <string name="quick_settings_sync_label">Synkronisering</string>
+ <string name="quick_settings_volume_panel_label">Volumpanel</string>
+ <string name="quick_settings_usb_tether_label">USB tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Tidsavbrudd for skjermen</string>
+ <string name="quick_settings_lockscreen_label">Låseskjerm</string>
+ <string name="quick_settings_ambient_display_label">Ambient skjerm</string>
+ <string name="quick_settings_lockscreen_label_enforced">Låseskjerm er påkrevd</string>
+ <string name="accessibility_quick_settings_screen_timeout">Skjerm tidsavbrudd: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Skjermens tidsavbrudd endret til <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Batterimodus</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Batterimodus: strømsparing.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Batterimodus: balansert.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Batterimodus: ytelse.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Batterimodus: effektivitet modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Batterimodus: hurtigmodus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Batterimodus er endret til strømsparingsmodus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Batterimodus er endret til balansert modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Batterimodus er endret til ytelsesmodus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Batterimodus endret til effektivitet modus.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Batterimodus endret til hurtigmodus.</string>
+ <string name="quick_settings_performance_profile_detail_title">Batterimodus</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Låseskjerm av.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Låseskjerm på.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Låseskjerm slått av.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Låseskjerm slått på.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient visning av.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient visning på.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient visning er skrudd av.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient visning er skrudd på.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up notifikasjoner er av.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up notifikasjoner er på.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads-up ble deaktivert.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads-up ble aktivert.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Batterisparing av.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Batterisparing på.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Batterisparing slått av.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Batterisparing slått på.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamisk flis</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Neste alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME-velger</string>
+ <string name="dynamic_qs_tile_su_label">Root-tilgang</string>
+ <string name="accessibility_quick_settings_live_display_off">Direkteskjerm av.</string>
+ <string name="accessibility_quick_settings_live_display_auto">Direkteskjerm: automatisk.</string>
+ <string name="accessibility_quick_settings_live_display_day">Direkteskjerm: dagsmodus.</string>
+ <string name="accessibility_quick_settings_live_display_night">Direkteskjerm: nattmodus.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">Direkteskjerm: utendørs.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">Direkteskjerm deaktivert.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">Direkteskjerm endret til automatisk.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">Direkteskjerm endret til dagsmodus.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">Direkteskjerm endret til nattmodus.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">Direkteskjerm endret til utendørs.</string>
+ <string name="quick_settings_title_advanced_location">Tre nivåer stedsangivelse</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Lokasjonsmodus: strømsparemodus.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Lokasjonsmodus: kun sensorer.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Lokasjonsmodus: høy nøyaktighet.</string>
+ <string name="quick_settings_location_detail_title">Lokasjonsmodus</string>
+ <string name="quick_settings_location_battery_saving_label">Batterisparing</string>
+ <string name="quick_settings_location_gps_only_label">Kun enhet</string>
+ <string name="quick_settings_location_high_accuracy_label">Høy nøyaktighet</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Lokasjonsmodus endret til batterisparing.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Lokasjonsmodus endret til bare sensorer.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Lokasjonsmodus endret til høy nøyaktighet.</string>
+ <string name="quick_settings_tiles_category_system">Systemet fliser</string>
+ <string name="quick_settings_tiles_add_tiles">Legge til en flis</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nl/cm_arrays.xml b/packages/SystemUI/res/values-nl/cm_arrays.xml
new file mode 100644
index 0000000..823d481
--- /dev/null
+++ b/packages/SystemUI/res/values-nl/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NO</item>
+ <item>O</item>
+ <item>ZO</item>
+ <item>Z</item>
+ <item>ZW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-nl/cm_strings.xml b/packages/SystemUI/res/values-nl/cm_strings.xml
new file mode 100644
index 0000000..0305871
--- /dev/null
+++ b/packages/SystemUI/res/values-nl/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Veeg naar rechts voor %1$s</string>
+ <string name="right_shortcut_hint">Veeg naar links voor %1$s</string>
+ <string name="lockscreen_message">Tik links of rechts op een pictogram om de snelkoppeling opnieuw toe te wijzen.</string>
+ <string name="lockscreen_default_target">Standaard</string>
+ <string name="select_application">App selecteren</string>
+ <string name="lockscreen_choose_action_title">Actie selecteren</string>
+ <string name="lockscreen_none_target">Geen</string>
+ <string name="navbar_dialog_title">Kies de toe te wijzen functie</string>
+ <string name="navbar_home_button">Thuisknop</string>
+ <string name="navbar_recent_button">Recentknop</string>
+ <string name="navbar_search_button">Zoekknop</string>
+ <string name="navbar_back_button">Terugknop</string>
+ <string name="navbar_empty_button">Lege knop</string>
+ <string name="navbar_menu_conditional_button">Menuknop (altijd verbergen)</string>
+ <string name="navbar_menu_always_button">Menuknop (altijd tonen)</string>
+ <string name="navbar_menu_big_button">Menuknop</string>
+ <string name="accessibility_dpad_left">Cursor links</string>
+ <string name="accessibility_dpad_right">Cursor rechts</string>
+ <string name="advanced_dev_option_wipe_app">App-gegevens wissen</string>
+ <string name="advanced_dev_option_force_stop">Nu stoppen</string>
+ <string name="advanced_dev_option_uninstall">Verwijderen</string>
+ <string name="accessibility_notification_brightness">Verlichtingshelderheid</string>
+ <string name="accessibility_quick_settings_profiles_off">Profielen uit.</string>
+ <string name="accessibility_quick_settings_profiles">Profiel: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profielen uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profiel gewijzigd naar <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Initialiseren\u2026</string>
+ <string name="led_notification_title">Verlichtingsinstellingen</string>
+ <string name="led_notification_text">LED-verlichting ingeschakeld door instellingen</string>
+ <string name="qs_tile_edit_header_instruction">Tegels ingedrukt houden om te verplaatsen</string>
+ <string name="quick_settings_edit_label">Tegels bewerken</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Kan de bewerk-tegel niet verwijderen</string>
+ <string name="qs_tiles_reset_confirmation">Tegels snelle instellingen naar standaardwaarden herstellen?</string>
+ <string name="quick_settings_tile_reset_to_default">Standaardindeling herstellen</string>
+ <string name="quick_settings_title_header">Koptekst</string>
+ <string name="quick_settings_title_tiles">Tegels</string>
+ <string name="quick_settings_title_show_weather">Weer weergeven</string>
+ <string name="quick_settings_title_show_brightness_slider">Schuifregelaar helderheid</string>
+ <string name="quick_settings_title_enlarge_first_row">Eerst rij vergroten</string>
+ <string name="screen_pinning_description_no_navbar">Met scherm vastzetten wordt het beeldscherm vergrendeld op één weergave.\n\nBlijf de Terug-knop aanraken om het scherm los te maken.</string>
+ <string name="quick_settings_custom_tile_detail_title">Aangepaste tegel</string>
+ <string name="quick_settings_remove">Tegel verwijderen</string>
+ <string name="quick_settings_network_adb_label">ADB over netwerk</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systeemprofielen</string>
+ <string name="quick_settings_profiles_off">Profielen uitgeschakeld</string>
+ <string name="quick_settings_heads_up_label">Heads-up</string>
+ <string name="quick_settings_battery_saver_label">Accubesparing</string>
+ <string name="quick_settings_caffeine_label">Cafeïne</string>
+ <string name="accessibility_quick_settings_sync_off">Synchr. uit.</string>
+ <string name="accessibility_quick_settings_sync_on">Synchr. aan.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchr. uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchr. ingeschakeld.</string>
+ <string name="quick_settings_sync_label">Synchroniseren</string>
+ <string name="quick_settings_volume_panel_label">Volumepaneel</string>
+ <string name="quick_settings_usb_tether_label">USB-tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Schermtime-out</string>
+ <string name="quick_settings_lockscreen_label">Schermbeveiliging</string>
+ <string name="quick_settings_ambient_display_label">Omgevingsdisplay</string>
+ <string name="quick_settings_lockscreen_label_enforced">Schermbeveiliging activeren</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Uitgeschakeld door profiel</string>
+ <string name="accessibility_quick_settings_screen_timeout">Schermtime-out: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Schermtime-out gewijzigd naar <xliff:g id="timeout" example="30 seconds">%s </xliff:g>.</string>
+ <string name="qs_tile_performance">Accumodus</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Accumodus: energiebesparing.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Accumodus: gebalanceerd.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Accumodus: prestaties.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Accumodus: efficiënt.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Accumodus: snel.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Accumodus: gewijzigd naar energiebesparing.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Accumodus: gewijzigd naar gebalanceerd.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Accumodus: gewijzigd naar prestaties.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Accumodus: gewijzigd naar efficiënt.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Accumodus: gewijzigd naar snel.</string>
+ <string name="quick_settings_performance_profile_detail_title">Accumodus</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Schermvergrendeling uit.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Schermvergrendeling aan.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Schermvergrendeling uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Schermvergrendeling ingeschakeld.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Omgevingsdisplay uit.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Omgevingsdisplay aan.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Omgevingsdisplay uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Omgevingsdisplay ingeschakeld.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads-up uit.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads-up aan.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads-up uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads-up ingeschakeld.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Cafeïne uit.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Cafeïne aan.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Accubesparing uit.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Accubesparing aan.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Accubesparing uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Accubesparing ingeschakeld.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamische tegel</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Volgend alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Invoermethode</string>
+ <string name="dynamic_qs_tile_su_label">Root-toegang</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay uit.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automatisch.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: dagstand.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nachtstand.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: buitenstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay uitgeschakeld.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay gewijzigd naar automatisch.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay gewijzigd naar dagstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay gewijzigd naar nachtstand.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay gewijzigd naar buitenstand.</string>
+ <string name="quick_settings_title_advanced_location">Locatie met 3 standen</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Locatiemelding: accubesparing.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Locatiemelding: alleen apparaat.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Locatiemelding: grote nauwkeurigheid.</string>
+ <string name="quick_settings_location_detail_title">Locatiemodus</string>
+ <string name="quick_settings_location_battery_saving_label">Accubesparing</string>
+ <string name="quick_settings_location_gps_only_label">Alleen apparaat</string>
+ <string name="quick_settings_location_high_accuracy_label">Grote nauwkeurigheid</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Locatiemelding gewijzigd naar accubesparing.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Locatiemelding gewijzigd naar alleen apparaat.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Locatiemelding gewijzigd naar grote nauwkeurigheid.</string>
+ <string name="quick_settings_tiles_category_system">Systeemtegels</string>
+ <string name="quick_settings_tiles_add_tiles">Tegel toevoegen</string>
+ <string name="hotspot_apm_message">Kan geen verbinding maken met mobiele netwerken als vliegmodus is ingeschakeld. Schakel vliegmodus uit en probeer het opnieuw.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Zaklamp staat aan</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Tik om uit te schakelen</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pl/cm_arrays.xml b/packages/SystemUI/res/values-pl/cm_arrays.xml
new file mode 100644
index 0000000..6d676ae
--- /dev/null
+++ b/packages/SystemUI/res/values-pl/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>płn.</item>
+ <item>płn. wsch.</item>
+ <item>wsch.</item>
+ <item>płd. wsch.</item>
+ <item>płd.</item>
+ <item>płd. zach.</item>
+ <item>zach.</item>
+ <item>płn. zach.</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-pl/cm_strings.xml b/packages/SystemUI/res/values-pl/cm_strings.xml
new file mode 100644
index 0000000..30dfcf5
--- /dev/null
+++ b/packages/SystemUI/res/values-pl/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Przesuń palcem w prawo do %1$s</string>
+ <string name="right_shortcut_hint">Przesuń palcem w lewo do %1$s</string>
+ <string name="lockscreen_message">Dotknij ikony po lewej lub prawej, aby przypisać skrót ekranu blokady.</string>
+ <string name="lockscreen_default_target">Domyślna</string>
+ <string name="select_application">Wybierz aplikację</string>
+ <string name="lockscreen_choose_action_title">Wybierz akcję</string>
+ <string name="lockscreen_none_target">Brak</string>
+ <string name="navbar_dialog_title">Wybierz akcję do przypisania</string>
+ <string name="navbar_home_button">Przycisk Home</string>
+ <string name="navbar_recent_button">Przycisk Ostatnie aplikacje</string>
+ <string name="navbar_search_button">Przycisk Szukaj</string>
+ <string name="navbar_back_button">Przycisk Wstecz</string>
+ <string name="navbar_empty_button">Pusty przycisk</string>
+ <string name="navbar_menu_conditional_button">Przycisk Menu (autoukrywaj)</string>
+ <string name="navbar_menu_always_button">Przycisk Menu (zawsze pokazuj)</string>
+ <string name="navbar_menu_big_button">Przycisk Menu</string>
+ <string name="accessibility_dpad_left">Kursor w lewo</string>
+ <string name="accessibility_dpad_right">Kursor w prawo</string>
+ <string name="advanced_dev_option_wipe_app">Usuń dane aplikacji</string>
+ <string name="advanced_dev_option_force_stop">Wymuś zamknięcie</string>
+ <string name="advanced_dev_option_uninstall">Odinstaluj</string>
+ <string name="accessibility_notification_brightness">Jasność światła</string>
+ <string name="accessibility_quick_settings_profiles_off">Profile wyłączone.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profile zostały wyłączone.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil zmieniony na <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicjalizowanie\u2026</string>
+ <string name="led_notification_title">Ustawienia diody</string>
+ <string name="led_notification_text">Diody LED włączone przez ustawienia</string>
+ <string name="qs_tile_edit_header_instruction">Naciśnij i przytrzymaj kafelki, aby zmienić kolejność</string>
+ <string name="quick_settings_edit_label">Edycja kafelków</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Nie można usunąć kafelka edycji</string>
+ <string name="qs_tiles_reset_confirmation">Zresetować ustawienia kafelków szybkiego dostępu do domyślnej konfiguracji?</string>
+ <string name="quick_settings_tile_reset_to_default">Przywróć domyślny układ</string>
+ <string name="quick_settings_title_header">Nagłówek</string>
+ <string name="quick_settings_title_tiles">Kafelki</string>
+ <string name="quick_settings_title_show_weather">Pokaż pogodę</string>
+ <string name="quick_settings_title_show_brightness_slider">Pokaż suwak jasności</string>
+ <string name="quick_settings_title_enlarge_first_row">Powiększenie pierwszego rzędu</string>
+ <string name="screen_pinning_description_no_navbar">Zostaje na widoku do czasu odpięcia. Dotknij i przytrzymaj przycisk Wstecz, aby odpiąć.</string>
+ <string name="quick_settings_custom_tile_detail_title">Kafelek niestandardowy</string>
+ <string name="quick_settings_remove">Usuń kafelek</string>
+ <string name="quick_settings_network_adb_label">ADB przez sieć</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Profile systemowe</string>
+ <string name="quick_settings_profiles_off">Profile wyłączone</string>
+ <string name="quick_settings_heads_up_label">Wyskakujące powiadomienia</string>
+ <string name="quick_settings_battery_saver_label">Oszczędzanie baterii</string>
+ <string name="quick_settings_caffeine_label">Kofeina</string>
+ <string name="accessibility_quick_settings_sync_off">Synchronizacja wyłączona.</string>
+ <string name="accessibility_quick_settings_sync_on">Synchronizacja włączona.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchronizacja została wyłączona.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchronizacja została włączona.</string>
+ <string name="quick_settings_sync_label">Synchronizacja</string>
+ <string name="quick_settings_volume_panel_label">Panel głośności</string>
+ <string name="quick_settings_usb_tether_label">Tethering USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Wygaszanie ekranu</string>
+ <string name="quick_settings_lockscreen_label">Ekran blokady</string>
+ <string name="quick_settings_ambient_display_label">Aktywny wyświetlacz</string>
+ <string name="quick_settings_lockscreen_label_enforced">Blokada ekranu wymuszona</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Wyłączone przez profil</string>
+ <string name="accessibility_quick_settings_screen_timeout">Wygaszanie ekranu: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Wygaszanie ekranu zmieniono na <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Tryb baterii</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Tryb baterii: tryb oszczędzania baterii.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Tryb baterii: tryb zrównoważony.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Tryb baterii: tryb wydajności.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Tryb baterii: tryb wydajności.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Tryb baterii: tryb szybki.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Tryb baterii zmienił się na tryb oszczędzania energii.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Tryb baterii zmienił się na tryb zrównoważony.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Tryb baterii zmienił się na tryb wydajności.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Tryb baterii zmieniony na tryb wydajności.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Tryb baterii zmieniony na tryb szybki.</string>
+ <string name="quick_settings_performance_profile_detail_title">Tryb baterii</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Blokada ekranu wyłączona.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Blokada ekranu włączona.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Blokada ekranu została wyłączona.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Blokada ekranu została włączona.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Aktywny wyświetlacz wyłączony.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Aktywny wyświetlacz włączony.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Aktywny wyświetlacz został wyłączony.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Aktywny wyświetlacz został włączony.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Wyskakujące powiadomienia wyłączone.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Wyskakujące powiadomienia włączone.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Wyskakujące powiadomienia zostały wyłączone.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Wyskakujące powiadomienia zostały włączone.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kofeina wył.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kofeina wł.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Oszczędzanie baterii wył.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Oszczędzanie baterii wł.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Oszczędzanie baterii zostało wył.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Oszczędzanie baterii zostało wł.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamiczne przełączniki</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Następny alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Przełącznik klawiatury</string>
+ <string name="dynamic_qs_tile_su_label">Dostęp do roota</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay wyłączony.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: tryb automatyczny.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: tryb dzienny.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: tryb nocny.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: tryb zewnętrzny.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay został wyłączony.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay zmieniony na tryb automatyczny.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay zmieniony na tryb dzienny.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay zmieniony na tryb nocny.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay zmieniony na tryb zewnętrzny.</string>
+ <string name="quick_settings_title_advanced_location">Trójstanowa lokalizacja</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Raportowanie lokalizacji: tryb oszczędzania baterii.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Raportowanie lokalizacji: tylko czujniki.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Raportowanie lokalizacji: wysoka dokładność.</string>
+ <string name="quick_settings_location_detail_title">Tryb lokalizacji</string>
+ <string name="quick_settings_location_battery_saving_label">Oszczędzanie baterii</string>
+ <string name="quick_settings_location_gps_only_label">Tylko urządzenie</string>
+ <string name="quick_settings_location_high_accuracy_label">Wysoka dokładność</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Zgłaszanie lokalizacji przeszło w tryb oszczędzania energii.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Zgłaszanie lokalizacji przeszło w tryb \"tylko czujniki\".</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Zgłaszanie lokalizacji przeszło w tryb wysokiej dokładności.</string>
+ <string name="quick_settings_tiles_category_system">Kafelki systemowe</string>
+ <string name="quick_settings_tiles_add_tiles">Dodaj kafelek</string>
+ <string name="hotspot_apm_message">Sieć komórkowa jest niedostępna w Trybie samolotowym. Wyłącz go i spróbuj ponownie.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Latarka jest włączona</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Dotknij, aby wyłączyć</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/cm_arrays.xml b/packages/SystemUI/res/values-pt-rBR/cm_arrays.xml
new file mode 100644
index 0000000..cb6fbec
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rBR/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/cm_strings.xml b/packages/SystemUI/res/values-pt-rBR/cm_strings.xml
new file mode 100644
index 0000000..36ae8a2
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rBR/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="tempo">%1$s</xliff:g> - <xliff:g id="condição">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Deslizar para a direita para %1$s</string>
+ <string name="right_shortcut_hint">Deslizar para a esquerda para %1$s</string>
+ <string name="lockscreen_message">Toque em um ícone da esquerda ou da direita para reatribuir o atalho da tela de bloqueio.</string>
+ <string name="lockscreen_default_target">Padrão</string>
+ <string name="select_application">Selecionar aplicativo</string>
+ <string name="lockscreen_choose_action_title">Escolher ação</string>
+ <string name="lockscreen_none_target">Nenhum</string>
+ <string name="navbar_dialog_title">Escolha uma ação para atribuir</string>
+ <string name="navbar_home_button">Botão de início</string>
+ <string name="navbar_recent_button">Botão de recentes</string>
+ <string name="navbar_search_button">Botão de buscar</string>
+ <string name="navbar_back_button">Botão de voltar</string>
+ <string name="navbar_empty_button">Botão vazio</string>
+ <string name="navbar_menu_conditional_button">Botão menu (esconder auto.)</string>
+ <string name="navbar_menu_always_button">Botão menu (sempre visível)</string>
+ <string name="navbar_menu_big_button">Botão menu</string>
+ <string name="accessibility_dpad_left">Cursor à esquerda</string>
+ <string name="accessibility_dpad_right">Cursor à direita</string>
+ <string name="advanced_dev_option_wipe_app">Limpar dados de aplicativos</string>
+ <string name="advanced_dev_option_force_stop">Forçar fechamento</string>
+ <string name="advanced_dev_option_uninstall">Desinstalar</string>
+ <string name="accessibility_notification_brightness">Brilho</string>
+ <string name="accessibility_quick_settings_profiles_off">Perfis desligados.</string>
+ <string name="accessibility_quick_settings_profiles">Perfil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Perfis foram desligados.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Perfil alterado para <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicializando\u2026</string>
+ <string name="led_notification_title">Configurações de luz</string>
+ <string name="led_notification_text">Luz de LED ativada pelas configurações</string>
+ <string name="qs_tile_edit_header_instruction">Pressione e segure os botões para reorganizar</string>
+ <string name="quick_settings_edit_label">Editar botões</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Não é possível excluir o botão de Edição</string>
+ <string name="qs_tiles_reset_confirmation">Redefinir botões das configurações rápidas para o padrão?</string>
+ <string name="quick_settings_tile_reset_to_default">Redefinir para a organização padrão</string>
+ <string name="quick_settings_title_header">Cabeçalho</string>
+ <string name="quick_settings_title_tiles">Botões</string>
+ <string name="quick_settings_title_show_weather">Mostrar tempo</string>
+ <string name="quick_settings_title_show_brightness_slider">Mostrar o controle deslizante de brilho</string>
+ <string name="quick_settings_title_enlarge_first_row">Ampliar a primeira linha</string>
+ <string name="screen_pinning_description_no_navbar">Isto manterá-la na tela até você desafixar. Toque e segure o botão Voltar para desafixar.</string>
+ <string name="quick_settings_custom_tile_detail_title">Botão personalizado</string>
+ <string name="quick_settings_remove">Remover botão</string>
+ <string name="quick_settings_network_adb_label">ADB sobre rede</string>
+ <string name="quick_settings_compass_label">Bússola</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Perfis de sistema</string>
+ <string name="quick_settings_profiles_off">Perfis desativados</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Economizador de bateria</string>
+ <string name="quick_settings_caffeine_label">Cafeína</string>
+ <string name="accessibility_quick_settings_sync_off">Sincr. desl.</string>
+ <string name="accessibility_quick_settings_sync_on">Sincr. lig.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sincronização desligada.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sincronização ligada.</string>
+ <string name="quick_settings_sync_label">Sincronização</string>
+ <string name="quick_settings_volume_panel_label">Painel de volume</string>
+ <string name="quick_settings_usb_tether_label">Tethering USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Tempo limite de tela</string>
+ <string name="quick_settings_lockscreen_label">Tela de bloqueio</string>
+ <string name="quick_settings_ambient_display_label">Tela ambiente</string>
+ <string name="quick_settings_lockscreen_label_enforced">Tela de bloqueio imposta</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Desativado pelo perfil</string>
+ <string name="accessibility_quick_settings_screen_timeout">Tempo limite da tela: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Tempo limite da tela alterado para <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Modo de bateria</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Modo de bateria: modo de economia de energia.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Modo de bateria: modo equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Modo de bateria: modo de desempenho.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Modo de bateria: modo eficiente.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Modo de bateria: modo rápido.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Modo de bateria alterado para o modo de economia de energia.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Modo de bateria alterado para o modo equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Modo de bateria alterado para o modo de desempenho.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Modo de bateria alterado para o modo eficiente.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Modo de bateria alterado para o modo rápido.</string>
+ <string name="quick_settings_performance_profile_detail_title">Modo de bateria</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Tela de bloqueio desligada.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Tela de bloqueio ligada.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Tela de bloqueio foi desligada.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Tela de bloqueio foi ligada.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Tela ambiente desativado.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Tela ambiente ativado.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Tela ambiente desligado.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Tela ambiente ligado.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up desativado.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up ativado.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up desligado.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up ligado.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Cafeína desligado.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Cafeína ligado.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Economizador de bateria desligado.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Economizador de bateria ligado.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">O economizador de bateria foi desligado.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">O economizador de bateria foi ligado.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Botões dinâmicos</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Próximo alarme</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Seletor de IME</string>
+ <string name="dynamic_qs_tile_su_label">Acesso super-usuário</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay desligado.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modo dia.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modo noite.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modo ao ar livre.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay foi desligado.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay alterado para modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay alterado para modo dia.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay alterado para modo noite.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay alterado para modo ao ar livre.</string>
+ <string name="quick_settings_title_advanced_location">Localização em 3 estados</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Localização: economia de bateria.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Localização: apenas no dispositivo.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Localização: alta precisão.</string>
+ <string name="quick_settings_location_detail_title">Modo de localização</string>
+ <string name="quick_settings_location_battery_saving_label">Economia de bateria</string>
+ <string name="quick_settings_location_gps_only_label">Apenas no dispositivo</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precisão</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Modo de localização alterado para apenas Wi-Fi e redes móveis.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Modo de localização alterado para apenas GPS.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Modo de localização alterado para GPS, Wi-Fi e redes móveis.</string>
+ <string name="quick_settings_tiles_category_system">Botões de sistema</string>
+ <string name="quick_settings_tiles_add_tiles">Adicionar um botão</string>
+ <string name="hotspot_apm_message">Não é possível se conectar a redes móveis enquanto o Modo Avião estiver ativado. Desative o modo avião e tente novamente.</string>
+ <string name="quick_settings_tile_flashlight_not_title">A lanterna está ligada</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Toque para desligar</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/cm_arrays.xml b/packages/SystemUI/res/values-pt-rPT/cm_arrays.xml
new file mode 100644
index 0000000..cb6fbec
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rPT/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SO</item>
+ <item>O</item>
+ <item>NO</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/cm_strings.xml b/packages/SystemUI/res/values-pt-rPT/cm_strings.xml
new file mode 100644
index 0000000..0e1fd11
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rPT/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Deslizar para a direita para %1$s</string>
+ <string name="right_shortcut_hint">Deslizar para a esquerda para %1$s</string>
+ <string name="lockscreen_message">Toque num ícone da esquerda ou da direita para atribuir um atalho no ecrã de bloqueio.</string>
+ <string name="lockscreen_default_target">Padrão</string>
+ <string name="select_application">Selecionar aplicação</string>
+ <string name="lockscreen_choose_action_title">Selecionar ação</string>
+ <string name="lockscreen_none_target">Nenhum</string>
+ <string name="navbar_dialog_title">Escolha uma ação para atribuir</string>
+ <string name="navbar_home_button">Botão Home</string>
+ <string name="navbar_recent_button">Botão Recentes</string>
+ <string name="navbar_search_button">Botão Pesquisa</string>
+ <string name="navbar_back_button">Botão Voltar</string>
+ <string name="navbar_empty_button">Botão vazio</string>
+ <string name="navbar_menu_conditional_button">Botão Menu (esconder auto)</string>
+ <string name="navbar_menu_always_button">Botão Menu (sempre visível)</string>
+ <string name="navbar_menu_big_button">Botão Menu</string>
+ <string name="accessibility_dpad_left">Cursor à esquerda</string>
+ <string name="accessibility_dpad_right">Cursor à direita</string>
+ <string name="advanced_dev_option_wipe_app">Limpar dados da aplicação</string>
+ <string name="advanced_dev_option_force_stop">Forçar paragem</string>
+ <string name="advanced_dev_option_uninstall">Desinstalar</string>
+ <string name="accessibility_notification_brightness">Brilho</string>
+ <string name="accessibility_quick_settings_profiles_off">Perfis desligados.</string>
+ <string name="accessibility_quick_settings_profiles">Perfil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Perfis foram desligados.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Perfil alterado para <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">A iniciar\u2026</string>
+ <string name="led_notification_title">Definições de luz</string>
+ <string name="led_notification_text">Luz do LED ativada pelas definições</string>
+ <string name="qs_tile_edit_header_instruction">Pressione e segure os mosaicos para reorganizar</string>
+ <string name="quick_settings_edit_label">Editar os mosaicos</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Não é possível eliminar o mosaico de Editar</string>
+ <string name="qs_tiles_reset_confirmation">Repor os valores de origem dos mosaicos de definições rápidas?</string>
+ <string name="quick_settings_tile_reset_to_default">Restaurar a disposição padrão</string>
+ <string name="quick_settings_title_header">Cabeçalho</string>
+ <string name="quick_settings_title_tiles">Mosaicos</string>
+ <string name="quick_settings_title_show_weather">Mostrar o tempo</string>
+ <string name="quick_settings_title_show_brightness_slider">Mostrar o controlo deslizante de brilho</string>
+ <string name="quick_settings_title_enlarge_first_row">Ampliar a primeira linha</string>
+ <string name="screen_pinning_description_no_navbar">Isto mantém visível até soltar. Toque e segure o botão Voltar até soltar.</string>
+ <string name="quick_settings_custom_tile_detail_title">Mosaicos personalizados</string>
+ <string name="quick_settings_remove">Remover mosaico</string>
+ <string name="quick_settings_network_adb_label">ADB através da rede</string>
+ <string name="quick_settings_compass_label">Bússola</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Perfis de sistema</string>
+ <string name="quick_settings_profiles_off">Perfis desativados</string>
+ <string name="quick_settings_heads_up_label">Notificações pop-up</string>
+ <string name="quick_settings_battery_saver_label">Economizador de bateria</string>
+ <string name="quick_settings_caffeine_label">Cafeína</string>
+ <string name="accessibility_quick_settings_sync_off">Sincronização desligada.</string>
+ <string name="accessibility_quick_settings_sync_on">Sincronização ligada.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sincronização foi desligada.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sincronização foi ligada.</string>
+ <string name="quick_settings_sync_label">Sincronização</string>
+ <string name="quick_settings_volume_panel_label">Painel de volume</string>
+ <string name="quick_settings_usb_tether_label">Partilha de internet por USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Tempo limite do ecrã</string>
+ <string name="quick_settings_lockscreen_label">Ecrã de bloqueio</string>
+ <string name="quick_settings_ambient_display_label">Visualização de ambiente</string>
+ <string name="quick_settings_lockscreen_label_enforced">Ecrã de bloqueio forçado</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Desativado pelo perfil</string>
+ <string name="accessibility_quick_settings_screen_timeout">Tempo limite do ecrã: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Tempo limite do ecrã alterado para <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Modo de bateria</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Modo de bateria: modo de poupança de energia.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Modo de bateria: modo equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Modo de bateria: modo de desempenho.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Modo de bateria: modo de eficiência.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Modo de bateria: modo rápido.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Modo de bateria alterado para o modo de poupança de energia.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Modo de bateria alterado para o modo equilibrado.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Modo de bateria alterado para o modo de desempenho.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Modo de bateria alterado para o modo de eficiência.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Modo de bateria alterado para o modo rápido.</string>
+ <string name="quick_settings_performance_profile_detail_title">Modo de bateria</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Ecrã de bloqueio desligado.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Ecrã de bloqueio ligado.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Ecrã de bloqueio foi desligado.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Ecrã de bloqueio foi ligado.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Visualização de ambiente desligada.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Visualização de ambiente ligada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">A visualização de ambiente foi desligada.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">A visualização de ambiente foi ligada.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Notificações pop-up desligadas.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Notificações pop-up ligadas.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Notificações pop-up desligaram.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Notificações pop-up ligaram.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Cafeína desligada.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Cafeína ligada.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Economizador de bateria desligado.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Economizador de bateria ligado.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">O economizador de bateria desligou.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">O economizador de bateria ligou.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Mosaicos dinâmicos</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Próximo alarme</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Seletor de método de entrada</string>
+ <string name="dynamic_qs_tile_su_label">Acesso root</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay desligado.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: modo dia.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: modo noite.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: modo exterior.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay foi desligado.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay alterado para modo automático.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay alterado para modo dia.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay alterado para modo noite.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay alterado para modo exterior.</string>
+ <string name="quick_settings_title_advanced_location">Localização com 3 estados</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Localização: poupança de bateria.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Localização: apenas dispositivo.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Localização: alta precisão.</string>
+ <string name="quick_settings_location_detail_title">Modos de localização</string>
+ <string name="quick_settings_location_battery_saving_label">Poupança de bateria</string>
+ <string name="quick_settings_location_gps_only_label">Apenas dispositivo</string>
+ <string name="quick_settings_location_high_accuracy_label">Alta precisão</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Modo de localização alterado para poupança de bateria.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Modo de localização alterado para apenas dispositivo.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Modo de localização alterado para alta precisão.</string>
+ <string name="quick_settings_tiles_category_system">Mosaicos do sistema</string>
+ <string name="quick_settings_tiles_add_tiles">Adicionar um mosaico</string>
+ <string name="hotspot_apm_message">Não é possível ligar-se a redes móveis enquanto o modo de avião estiver ativo. Desative o modo de avião e tente novamente.</string>
+ <string name="quick_settings_tile_flashlight_not_title">A lanterna está ligada</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Toque para desligar</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ro/cm_arrays.xml b/packages/SystemUI/res/values-ro/cm_arrays.xml
new file mode 100644
index 0000000..91744501
--- /dev/null
+++ b/packages/SystemUI/res/values-ro/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>NV</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ro/cm_strings.xml b/packages/SystemUI/res/values-ro/cm_strings.xml
new file mode 100644
index 0000000..83531ab
--- /dev/null
+++ b/packages/SystemUI/res/values-ro/cm_strings.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Glisați dreapta pentru %1$s</string>
+ <string name="right_shortcut_hint">Glisați stânga pentru %1$s</string>
+ <string name="lockscreen_default_target">Implicit</string>
+ <string name="select_application">Selectați aplicația</string>
+ <string name="lockscreen_choose_action_title">Alege acțiunea</string>
+ <string name="lockscreen_none_target">Nimic</string>
+ <string name="navbar_dialog_title">Alege o acțiune pentru a o asocia</string>
+ <string name="navbar_home_button">Butonul Acasă</string>
+ <string name="navbar_recent_button">Butonul Recent</string>
+ <string name="navbar_search_button">Butonul Căutare</string>
+ <string name="navbar_back_button">Butonul Înapoi</string>
+ <string name="navbar_empty_button">Buton disponibil</string>
+ <string name="navbar_menu_conditional_button">Buton (ascundeAutomat) Meniu</string>
+ <string name="navbar_menu_always_button">Buton (afișareÎntotdeauna) Meniu</string>
+ <string name="navbar_menu_big_button">Buton Meniu</string>
+ <string name="accessibility_dpad_left">Cursor stânga</string>
+ <string name="accessibility_dpad_right">Cursor dreapta</string>
+ <string name="advanced_dev_option_wipe_app">Șterge datele aplicației</string>
+ <string name="advanced_dev_option_force_stop">Oprire forțată</string>
+ <string name="advanced_dev_option_uninstall">Dezinstalați</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiluri oprit.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiluri este activat.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil schimbat în <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inițializare\u2026</string>
+ <string name="led_notification_title">Setări de lumină</string>
+ <string name="qs_tile_edit_header_instruction">Apăsați și țineți apăsate chenarele pentru a rearanja</string>
+ <string name="quick_settings_edit_label">Editare chenare</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Nu se poate șterge chenarul Editare</string>
+ <string name="qs_tiles_reset_confirmation">Resetați chenarele cu setări rapide la configurația implicită?</string>
+ <string name="quick_settings_tile_reset_to_default">Resetare la aspectul implicit</string>
+ <string name="quick_settings_title_header">Antet</string>
+ <string name="quick_settings_title_tiles">Chenare</string>
+ <string name="quick_settings_title_show_weather">Arată vremea</string>
+ <string name="quick_settings_title_show_brightness_slider">Arată glisorul de luminozitate</string>
+ <string name="quick_settings_custom_tile_detail_title">Chenar personalizat</string>
+ <string name="quick_settings_remove">Eliminare chenar</string>
+ <string name="quick_settings_network_adb_label">ADB prin rețea</string>
+ <string name="quick_settings_compass_label">Busolă</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Profiluri de sistem</string>
+ <string name="quick_settings_profiles_off">Profilurile sunt dezactivate</string>
+ <string name="quick_settings_heads_up_label">Atenționare</string>
+ <string name="quick_settings_battery_saver_label">Economizor baterie</string>
+ <string name="quick_settings_caffeine_label">Cofeină</string>
+ <string name="accessibility_quick_settings_sync_off">Sincronizare oprită.</string>
+ <string name="accessibility_quick_settings_sync_on">Sincronizare pornită.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sincronizare oprită.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sincronizare pornită.</string>
+ <string name="quick_settings_sync_label">Sincronizare</string>
+ <string name="quick_settings_volume_panel_label">Panou volum</string>
+ <string name="quick_settings_usb_tether_label">Tethering USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Timpul de expirare ecran</string>
+ <string name="quick_settings_lockscreen_label">Ecran de blocare</string>
+ <string name="quick_settings_ambient_display_label">Afișare ambientală</string>
+ <string name="quick_settings_lockscreen_label_enforced">Blocare ecran impusă</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Dezactivat de profil</string>
+ <string name="accessibility_quick_settings_screen_timeout">Timp expirare ecran: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Timp expirare ecran a fost schimbat la <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Mod baterie</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Mod baterie: mod de salvare energie.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Mod baterie: mod echilibrat.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Mod baterie: mod performanță.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Mod baterie: mod eficiență.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Mod baterie: mod rapid.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Modul bateriei a fost schimbat în modul de salvare energie.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Modul bateriei a fost schimbat în mod echilibrat.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Modul bateriei schimbat în modul de performanță.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Modul bateriei a fost schimbat în modul de eficiență.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Modul bateriei a fost schimbat în modul rapid.</string>
+ <string name="quick_settings_performance_profile_detail_title">Mod baterie</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Blocare ecran oprit.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Blocare ecran pornit.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Afișare ambientală oprită.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Afișare ambientală pornită.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Cofeină oprit.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Cofeină pornit.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Economisire baterie oprită.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Economisire baterie pornită.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Economisire baterie este dezactivată.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Economisire baterie este activată.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Chenar dinamic</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Următoarea alarmă</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Selector IME</string>
+ <string name="dynamic_qs_tile_su_label">Acces root</string>
+ <string name="quick_settings_title_advanced_location">Starea celor 3 moduri de locație</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Raportarea locației: mod economisire baterie.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Raportarea locației: doar senzori.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Raportarea locației: precizie ridicată.</string>
+ <string name="quick_settings_location_detail_title">Mod localizare</string>
+ <string name="quick_settings_location_battery_saving_label">Economisire baterie</string>
+ <string name="quick_settings_location_gps_only_label">Doar dispozitiv</string>
+ <string name="quick_settings_location_high_accuracy_label">Precizie ridicată</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Raportarea locației modificată în modul economisire baterie.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Raportarea locației modificată în modul doar senzori.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Raportarea locației modificată în modul precizie ridicată.</string>
+ <string name="quick_settings_tiles_category_system">Chenar sistem</string>
+ <string name="quick_settings_tiles_add_tiles">Adaugă un chenar</string>
+ <string name="hotspot_apm_message">Nu se poate conecta la rețele mobile în timp ce modul Avion este activat. Dezactivați modul Avion și încercați din nou.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Lanterna este pornită</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Atingeți pentru a dezactiva</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ru/cm_arrays.xml b/packages/SystemUI/res/values-ru/cm_arrays.xml
new file mode 100644
index 0000000..2e58d85
--- /dev/null
+++ b/packages/SystemUI/res/values-ru/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>С</item>
+ <item>СВ</item>
+ <item>В</item>
+ <item>ЮВ</item>
+ <item>Ю</item>
+ <item>ЮЗ</item>
+ <item>З</item>
+ <item>СЗ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ru/cm_strings.xml b/packages/SystemUI/res/values-ru/cm_strings.xml
new file mode 100644
index 0000000..919c2e0
--- /dev/null
+++ b/packages/SystemUI/res/values-ru/cm_strings.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Проведите вправо, чтобы открыть приложение «%1$s»</string>
+ <string name="right_shortcut_hint">Проведите влево, чтобы открыть приложение «%1$s»</string>
+ <string name="lockscreen_message">Нажмите значок слева или справа для изменения ярлыка экрана блокировки.</string>
+ <string name="lockscreen_default_target">По умолчанию</string>
+ <string name="select_application">Выбор приложения</string>
+ <string name="lockscreen_choose_action_title">Выбор действия</string>
+ <string name="lockscreen_none_target">Ничего</string>
+ <string name="navbar_dialog_title">Выберите действие</string>
+ <string name="navbar_home_button">Домой</string>
+ <string name="navbar_recent_button">Запущ. приложения</string>
+ <string name="navbar_search_button">Поиск</string>
+ <string name="navbar_back_button">Назад</string>
+ <string name="navbar_empty_button">Пустая кнопка</string>
+ <string name="navbar_menu_conditional_button">Меню (если доступно)</string>
+ <string name="navbar_menu_always_button">Меню (всегда)</string>
+ <string name="navbar_menu_big_button">Меню</string>
+ <string name="accessibility_dpad_left">Курсор влево</string>
+ <string name="accessibility_dpad_right">Курсор вправо</string>
+ <string name="advanced_dev_option_wipe_app">Стереть данные</string>
+ <string name="advanced_dev_option_force_stop">Остановить</string>
+ <string name="advanced_dev_option_uninstall">Удалить</string>
+ <string name="accessibility_notification_brightness">Яркость</string>
+ <string name="accessibility_quick_settings_profiles_off">Профили выключены.</string>
+ <string name="accessibility_quick_settings_profiles">Профиль: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Профили выключены.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Профиль изменён на <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Включение\u2026</string>
+ <string name="led_notification_title">Индикатор событий</string>
+ <string name="led_notification_text">Светодиод включен в настройках</string>
+ <string name="qs_tile_edit_header_instruction">Нажмите и удерживайте плитку для её перемещения</string>
+ <string name="quick_settings_edit_label">Изменить плитки</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Невозможно удалить кнопку редактирования</string>
+ <string name="qs_tiles_reset_confirmation">Восстановить набор плиток по умолчанию?</string>
+ <string name="quick_settings_tile_reset_to_default">Восстановить стандартные</string>
+ <string name="quick_settings_title_header">Заголовок</string>
+ <string name="quick_settings_title_tiles">Плитки</string>
+ <string name="quick_settings_title_show_weather">Сведения о погоде</string>
+ <string name="quick_settings_title_show_brightness_slider">Показывать регулятор яркости</string>
+ <string name="quick_settings_title_enlarge_first_row">Увеличить первый ряд</string>
+ <string name="screen_pinning_description_no_navbar">Это приложение останется активным, пока вы не отмените блокировку долгим нажатием кнопки «Назад».</string>
+ <string name="quick_settings_custom_tile_detail_title">Пользовательская плитка</string>
+ <string name="quick_settings_remove">Удалить плитку</string>
+ <string name="quick_settings_network_adb_label">Отладка по сети</string>
+ <string name="quick_settings_compass_label">Компас</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Системные профили</string>
+ <string name="quick_settings_profiles_off">Профили отключены</string>
+ <string name="quick_settings_heads_up_label">Всплывающие уведомления</string>
+ <string name="quick_settings_battery_saver_label">Энергосбережение</string>
+ <string name="accessibility_quick_settings_sync_off">Синхронизация отключена.</string>
+ <string name="accessibility_quick_settings_sync_on">Синхронизация включена.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Синхронизация отключена.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Синхронизация включена.</string>
+ <string name="quick_settings_sync_label">Синхронизация</string>
+ <string name="quick_settings_volume_panel_label">Панель громкости</string>
+ <string name="quick_settings_usb_tether_label">USB-модем</string>
+ <string name="quick_settings_screen_timeout_detail_title">Задержка отключения экрана</string>
+ <string name="quick_settings_lockscreen_label">Экран блокировки</string>
+ <string name="quick_settings_ambient_display_label">Индикация событий</string>
+ <string name="quick_settings_lockscreen_label_enforced">Блокировка экрана включена</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Отключено профилем</string>
+ <string name="accessibility_quick_settings_screen_timeout">Время до выключения экрана: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Время до выключения экрана изменено на <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Энергопотребление</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Режим энергопотребления: экономия энергии.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Режим энергопотребления: сбалансированный.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Режим энергопотребления: высокая производительность.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Режим энергопотребления: энергоэффективный.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Режим энергопотребления: оптимальная производительность.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Режим энергопотребления изменён на режим экономии энергии.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Режим энергопотребления изменён на сбалансированный.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Режим энергопотребления изменён на режим высокой производительности.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Режим энергопотребления изменён на энергоэффективный.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Режим энергопотребления изменён на режим оптимальной производительности.</string>
+ <string name="quick_settings_performance_profile_detail_title">Энергопотребление</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Экран блокировки выключен.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Экран блокировки включён.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Экран блокировки выключен.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Экран блокировки включён.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Индикация событий экраном отключена.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Индикация событий экраном включена.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Индикация событий экраном отключена.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Индикация событий экраном включена.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Всплывающие уведомления отключены.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Всплывающие уведомления включены.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Всплывающие уведомления отключены.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Всплывающие уведомления включены.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Режим энергосбережения выключен.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Режим энергосбережения включён.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Режим энергосбережения выключен.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Режим энергосбережения включён.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Динамическая плитка</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Следующий будильник</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Выбор метода ввода</string>
+ <string name="dynamic_qs_tile_su_label">Суперпользователь</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay выключен.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay работает в автоматическом режиме.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay работает в дневном режиме.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay работает в ночном режиме.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay работает в режиме «на улице».</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay выключен.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay переключён в автоматический режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay переключён в дневной режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay переключён в ночной режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay переключён в режим «на улице».</string>
+ <string name="quick_settings_title_advanced_location">Параметры отправки геоданных</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Отправка местоположения: режим экономии батареи.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Отправка местоположения: только по GPS.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Отправка местоположения: режим высокой точности.</string>
+ <string name="quick_settings_location_detail_title">Определение местоположения</string>
+ <string name="quick_settings_location_battery_saving_label">По координатам сети</string>
+ <string name="quick_settings_location_gps_only_label">По спутникам GPS</string>
+ <string name="quick_settings_location_high_accuracy_label">По всем источникам</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Служба отправки местоположения переключена в режим экономии батареи.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Для отправки местоположения используются только данные GPS.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Служба отправки местоположения переключена в режим высокой точности.</string>
+ <string name="quick_settings_tiles_category_system">Системные плитки</string>
+ <string name="quick_settings_tiles_add_tiles">Добавление плитки</string>
+ <string name="hotspot_apm_message">Подключение к мобильной сети невозможно, пока включён режим полёта. Отключите его, а затем повторите попытку.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Фонарик включён</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Нажмите для отключения</string>
+</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/cm_arrays.xml b/packages/SystemUI/res/values-si-rLK/cm_arrays.xml
new file mode 100644
index 0000000..e25e89b
--- /dev/null
+++ b/packages/SystemUI/res/values-si-rLK/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>උතුර</item>
+ <item>ඊශාන</item>
+ <item>නැගෙනහිර</item>
+ <item>ගිනිකොන</item>
+ <item>දකුණ</item>
+ <item>නිරිත</item>
+ <item>බටහිර</item>
+ <item>වයඹ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/cm_strings.xml b/packages/SystemUI/res/values-si-rLK/cm_strings.xml
new file mode 100644
index 0000000..1cb2423
--- /dev/null
+++ b/packages/SystemUI/res/values-si-rLK/cm_strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="navbar_dialog_title">පැවරීමට ක්‍රියාවක් තෝරන්න</string>
+ <string name="navbar_home_button">නිවස බොත්තම</string>
+ <string name="navbar_recent_button">මෑත බොත්තම</string>
+ <string name="navbar_search_button">සොයන්න බොත්තම</string>
+ <string name="navbar_back_button">ආපසු බොත්තම</string>
+ <string name="navbar_menu_conditional_button">මෙනුව (ඉබේ වැසෙන) බොත්තම</string>
+ <string name="navbar_menu_always_button">මෙනුව (නිතර පෙනෙන) බොත්තම</string>
+ <string name="navbar_menu_big_button">මෙනුව බොත්තම</string>
+ <string name="accessibility_dpad_left">වම් කර්සරය</string>
+ <string name="accessibility_dpad_right">දකුණු කර්සරය</string>
+ <string name="advanced_dev_option_wipe_app">යෙදුම් දත්ත පිහින්න</string>
+ <string name="advanced_dev_option_force_stop">බලෙන් නවත්වන්න</string>
+ <string name="advanced_dev_option_uninstall">අස්ථාපනය කරන්න</string>
+ <string name="quick_settings_compass_init">අරඹමින්\u2026</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sk/cm_arrays.xml b/packages/SystemUI/res/values-sk/cm_arrays.xml
new file mode 100644
index 0000000..ca2178e
--- /dev/null
+++ b/packages/SystemUI/res/values-sk/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>JV</item>
+ <item>J</item>
+ <item>JZ</item>
+ <item>Z</item>
+ <item>SZ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-sk/cm_strings.xml b/packages/SystemUI/res/values-sk/cm_strings.xml
new file mode 100644
index 0000000..6be4ea1
--- /dev/null
+++ b/packages/SystemUI/res/values-sk/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Potiahnite doprava pre %1$s</string>
+ <string name="right_shortcut_hint">Potiahnite doľava pre %1$s</string>
+ <string name="select_application">Vyberte aplikáciu</string>
+ <string name="lockscreen_choose_action_title">Vyberte akciu</string>
+ <string name="lockscreen_none_target">Žiadna</string>
+ <string name="navbar_dialog_title">Vyberte akciu na priradenie</string>
+ <string name="navbar_home_button">Tlačidlo Domov</string>
+ <string name="navbar_recent_button">Tlačidlo Nedávne</string>
+ <string name="navbar_search_button">Tlačidlo Hľadať</string>
+ <string name="navbar_back_button">Tlačidlo Späť</string>
+ <string name="navbar_empty_button">Prázdne tlačidlo</string>
+ <string name="navbar_menu_conditional_button">Tlačidlo Ponuka (automaticky skrývané)</string>
+ <string name="navbar_menu_always_button">Tlačidlo Ponuka (vždy viditeľné)</string>
+ <string name="navbar_menu_big_button">Tlačidlo Ponuka</string>
+ <string name="accessibility_dpad_left">Kurzor vľavo</string>
+ <string name="accessibility_dpad_right">Kurzor vpravo</string>
+ <string name="advanced_dev_option_wipe_app">Vymazať údaje aplikácie</string>
+ <string name="advanced_dev_option_force_stop">Vynútiť zastavenie</string>
+ <string name="advanced_dev_option_uninstall">Odinštalovať</string>
+ <string name="accessibility_quick_settings_profiles_off">Profily vyp.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profily vypnuté.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil sa zmenil na <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Inicializácia\u2026</string>
+ <string name="screen_pinning_description_no_navbar">Zobrazenie aktuálnej obrazovky je zaistené, dokým ju neuvoľníte. Dotknite a podržte tlačidlo Späť pre uvoľnenie.</string>
+ <string name="quick_settings_custom_tile_detail_title">Vlastná dlaždica</string>
+ <string name="quick_settings_remove">Odstrániť dlaždicu</string>
+ <string name="quick_settings_network_adb_label">ADB cez sieť</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systémové profily</string>
+ <string name="quick_settings_profiles_off">Profily zakázané</string>
+ <string name="quick_settings_heads_up_label">Plávajúce oznámenia</string>
+ <string name="quick_settings_battery_saver_label">Šetrič batérie</string>
+ <string name="accessibility_quick_settings_sync_off">Synch. vyp.</string>
+ <string name="accessibility_quick_settings_sync_on">Synch. zap.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synchronizácia vypnutá.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synchronizácia zapnutá.</string>
+ <string name="quick_settings_sync_label">Synchronizácia</string>
+ <string name="quick_settings_volume_panel_label">Panel hlasitosti</string>
+ <string name="quick_settings_usb_tether_label">Zdieľanie cez USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Časový limit obrazovky</string>
+ <string name="quick_settings_lockscreen_label">Obrazovka uzamknutia</string>
+ <string name="quick_settings_ambient_display_label">Ambientné zobrazenie</string>
+ <string name="quick_settings_lockscreen_label_enforced">Obrazovka uzamknutia povolená</string>
+ <string name="accessibility_quick_settings_screen_timeout">Časový limit obrazovky: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Časový limit obrazovky sa zmenil na <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Režim batérie</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Režim batérie: režim šetrenia energie.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Režim batérie: vyvážený režim.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Režim batérie: režim výkonu.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Režim batérie: efektívny režim.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Režim batérie: rýchly režim.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Režim batérie sa zmenil na režim šetrenia energie.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Režim batérie sa zmenil na vyvážený režim.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Režim batérie sa zmenil na režim výkonu.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Režim batérie sa zmenil na efektívny režim.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Režim batérie sa zmenil na výkonný režim.</string>
+ <string name="quick_settings_performance_profile_detail_title">Režim batérie</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Obrazovka uzamknutia vyp.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Obrazovka uzamknutia zap.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Obrazovka uzamknutia vypnutá.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Obrazovka uzamknutia zapnutá.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambientné zobrazenie povolené.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambientné zobrazenie zakázané.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambientné zobrazenie povolené.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambientné zobrazenie zakázané.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Plávajúce oznámenia zakázané.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Plávajúce oznámenia povolené.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Plávajúce oznámenia zakázané.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Plávajúce oznámenia povolené.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Šetrič batérie vypnutý.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Šetrič batérie zapnutý.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Šetrič batérie vypnutý.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Šetrič batérie zapnutý.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamické dlaždice</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Ďalší budík</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Výber IME</string>
+ <string name="dynamic_qs_tile_su_label">Root prístup</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay vyp.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automatický režim.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: denný režim.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nočný režim.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: režim vonku.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay vypnutý.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay sa zmenil na automatický režim.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay sa zmenil na denný režim.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay sa zmenil na nočný režim.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay sa zmenil na režim vonku.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Hlásenie polohy: režim šetrenia batérie.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Hlásenie polohy: režim iba so snímačmi.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Hlásenie polohy: režim vysokej presnosti.</string>
+ <string name="quick_settings_location_detail_title">Režimy polohy</string>
+ <string name="quick_settings_location_battery_saving_label">Šetrenie batérie</string>
+ <string name="quick_settings_location_gps_only_label">Iba zariadenie</string>
+ <string name="quick_settings_location_high_accuracy_label">Vysoká presnosť</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Hlásenie polohy sa zmenilo na režim šetrenia batérie.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Hlásenie polohy sa zmenilo na režim iba senzorov.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Hlásenie polohy sa zmenilo na režim vysokej presnosti.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sl/cm_arrays.xml b/packages/SystemUI/res/values-sl/cm_arrays.xml
new file mode 100644
index 0000000..ca2178e
--- /dev/null
+++ b/packages/SystemUI/res/values-sl/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>JV</item>
+ <item>J</item>
+ <item>JZ</item>
+ <item>Z</item>
+ <item>SZ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-sl/cm_strings.xml b/packages/SystemUI/res/values-sl/cm_strings.xml
new file mode 100644
index 0000000..ac3c894
--- /dev/null
+++ b/packages/SystemUI/res/values-sl/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Povlecite desno za %1$s</string>
+ <string name="right_shortcut_hint">Povlecite levo za %1$s</string>
+ <string name="lockscreen_message">Tapnite ikono na levi ali desni, da ponovno dodelite bližnjico zaslona za zaklepanje.</string>
+ <string name="lockscreen_default_target">Privzeto</string>
+ <string name="select_application">Izberite aplikacijo</string>
+ <string name="lockscreen_choose_action_title">Izberite dejanje</string>
+ <string name="lockscreen_none_target">Brez</string>
+ <string name="navbar_dialog_title">Izberite dejanje za dodelitev</string>
+ <string name="navbar_home_button">Gumb Domov</string>
+ <string name="navbar_recent_button">Gumb Nedavno</string>
+ <string name="navbar_search_button">Gumb Iskanje</string>
+ <string name="navbar_back_button">Gumb Nazaj</string>
+ <string name="navbar_empty_button">Gumb Prazno</string>
+ <string name="navbar_menu_conditional_button">Menijski gumb (sam. skrivanje)</string>
+ <string name="navbar_menu_always_button">Menijski gumb (vedno prikaži)</string>
+ <string name="navbar_menu_big_button">Menijski gumb</string>
+ <string name="accessibility_dpad_left">Kazalec levo</string>
+ <string name="accessibility_dpad_right">Kazalec desno</string>
+ <string name="advanced_dev_option_wipe_app">Izbriši podatke aplikacije</string>
+ <string name="advanced_dev_option_force_stop">Vsili ustavitev</string>
+ <string name="advanced_dev_option_uninstall">Odstrani</string>
+ <string name="accessibility_notification_brightness">Svetlost lučke</string>
+ <string name="accessibility_quick_settings_profiles_off">Profili izklopljeni.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profili izklopljeni.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil spremenjen v <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Začenjanje \u2026</string>
+ <string name="led_notification_title">Nastavitve lučke</string>
+ <string name="led_notification_text">Lučka LED omogočena v nastavitvah</string>
+ <string name="qs_tile_edit_header_instruction">Pritisnite in pridržite ploščice za preurejanje</string>
+ <string name="quick_settings_edit_label">Uredi ploščice</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Ploščice za urejanje ni mogoče izbrisati</string>
+ <string name="qs_tiles_reset_confirmation">Ponastavi ploščice hitrih nastavitev na privzeto nastavitev?</string>
+ <string name="quick_settings_tile_reset_to_default">Ponastavi na privzeto razporeditev</string>
+ <string name="quick_settings_title_header">Glava</string>
+ <string name="quick_settings_title_tiles">Ploščice</string>
+ <string name="quick_settings_title_show_weather">Prikaži vreme</string>
+ <string name="quick_settings_title_show_brightness_slider">Prikaži drsnik za svetlost</string>
+ <string name="quick_settings_title_enlarge_first_row">Povečaj prvo vrstico</string>
+ <string name="screen_pinning_description_no_navbar">To jo ohrani prikazano, dokler je ne odpnete. Tapnite in pridržite gumb Nazaj, da jo odpnete.</string>
+ <string name="quick_settings_custom_tile_detail_title">Ploščica po meri</string>
+ <string name="quick_settings_remove">Odstrani ploščico</string>
+ <string name="quick_settings_network_adb_label">ADB preko omrežja</string>
+ <string name="quick_settings_compass_label">Kompas</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Sistemski profili</string>
+ <string name="quick_settings_profiles_off">Profili onemogočeni</string>
+ <string name="quick_settings_heads_up_label">Obvestila na zaslonu</string>
+ <string name="quick_settings_battery_saver_label">Ohranjevalnik baterije</string>
+ <string name="quick_settings_caffeine_label">Kofein</string>
+ <string name="accessibility_quick_settings_sync_off">Sinhronizacija izklopljena.</string>
+ <string name="accessibility_quick_settings_sync_on">Sinhronizacija vklopljena.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Sinhronizacija izklopljena.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Sinhronizacija vklopljena.</string>
+ <string name="quick_settings_sync_label">Sinhronizacija</string>
+ <string name="quick_settings_volume_panel_label">Plošča za glasnost</string>
+ <string name="quick_settings_usb_tether_label">Delj. mob. int. USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Časovna omejitev zaslona</string>
+ <string name="quick_settings_lockscreen_label">Zakleni zaslon</string>
+ <string name="quick_settings_ambient_display_label">Okoliški zaslon</string>
+ <string name="quick_settings_lockscreen_label_enforced">Vsiljen zaslon za zaklepanje</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Onemogočeno s profilom</string>
+ <string name="accessibility_quick_settings_screen_timeout">Časovna omejitev zaslona: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Časovna omejitev zaslona spremenjena na <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Način varčevanja energije</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Način varčevanja energije: način varčevanja.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Način varčevanja energije: uravnotežen način.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Način varčevanja energije: zmogljivostni način.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Način varčevanja energije: učinkoviti način.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Način varčevanja energije: hitri način.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Način varčevanja energije spremenjen v način varčevanja.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Način varčevanja energije spremenjen v uravnotežen način.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Način varčevanja energije spremenjen v zmogljivostni način.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Način varčevanja energije spremenjen v učinkoviti način.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Način varčevanja energije spremenjen v hitri način.</string>
+ <string name="quick_settings_performance_profile_detail_title">Način varčevanja energije</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Zaslon za zaklepanje izklopljen.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Zaslon za zaklepanje vklopljen.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Zaslon za zaklepanje izklopljen.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Zaslon za zaklepanje vklopljen.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Okoliški zaslon izklopljen.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Okoliški zaslon vklopljen.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Okoliški zaslon izklopljen.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Okoliški zaslon vklopljen.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Obvestila na zas. izk.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Obvestila na zas. vkl.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Obvestila na zaslonu izklopljena.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Obvestila na zaslonu vklopljena.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Kofein izklopljen.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Kofein vklopljen.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Ohranjevalnik baterije izklopljen.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Ohranjevalnik baterije vklopljen.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Ohranjevalnik baterije izklopljen.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Ohranjevalnik baterije vklopljen.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamične ploščice</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Naslednja budilka</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Izbirnik IME</string>
+ <string name="dynamic_qs_tile_su_label">Skrbniški dostop</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay izklopljen.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: samodejni način.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: dnevni način.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nočni način.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: zunanji način.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay izklopljen.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay spremenjen v samodejni način.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay spremenjen v dnevni način.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay spremenjen v nočni način.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay spremenjen v zunanji način.</string>
+ <string name="quick_settings_title_advanced_location">Tri stanja lokacije</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Poročanje o lokaciji: način varčevanja energije.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Poročanje o lokaciji: način \'samo tipala\'.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Poročanje o lokaciji: način visoke natančnosti.</string>
+ <string name="quick_settings_location_detail_title">Način lokacije</string>
+ <string name="quick_settings_location_battery_saving_label">Varčevanje z energijo</string>
+ <string name="quick_settings_location_gps_only_label">Samo naprava</string>
+ <string name="quick_settings_location_high_accuracy_label">Visoka natančnost</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Poročanje o lokaciji spremenjeno v način varčevanja energije.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Poročanje o lokaciji spremenjeno v način \'samo tipala\'.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Poročanje o lokaciji spremenjen v način visoke natančnosti.</string>
+ <string name="quick_settings_tiles_category_system">Sistemske ploščice</string>
+ <string name="quick_settings_tiles_add_tiles">Dodaj ploščico</string>
+ <string name="hotspot_apm_message">Povezava z mobilnimi omrežji ni možna v načinu za letalo. Onemogočite način za letalo in poskusite znova.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Svetilka je vklopljena</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Tapnite, če želite izklopiti</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sr/cm_arrays.xml b/packages/SystemUI/res/values-sr/cm_arrays.xml
new file mode 100644
index 0000000..977ddf0
--- /dev/null
+++ b/packages/SystemUI/res/values-sr/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>С</item>
+ <item>СИ</item>
+ <item>И</item>
+ <item>ЈИ</item>
+ <item>Ј</item>
+ <item>ЈЗ</item>
+ <item>З</item>
+ <item>СЗ</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-sr/cm_strings.xml b/packages/SystemUI/res/values-sr/cm_strings.xml
new file mode 100644
index 0000000..d17f8e5
--- /dev/null
+++ b/packages/SystemUI/res/values-sr/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA +</string>
+ <string name="accessibility_data_connection_4g_plus">4G +</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Превуци десно за %1$s</string>
+ <string name="right_shortcut_hint">Превуци лево за %1$s</string>
+ <string name="lockscreen_message">Додирни икону лево или десно да доделиш пречицу за закључани екран.</string>
+ <string name="lockscreen_default_target">Подразумевано</string>
+ <string name="select_application">Изабери апликацију</string>
+ <string name="lockscreen_choose_action_title">Изабери акцију</string>
+ <string name="lockscreen_none_target">Ниједан</string>
+ <string name="navbar_dialog_title">Изабери акцију да доделиш</string>
+ <string name="navbar_home_button">Главно дугме</string>
+ <string name="navbar_recent_button">Дугме за Недавно</string>
+ <string name="navbar_search_button">Дугме за Претрагу</string>
+ <string name="navbar_back_button">Дугме за Назад</string>
+ <string name="navbar_empty_button">Празан тастер</string>
+ <string name="navbar_menu_conditional_button">Мени (ауто сакриј) дугме</string>
+ <string name="navbar_menu_always_button">Мени (увек прикажи) дугме</string>
+ <string name="navbar_menu_big_button">Дугме за Мени</string>
+ <string name="accessibility_dpad_left">Курсор лево</string>
+ <string name="accessibility_dpad_right">Курсор десно</string>
+ <string name="advanced_dev_option_wipe_app">Избриши податке апликације</string>
+ <string name="advanced_dev_option_force_stop">Приморај заустављање</string>
+ <string name="advanced_dev_option_uninstall">Деинсталирај</string>
+ <string name="accessibility_notification_brightness">Осветљење</string>
+ <string name="accessibility_quick_settings_profiles_off">Профили искључени.</string>
+ <string name="accessibility_quick_settings_profiles">Профил: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Профили су искључени.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Профил је промењен у <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Покретање\u2026</string>
+ <string name="led_notification_title">Поставке светла</string>
+ <string name="led_notification_text">LED светло омогућено помоћу поставки</string>
+ <string name="qs_tile_edit_header_instruction">Притисни и држи плочицу за реорганизацију</string>
+ <string name="quick_settings_edit_label">Уреди плочице</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Није могуће обрисати уређивање плочица</string>
+ <string name="qs_tiles_reset_confirmation">Подеси плочице брзог подешавања на подразумевано?</string>
+ <string name="quick_settings_tile_reset_to_default">Подеси на посразумевани распоред</string>
+ <string name="quick_settings_title_header">Заглавље</string>
+ <string name="quick_settings_title_tiles">Плочице</string>
+ <string name="quick_settings_title_show_weather">Покажи време</string>
+ <string name="quick_settings_title_show_brightness_slider">Прикажи клизач оветљености</string>
+ <string name="quick_settings_title_enlarge_first_row">Увећајте први ред</string>
+ <string name="screen_pinning_description_no_navbar">Ово задржава преглед док га не уклониш. Додирни и држи дугме за назад да уклониш.</string>
+ <string name="quick_settings_custom_tile_detail_title">Промени назив</string>
+ <string name="quick_settings_remove">Уклони назив</string>
+ <string name="quick_settings_network_adb_label">ADB преко мреже</string>
+ <string name="quick_settings_compass_label">Компас</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Профили система</string>
+ <string name="quick_settings_profiles_off">Профили онемогућени</string>
+ <string name="quick_settings_heads_up_label">Искачуће поруке</string>
+ <string name="quick_settings_battery_saver_label">Уштеда батерије</string>
+ <string name="quick_settings_caffeine_label">Кофеин</string>
+ <string name="accessibility_quick_settings_sync_off">Синхрон. искључено.</string>
+ <string name="accessibility_quick_settings_sync_on">Синхрон. укључено.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Синхронизација је искључена.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Синхронизација је укључена.</string>
+ <string name="quick_settings_sync_label">Синхрон</string>
+ <string name="quick_settings_volume_panel_label">Панел гласноће</string>
+ <string name="quick_settings_usb_tether_label">USB повезивање</string>
+ <string name="quick_settings_screen_timeout_detail_title">Искључивање екрана</string>
+ <string name="quick_settings_lockscreen_label">Закључан екран</string>
+ <string name="quick_settings_ambient_display_label">Амбијент приказ</string>
+ <string name="quick_settings_lockscreen_label_enforced">Присилно закључани екран</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Онемогућено профилом</string>
+ <string name="accessibility_quick_settings_screen_timeout">Време искључења екрана: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Време искључења екрана промењено у <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Режим батерије</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Режим батерије: режим уштеде енергије.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Режим батерије: балансирани режим.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Режим батерије: режим учинка.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Режим батерије: режим ефикасности.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Режим батерије: режим брзине.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Режим батерије промењен у режим уштеде енергије.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Режим батерије промењен у балансирани режим.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Режим батерије промењен у режим учинка.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Режим батерије промењен у режим ефикасности.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Режим батерије промењен у режим брзине.</string>
+ <string name="quick_settings_performance_profile_detail_title">Режим батерије</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Закључани екран искључен.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Закључани екран укључен.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Закључани екран је искључен.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Закључани екран је укључен.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Амбијент приказ искључен.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Амбијент приказ укључен.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Амбијент приказ ће бити искључен.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Амбијент приказ ће бити укључен.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Искачуће поруке искључене.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Искачуће поруке укључене.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Искачуће поруке ће бити искључене.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Искачуће поруке ће бити укључене.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Кофеин је искључен.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Кофеин је укључен.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Уштеда батерије искључена.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Уштеда батерије укључена.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Уштеда батерије је искључена.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Уштеда батерије је укључена.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Динамичне плочице</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Следећи аларм</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME бирач</string>
+ <string name="dynamic_qs_tile_su_label">Root приступ</string>
+ <string name="accessibility_quick_settings_live_display_off">Активни екран искључен.</string>
+ <string name="accessibility_quick_settings_live_display_auto">Активни Екран: ауто режим.</string>
+ <string name="accessibility_quick_settings_live_display_day">Активни Екран: дневни режим.</string>
+ <string name="accessibility_quick_settings_live_display_night">Активни Екран: ноћни режим.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">Активни Екран: режим на отвореном.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">Активни Екран је искључен.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">Активни Екран промењен у ауто режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">Активни Екран промењен у дневни режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">Активни Екран промењен у ноћни режим.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">Активни Екран промењен у режим на отвореном.</string>
+ <string name="quick_settings_title_advanced_location">Локација три-државе</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Локација извештај: режим чувања батерије.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Локација извештај: режим само сензори.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Локација извештај: режим високе тачности.</string>
+ <string name="quick_settings_location_detail_title">Режими локације</string>
+ <string name="quick_settings_location_battery_saving_label">Уштеда батерије</string>
+ <string name="quick_settings_location_gps_only_label">Само уређај</string>
+ <string name="quick_settings_location_high_accuracy_label">Велика прецизност</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Извештај о локацији промењен у режим уштеде батерије.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Извештај о локацији промењен у режим само сензора.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Извештај о локацији промењен у режим високе прецизности.</string>
+ <string name="quick_settings_tiles_category_system">Плочице система</string>
+ <string name="quick_settings_tiles_add_tiles">Додај плочицу</string>
+ <string name="hotspot_apm_message">Није се могуће конектовати на мобилне мреже док је режим авиона омогућен. Онемогући режим авиона и пробај поново.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Блиц је укључен</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Додирни да угасиш</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sv/cm_arrays.xml b/packages/SystemUI/res/values-sv/cm_arrays.xml
new file mode 100644
index 0000000..fe795f4
--- /dev/null
+++ b/packages/SystemUI/res/values-sv/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NO</item>
+ <item>O</item>
+ <item>SO</item>
+ <item>S</item>
+ <item>SV</item>
+ <item>V</item>
+ <item>NV</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-sv/cm_strings.xml b/packages/SystemUI/res/values-sv/cm_strings.xml
new file mode 100644
index 0000000..73840fc
--- /dev/null
+++ b/packages/SystemUI/res/values-sv/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Svep höger för %1$s</string>
+ <string name="right_shortcut_hint">Svep vänster för %1$s</string>
+ <string name="lockscreen_message">Tryck på en ikon till vänster eller höger för att tilldela en låsskärmgenväg.</string>
+ <string name="lockscreen_default_target">Standard</string>
+ <string name="select_application">Välj app</string>
+ <string name="lockscreen_choose_action_title">Välj åtgärd</string>
+ <string name="lockscreen_none_target">Ingen</string>
+ <string name="navbar_dialog_title">Välj åtgärd att tilldela</string>
+ <string name="navbar_home_button">Hemknapp</string>
+ <string name="navbar_recent_button">Senasteknapp</string>
+ <string name="navbar_search_button">Sökknapp</string>
+ <string name="navbar_back_button">Bakåtknapp</string>
+ <string name="navbar_empty_button">Tom knapp</string>
+ <string name="navbar_menu_conditional_button">Menyknapp (autogöm)</string>
+ <string name="navbar_menu_always_button">Menyknapp (visa alltid)</string>
+ <string name="navbar_menu_big_button">Menyknapp</string>
+ <string name="accessibility_dpad_left">Markör till vänster</string>
+ <string name="accessibility_dpad_right">Markör till höger</string>
+ <string name="advanced_dev_option_wipe_app">Rensa appdata</string>
+ <string name="advanced_dev_option_force_stop">Tvinga avslutning</string>
+ <string name="advanced_dev_option_uninstall">Avinstallera</string>
+ <string name="accessibility_notification_brightness">Ljusstyrka</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiler av.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiler har stängts av.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Profil ändrades till <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Initierar\u2026</string>
+ <string name="led_notification_title">Ljusinställningar</string>
+ <string name="led_notification_text">LED-ljus aktiverat av inställningar</string>
+ <string name="qs_tile_edit_header_instruction">Tryck och håll brickor för att arrangera om</string>
+ <string name="quick_settings_edit_label">Redigera brickor</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Kan inte radera Redigera-brickan</string>
+ <string name="qs_tiles_reset_confirmation">Återställ snabbinställningsbrickor till standardkonfiguration?</string>
+ <string name="quick_settings_tile_reset_to_default">Återställ till standardlayout</string>
+ <string name="quick_settings_title_header">Huvud</string>
+ <string name="quick_settings_title_tiles">Brickor</string>
+ <string name="quick_settings_title_show_weather">Visa väder</string>
+ <string name="quick_settings_title_show_brightness_slider">Visa Ljusstyrkereglaget</string>
+ <string name="quick_settings_title_enlarge_first_row">Förstora första raden</string>
+ <string name="screen_pinning_description_no_navbar">Detta håller den synlig tills du frigör den. Tryck och håll nere Bakåt-knappen för att frigöra.</string>
+ <string name="quick_settings_custom_tile_detail_title">Anpassad bricka</string>
+ <string name="quick_settings_remove">Ta bort bricka</string>
+ <string name="quick_settings_network_adb_label">ADB över nätverk</string>
+ <string name="quick_settings_compass_label">Kompass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Systemprofiler</string>
+ <string name="quick_settings_profiles_off">Profiler inaktiverad</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Strömsparläge</string>
+ <string name="quick_settings_caffeine_label">Koffein</string>
+ <string name="accessibility_quick_settings_sync_off">Synk av.</string>
+ <string name="accessibility_quick_settings_sync_on">Synk på.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Synk inaktiverad.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Synk aktiverad.</string>
+ <string name="quick_settings_sync_label">Synk</string>
+ <string name="quick_settings_volume_panel_label">Volympanel</string>
+ <string name="quick_settings_usb_tether_label">USB-tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Timeout för skärm</string>
+ <string name="quick_settings_lockscreen_label">Låsskärm</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Tvingad låsskärm</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Inaktiverad av profil</string>
+ <string name="accessibility_quick_settings_screen_timeout">Skärm-timeout: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Skärm-timeout ändrades till <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Batteriläge</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Batteriläge: energisparläge.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Batteriläge: balanserat läge.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Batteriläge: prestandaläge.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Batteriläge: strömsparande läge.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Batteriläge: prestandaläge.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Batteriläge ändrat till energisparläge.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Batteriläge ändrat till balanserat läge.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Batteriläge ändrat till prestandaläge.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Batteriläge ändrat till strömsparande läge.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Batteriläge ändrat till prestandaläge.</string>
+ <string name="quick_settings_performance_profile_detail_title">Batteriläge</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Låsskärm av.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Låsskärm på.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Låsskärm inaktiverad.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Låsskärm aktiverad.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display avslagen.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display påslagen.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient display avslagen.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display påslagen.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up av.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up på.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up avslaget.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up påslaget.</string>
+ <string name="accessibility_quick_settings_caffeine_off">Koffein av.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Koffein på.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Strömsparläge är inaktiverat.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Strömsparläge är aktiverat.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Strömsparläge inaktiverat.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Strömsparläge aktiverat.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamiska bricka</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Nästa alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME-väljare</string>
+ <string name="dynamic_qs_tile_su_label">Root-åtkomst</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay av.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: automatiskt läge.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: dagläge.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: nattläge.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: utomhusläge.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay inaktiverad.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay ändrad till auto-läge.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay ändrad till dagläge.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay ändrad till nattläge.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay ändrad till utomhusläge.</string>
+ <string name="quick_settings_title_advanced_location">Tri-state placering</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Platsrapportering: batterisparläge.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Platsrapportering: endast sensorläge.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Platsrapportering: högt precisionsläge.</string>
+ <string name="quick_settings_location_detail_title">Platsläge</string>
+ <string name="quick_settings_location_battery_saving_label">Batterisparläge</string>
+ <string name="quick_settings_location_gps_only_label">Endast enhet</string>
+ <string name="quick_settings_location_high_accuracy_label">Hög noggrannhet</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Platsrapportering ändrades till batterispararläge.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Platsrapportering ändrad till endast sensor.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Platsrapportering ändrad till hög noggrannhet.</string>
+ <string name="quick_settings_tiles_category_system">Systembrickor</string>
+ <string name="quick_settings_tiles_add_tiles">Lägg till en bricka</string>
+ <string name="hotspot_apm_message">Det går inte att ansluta till mobila nät när flygplansläge är aktiverat. Inaktivera flygplansläge och försök igen.</string>
+ <string name="quick_settings_tile_flashlight_not_title">Ficklampan är på</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Tryck för att stänga av</string>
+</resources>
diff --git a/packages/SystemUI/res/values-th/cm_arrays.xml b/packages/SystemUI/res/values-th/cm_arrays.xml
new file mode 100644
index 0000000..cf5825b
--- /dev/null
+++ b/packages/SystemUI/res/values-th/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>N</item>
+ <item>NE</item>
+ <item>E</item>
+ <item>SE</item>
+ <item>S</item>
+ <item>SW</item>
+ <item>W</item>
+ <item>NW</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-th/cm_strings.xml b/packages/SystemUI/res/values-th/cm_strings.xml
new file mode 100644
index 0000000..2651986
--- /dev/null
+++ b/packages/SystemUI/res/values-th/cm_strings.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">ปัดไปทางขวาเพื่อ %1$s</string>
+ <string name="right_shortcut_hint">ปัดไปทางซ้ายเพื่อ %1$s</string>
+ <string name="lockscreen_message">แตะที่ไอคอนด้านซ้ายหรือขวาเพื่อกำหนดทางลัดสำหรับหน้าจอล็อค</string>
+ <string name="lockscreen_default_target">ค่าเริ่มต้น</string>
+ <string name="select_application">เลือกแอปพลิเคชัน</string>
+ <string name="lockscreen_choose_action_title">เลือกการกระทำ</string>
+ <string name="lockscreen_none_target">ไม่มี</string>
+ <string name="navbar_dialog_title">เลือกใช้การกระทำ</string>
+ <string name="navbar_home_button">ปุ่มหลัก</string>
+ <string name="navbar_recent_button">ปุ่มแอปล่าสุด</string>
+ <string name="navbar_search_button">ปุ่มค้นหา</string>
+ <string name="navbar_back_button">ปุ่มกลับ</string>
+ <string name="navbar_empty_button">ปุ่มว่าง</string>
+ <string name="navbar_menu_conditional_button">ปุ่มเมนู (ซ่อนอัตโนมัติ)</string>
+ <string name="navbar_menu_always_button">ปุ่มเมนู (แสดงตลอด)</string>
+ <string name="navbar_menu_big_button">ปุ่มเมนู</string>
+ <string name="accessibility_dpad_left">เคอร์เซอร์ซ้าย</string>
+ <string name="accessibility_dpad_right">เคอร์เซอร์ขวา</string>
+ <string name="advanced_dev_option_wipe_app">ล้างข้อมูลแอป</string>
+ <string name="advanced_dev_option_force_stop">บังคับปิด</string>
+ <string name="advanced_dev_option_uninstall">ยกเลิกการติดตั้ง</string>
+ <string name="accessibility_notification_brightness">ความสว่าง</string>
+ <string name="accessibility_quick_settings_profiles_off">โปรไฟล์ปิดอยู่</string>
+ <string name="accessibility_quick_settings_profiles">โปรไฟล์: <xliff:g id="profile" example="Default">%s</xliff:g></string>
+ <string name="accessibility_quick_settings_profiles_changed_off">ปิดโปรไฟล์</string>
+ <string name="accessibility_quick_settings_profiles_changed">โปรไฟล์เปลี่ยนเป็น <xliff:g id="profile" example="Default">%s</xliff:g></string>
+ <string name="quick_settings_compass_init">กำลังเตรียมการ\u2026</string>
+ <string name="led_notification_title">การตั้งค่าแสง</string>
+ <string name="led_notification_text">LED ถูกเปิดใช้งานโดยการตั้งค่า</string>
+ <string name="qs_tile_edit_header_instruction">แตะไทต์ค้างไว้เพื่อย้ายตำแหน่ง</string>
+ <string name="quick_settings_edit_label">แก้ไขไทต์</string>
+ <string name="quick_settings_cannot_delete_edit_tile">ไม่สามารถลบไทต์แก้ไขได้</string>
+ <string name="qs_tiles_reset_confirmation">คืนค่าการจัดวางไทต์เป็นค่าเริ่มต้น</string>
+ <string name="quick_settings_tile_reset_to_default">คืนค่าเป็นการจัดวางเริ่มต้น</string>
+ <string name="quick_settings_title_header">หัวข้อ</string>
+ <string name="quick_settings_title_tiles">ไทต์</string>
+ <string name="quick_settings_title_show_weather">แสดงสภาพอากาศ</string>
+ <string name="quick_settings_title_enlarge_first_row">ขยายแถวแรก</string>
+ <string name="screen_pinning_description_no_navbar">จะแสดงหน้านี้จนกว่าคุณจะเลิกปักหมุด กดปุ่มกลับค้างเพื่อเลิกปักหมุด</string>
+ <string name="quick_settings_custom_tile_detail_title">ไทล์กำหนดเอง</string>
+ <string name="quick_settings_remove">ลบไทล์ออก</string>
+ <string name="quick_settings_network_adb_label">ADB บนเครือข่าย</string>
+ <string name="quick_settings_compass_label">เข็มทิศ</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">โปรไฟล์ระบบ</string>
+ <string name="quick_settings_profiles_off">โปรไฟล์ถูกปิดอยู่</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">ประหยัดแบตเตอรี่</string>
+ <string name="accessibility_quick_settings_sync_off">ปิดการซิงค์</string>
+ <string name="accessibility_quick_settings_sync_on">การซิงค์เปิดอยู่</string>
+ <string name="accessibility_quick_settings_sync_changed_off">การซิงค์ปิดอยู่</string>
+ <string name="accessibility_quick_settings_sync_changed_on">การซิงค์เปิดอยู่</string>
+ <string name="quick_settings_sync_label">ซิงค์</string>
+ <string name="quick_settings_volume_panel_label">แผงควบคุมระดับเสียง</string>
+ <string name="quick_settings_usb_tether_label">ปล่อยสัญญาณผ่าน USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">เวลาที่หน้าจอดับ</string>
+ <string name="quick_settings_lockscreen_label">หน้าจอล็อค</string>
+ <string name="quick_settings_ambient_display_label">หน้าจอแวดล้อม</string>
+ <string name="quick_settings_lockscreen_label_enforced">บังคับล็อคหน้าจอ</string>
+ <string name="accessibility_quick_settings_screen_timeout">หมดเวลาหน้าจอ: <xliff:g id="timeout" example="30 seconds">%s</xliff:g></string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">หมดเวลาหน้าจอเปลี่ยนเป็น <xliff:g id="timeout" example="30 seconds">%s</xliff:g></string>
+ <string name="qs_tile_performance">รูปแบบแบตเตอรี่</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">รูปแบบแบตเตอรี่: ประหยัดพลังงาน</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">รูปแบบแบตเตอรี่: สมดุล</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">รูปแบบแบตเตอรี่: ประสิทธิภาพ</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">รูปแบบแบตเตอรี่: รูปแบบใช้พลังงานต่ำ</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">รูปแบบแบตเตอรี่: รูปแบบรวดเร็ว</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">รูปแบบแบตเตอรี่เปลี่ยนเป็นรูปแบบประหยัดพลังงาน</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">รูปแบบแบตเตอรี่เปลี่ยนเป็นสมดุล</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">รูปแบบแบตเตอรี่เปลี่ยนเป็นรูปแบบประสิทธิภาพ</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">รูปแบบแบตเตอรี่เปลี่ยนเป็นรูปแบบใช้พลังงานต่ำ</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">รูปแบบแบตเตอรี่เปลี่ยนเป็นรูปแบบรวดเร็ว</string>
+ <string name="quick_settings_performance_profile_detail_title">รูปแบบแบตเตอรี่</string>
+ <string name="accessibility_quick_settings_lock_screen_off">หน้าจอล็อคปิดอยู่</string>
+ <string name="accessibility_quick_settings_lock_screen_on">หน้าจอล็อคเปิดอยู่</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">หน้าจอล็อคถูกปิด</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">หน้าจอล็อคถูกเปิด</string>
+ <string name="accessibility_quick_settings_ambient_display_off">ปิดหน้าจอแวดล้อม</string>
+ <string name="accessibility_quick_settings_ambient_display_on">เปิดหน้าจอแวดล้อม</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">หน้าจอแวดล้อมปิดอยู่</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">หน้าจอแวดล้อมเปิดอยู่</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up ปิดอยู่</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up เปิดอยู่</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up ปิดอยู่</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up เปิดอยู่</string>
+ <string name="accessibility_quick_settings_battery_saver_off">ตัวประหยัดแบตเตอรี่ปิดอยู่</string>
+ <string name="accessibility_quick_settings_battery_saver_on">ตัวประหยัดแบตเตอรี่เปิดอยู่</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">ตัวประหยัดแบตเตอรีถูกปิด</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">ตัวประหยัดแบตเตอรีถูกเปิด</string>
+ <string name="quick_settings_dynamic_tile_detail_title">ไทล์แบบไดนามิก</string>
+ <string name="dynamic_qs_tile_next_alarm_label">การปลุกครั้งต่อไป</string>
+ <string name="dynamic_qs_tile_ime_selector_label">ตัวเลือก IME</string>
+ <string name="dynamic_qs_tile_su_label">สิทธิผู้ดูแลระบบ</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay ปิดอยู่</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: รูปแบบอัตโนมัติ</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: รูปแบบกลางวัน</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: รูปแบบกลางคืน</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: รูปแบบกลางแจ้ง</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay ถูกปิด</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay เปลี่ยนเป็นรูปแบบอัตโนมัติ</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay เปลี่ยนเป็นรูปแบบกลางวัน</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay เปลี่ยนเป็นรูปแบบกลางคืน</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay เปลี่ยนเป็นรูปแบบกลางแจ้ง</string>
+ <string name="quick_settings_title_advanced_location">ตำแหน่งแบบสามสถานะ</string>
+ <string name="accessibility_quick_settings_location_battery_saving">การระบุตำแหน่ง: รูปแบบประหยัดแบตเตอรี่</string>
+ <string name="accessibility_quick_settings_location_gps_only">รายงานตำแหน่งที่ตั้ง: เซนเซอร์เท่านั้น</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">รูปแบบการระบุตำแหน่ง: ความแม่นยำสูง</string>
+ <string name="quick_settings_location_detail_title">รูปแบบตำแหน่งที่ตั้ง</string>
+ <string name="quick_settings_location_battery_saving_label">ประหยัดแบตเตอรี่</string>
+ <string name="quick_settings_location_gps_only_label">อุปกรณ์เท่านั้น</string>
+ <string name="quick_settings_location_high_accuracy_label">ความแม่นยำสูง</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">ตำแหน่งการระบุเปลี่ยนเป็นรูปแบบประหยัดแบตเตอรี่</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">การระบุตำแหน่งเปลี่ยนเป็นรูปแบบเฉพาะเซนเซอร์</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">การระบุตำแหน่งเปลี่ยนรูปแบบเป็นความแม่นยำสูง</string>
+</resources>
diff --git a/packages/SystemUI/res/values-tr/cm_arrays.xml b/packages/SystemUI/res/values-tr/cm_arrays.xml
new file mode 100644
index 0000000..472dd22
--- /dev/null
+++ b/packages/SystemUI/res/values-tr/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>K</item>
+ <item>KD</item>
+ <item>D</item>
+ <item>GD</item>
+ <item>G</item>
+ <item>GB</item>
+ <item>B</item>
+ <item>KB</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-tr/cm_strings.xml b/packages/SystemUI/res/values-tr/cm_strings.xml
new file mode 100644
index 0000000..a70ea9e
--- /dev/null
+++ b/packages/SystemUI/res/values-tr/cm_strings.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">%1$s için sağa kaydırın</string>
+ <string name="right_shortcut_hint">%1$s için sola kaydırın</string>
+ <string name="lockscreen_message">Kilit ekranı kısayollarını ayarlamak için sağ ya da soldaki simgeye dokunun.</string>
+ <string name="lockscreen_default_target">Varsayılan</string>
+ <string name="select_application">Uygulama seçin</string>
+ <string name="lockscreen_choose_action_title">Eylem seçin</string>
+ <string name="lockscreen_none_target">Yok</string>
+ <string name="navbar_dialog_title">Atamak için işlev seçin</string>
+ <string name="navbar_home_button">Ana ekran tuşu</string>
+ <string name="navbar_recent_button">Son uyg. tuşu</string>
+ <string name="navbar_search_button">Arama tuşu</string>
+ <string name="navbar_back_button">Geri tuşu</string>
+ <string name="navbar_empty_button">Boş tuş</string>
+ <string name="navbar_menu_conditional_button">Menü (otoGizle) tuşu</string>
+ <string name="navbar_menu_always_button">Menü (hepGöster) tuşu</string>
+ <string name="navbar_menu_big_button">Menü tuşu</string>
+ <string name="accessibility_dpad_left">Sol imleç</string>
+ <string name="accessibility_dpad_right">Sağ imleç</string>
+ <string name="advanced_dev_option_wipe_app">Uygulama verisini sil</string>
+ <string name="advanced_dev_option_force_stop">Durmaya zorla</string>
+ <string name="advanced_dev_option_uninstall">Kaldır</string>
+ <string name="accessibility_notification_brightness">Işık parlaklığı</string>
+ <string name="accessibility_quick_settings_profiles_off">Profiller kapalı.</string>
+ <string name="accessibility_quick_settings_profiles">Profil: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiller kapatıldı.</string>
+ <string name="accessibility_quick_settings_profiles_changed"><xliff:g id="profile" example="Default">%s</xliff:g> profiline geçildi.</string>
+ <string name="quick_settings_compass_init">Başlatılıyor\u2026</string>
+ <string name="led_notification_title">Işık ayarları</string>
+ <string name="led_notification_text">LED ışık ayarlar tarafından etkinleştirilmiş</string>
+ <string name="qs_tile_edit_header_instruction">Kareleri yeniden düzenlemek için basılı tutun</string>
+ <string name="quick_settings_edit_label">Kareleri düzenle</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Düzenle karesi silinemiyor</string>
+ <string name="qs_tiles_reset_confirmation">Hızlı ayarlar kareleri ilk durumuna sıfırlansın mı?</string>
+ <string name="quick_settings_tile_reset_to_default">Varsayılan düzene sıfırla</string>
+ <string name="quick_settings_title_header">Başlık</string>
+ <string name="quick_settings_title_tiles">Kareler</string>
+ <string name="quick_settings_title_show_weather">Hava durumunu göster</string>
+ <string name="quick_settings_title_enlarge_first_row">İlk satırı büyüt</string>
+ <string name="screen_pinning_description_no_navbar">Ekrandan kaldırana kadar görünümde tutar. Kaldırmak için Geri tuşuna dokunun ve tutun.</string>
+ <string name="quick_settings_custom_tile_detail_title">Özel kare</string>
+ <string name="quick_settings_remove">Kareyi kaldır</string>
+ <string name="quick_settings_network_adb_label">Ağ üzerinden ADB</string>
+ <string name="quick_settings_compass_label">Pusula</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Sistem profilleri</string>
+ <string name="quick_settings_profiles_off">Profiller devre dışı</string>
+ <string name="quick_settings_heads_up_label">Bildirim pencereleri</string>
+ <string name="quick_settings_battery_saver_label">Pil tasarrufu</string>
+ <string name="accessibility_quick_settings_sync_off">Eşitleme kapalı.</string>
+ <string name="accessibility_quick_settings_sync_on">Eşitleme açık.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Eşitleme kapatıldı.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Eşitleme açıldı.</string>
+ <string name="quick_settings_sync_label">Eşitleme</string>
+ <string name="quick_settings_volume_panel_label">Ses paneli</string>
+ <string name="quick_settings_usb_tether_label">USB İnternet Paylaşımı</string>
+ <string name="quick_settings_screen_timeout_detail_title">Ekran zaman aşımı</string>
+ <string name="quick_settings_lockscreen_label">Kilit ekranı</string>
+ <string name="quick_settings_ambient_display_label">Bildirim ekranı</string>
+ <string name="quick_settings_lockscreen_label_enforced">Kilit ekranı zorunlu</string>
+ <string name="accessibility_quick_settings_screen_timeout">Ekran zaman aşımı : <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Ekran zaman aşımı <xliff:g id="timeout" example="30 seconds">%s</xliff:g> olarak ayarlandı.</string>
+ <string name="qs_tile_performance">Pil modu</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Pil modu: güç tasarruf modu.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Pil modu: dengeli mod.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Pil modu: performans modu.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Pil modu: verimlilik modu.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Pil modu: hızlı mod.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Pil modu güç tasarruf moduna geçti.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Pil modu dengeli moda geçti.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Pil modu performans moduna geçti.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Pil modu verimlilik moduna geçti.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Pil modu hızlı moda geçti.</string>
+ <string name="quick_settings_performance_profile_detail_title">Pil modu</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Kilit ekranı kapalı.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Kilit ekranı açık.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Kilit ekranı kapatıldı.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Kilit ekranı açıldı.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Bildirim ekranı kapalı.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Bildirim ekranı açık.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Bildirim ekranı kapatıldı.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Bildirim ekranı açıldı.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Bildirim pencereleri kapalı.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Bildirim pencereleri açık.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Bildirim pencereleri kapatıldı.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Bildirim pencereleri açıldı.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Pil tasarrufu kapalı.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Pil tasarrufu açık.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Pil tasarrufu kapatıldı.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Pil tasarrufu açıldı.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Dinamik kare</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Sonraki alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME seçici</string>
+ <string name="dynamic_qs_tile_su_label">Root erişimi</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay kapalı.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: otomatik mod.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: gündüz modu.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: gece modu.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: açık hava modu.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay kapatıldı.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay otomatik moda geçti.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay gündüz moduna geçti.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay gece moduna geçti.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay açık hava moduna geçti.</string>
+ <string name="quick_settings_title_advanced_location">3-durumlu konum</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Konum bildirimi: pil tasarruf modu.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Konum bildirimi: sadece sensörler modu.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Konum bildirimi: yüksek hassasiyet modu.</string>
+ <string name="quick_settings_location_detail_title">Konum modu</string>
+ <string name="quick_settings_location_battery_saving_label">Pil tasarrufu</string>
+ <string name="quick_settings_location_gps_only_label">Sadece cihaz</string>
+ <string name="quick_settings_location_high_accuracy_label">Yüksek doğruluk</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Konum bildirimi pil tasarruf moduna geçti.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Konum bildirimi sadece sensörler moduna geçti.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Konum bildirimi yüksek hassasiyet moduna geçti.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ug/cm_arrays.xml b/packages/SystemUI/res/values-ug/cm_arrays.xml
new file mode 100644
index 0000000..e5c5ade
--- /dev/null
+++ b/packages/SystemUI/res/values-ug/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>شىمال</item>
+ <item>شەرقىي شىمال</item>
+ <item>شەرق</item>
+ <item>شەرقىي جەنۇپ</item>
+ <item>جەنۇپ</item>
+ <item>غەربىي جەنۇپ</item>
+ <item>غەرب</item>
+ <item>غەربىي شىمال</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-ug/cm_strings.xml b/packages/SystemUI/res/values-ug/cm_strings.xml
new file mode 100644
index 0000000..21480ce
--- /dev/null
+++ b/packages/SystemUI/res/values-ug/cm_strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">%1$s ئۈچۈن ئوڭغا سۈرۈڭ</string>
+ <string name="right_shortcut_hint">%1$s ئۈچۈن سولغا سۈرۈڭ</string>
+ <string name="select_application">ئەپ تاللاڭ</string>
+ <string name="lockscreen_choose_action_title">مەشغۇلات تاللاڭ</string>
+ <string name="lockscreen_none_target">يوق</string>
+ <string name="navbar_dialog_title">تەقسىملەيدىغان مەشغۇلاتنى تاللاڭ</string>
+ <string name="navbar_home_button">باش بەت توپچا</string>
+ <string name="navbar_recent_button">يېقىنقى توپچىلار</string>
+ <string name="navbar_search_button">ئىزدەش توپچىسى</string>
+ <string name="navbar_back_button">قايت توپچا</string>
+ <string name="navbar_empty_button">بوش توپچا</string>
+ <string name="navbar_menu_conditional_button">تىزىملىك (ئۆزلۈكىدىن يوشۇر) توپچا</string>
+ <string name="navbar_menu_always_button">‫تىزىملىك (ھەمىشە كۆرسەت) توپچا‪</string>
+ <string name="navbar_menu_big_button">تىزىملىك توپچا</string>
+ <string name="accessibility_dpad_left">نۇربەلگە سولغا</string>
+ <string name="accessibility_dpad_right">نۇر بەلگە ئوڭغا</string>
+ <string name="advanced_dev_option_wipe_app">ئەپ سانلىق مەلۇماتىنى تازىلا</string>
+ <string name="advanced_dev_option_force_stop">مەجبۇرى توختات</string>
+ <string name="advanced_dev_option_uninstall">ئۆچۈر</string>
+ <string name="quick_settings_compass_init">دەسلەپلەشتۈرۈۋاتىدۇ\u2026</string>
+ <string name="quick_settings_network_adb_label">ADB تور سازلاش</string>
+ <string name="quick_settings_compass_label">كومپاس</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">سىستېما سەپلىمە ھۆججەتلىرى</string>
+ <string name="quick_settings_profiles_off">سەپلىمە ھۆججەت چەكلەندى</string>
+ <string name="quick_settings_screen_timeout_detail_title">ئېكران مۆھلىتى</string>
+ <string name="quick_settings_lockscreen_label">قۇلۇپ ئېكرانى</string>
+ <string name="quick_settings_lockscreen_label_enforced">ئېكراننى مەجبۇرىي قۇلۇپلا</string>
+ <string name="accessibility_quick_settings_location_battery_saving">ئورۇن دوكلاتى: توك تېجەش ھالىتى.</string>
+ <string name="accessibility_quick_settings_location_gps_only">ئورۇن دوكلاتى: سەزگۈچ ھالىتىلا.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">ئورۇن دوكلاتى: يۇقىرى ئېنىقلىق ھالىتى.</string>
+ <string name="quick_settings_location_detail_title">ئورۇن ھالىتى</string>
+ <string name="quick_settings_location_battery_saving_label">توك سەرپىياتى تۆۋەن</string>
+ <string name="quick_settings_location_gps_only_label">ئۈسكۈنىلا</string>
+ <string name="quick_settings_location_high_accuracy_label">دەللىكى يۇقىرى</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ug/strings.xml b/packages/SystemUI/res/values-ug/strings.xml
new file mode 100644
index 0000000..8ae8ed7
--- /dev/null
+++ b/packages/SystemUI/res/values-ug/strings.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label">سىستېما ئارايۈزى</string>
+ <string name="status_bar_clear_all_button">تازىلا</string>
+ <string name="status_bar_recent_remove_item_title">تىزىمدىن چىقىرىۋەت</string>
+ <string name="status_bar_recent_inspect_item_title">ئەپ ئۇچۇرى</string>
+ <string name="status_bar_accessibility_dismiss_recents">يېقىنقى ئەپلەرنى بىكار قىل</string>
+ <string name="status_bar_no_notifications_title">ئۇقتۇرۇش يوق</string>
+ <string name="status_bar_ongoing_events_title">ئېلىپ بېرىلىۋاتىدۇ</string>
+ <string name="status_bar_latest_events_title">ئۇقتۇرۇشلار</string>
+ <string name="invalid_charger">USB دىن توكلاشنى قوللىمايدۇ.\nتوكلىغۇچتىن توڭلاڭ.</string>
+ <string name="status_bar_settings_settings_button">تەڭشەكلەر</string>
+ <string name="status_bar_settings_wifi_button">Wi-Fi</string>
+ <string name="status_bar_settings_auto_rotation">ئېكراننى ئۆزلۈكىدىن ئايلاندۇر</string>
+ <string name="status_bar_settings_mute_label">ئۈنسىز</string>
+ <string name="status_bar_settings_auto_brightness_label">ئاپتوماتىك</string>
+ <string name="status_bar_settings_notifications">ئۇقتۇرۇشلار</string>
+ <string name="bluetooth_tethered">كۆكچىش چەكلىمىسى</string>
+ <string name="status_bar_input_method_settings_configure_input_methods">كىرگۈزگۈچ تەڭشەك</string>
+ <string name="status_bar_use_physical_keyboard">فىزىكىلىق ھەرپتاختا</string>
+ <string name="usb_device_permission_prompt"><xliff:g id="APPLICATION">%1$s</xliff:g> ئەپنىڭ USB ئۈسكۈنىنى زىيارەت قىلىشىغا يول قويامدۇ؟</string>
+ <string name="usb_accessory_permission_prompt"><xliff:g id="APPLICATION">%1$s</xliff:g> ئەپنىڭ USB قوشۇمچىسىنى زىيارەت قىلىشىغا يول قويامدۇ؟</string>
+ <string name="usb_device_confirm_prompt">بۇ USB ئۈسكۈنە باغلانغاندا <xliff:g id="ACTIVITY">%1$s</xliff:g> نى ئاچامدۇ؟</string>
+ <string name="usb_accessory_confirm_prompt">بۇ USB قوشۇمچىسى باغلانغاندا <xliff:g id="ACTIVITY">%1$s</xliff:g> نى ئاچامدۇ؟</string>
+ <string name="usb_accessory_uri_prompt">بۇ USB قوشۇمچىسىغا ماس كېلىدىغان ئەپ ئورنىتىلمىغان. بۇ قوشۇمچە ھەققىدىكى تېخىمۇ كۆپ ئۇچۇرنى <xliff:g id="URL">%1$s</xliff:g> دىن زىيارەت قىلىڭ.</string>
+ <string name="title_usb_accessory">USB قوشۇمچە</string>
+ <string name="label_view">كۆرۈنۈش</string>
+ <string name="always_use_device">كۆڭۈلدىكى ئەھۋالدا بۇ USB ئۈسكۈنىنى ئىشلەت</string>
+ <string name="always_use_accessory">كۆڭۈلدىكى ئەھۋالدا بۇ USB قوشۇمچىنى ئىشلەت</string>
+ <string name="usb_debugging_title">USB سازلاشقا يول قويامدۇ؟</string>
+ <string name="usb_debugging_message">بۇ كومپيۇتېرنىڭ RSA ئاچقۇچىنىڭ بارماق ئىزى: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g></string>
+ <string name="usb_debugging_always">بۇ كومپيۇتېرغا ھەمىشە يول قوي</string>
+ <string name="compat_mode_on">پۈتۈن ئېكرانغا چوڭايت</string>
+ <string name="compat_mode_off">پۈتۈن ئېكرانغا ياي</string>
+ <string name="screenshot_saving_ticker">ئېكران كەسمىسىنى ساقلاۋاتىدۇ…</string>
+ <string name="screenshot_saving_title">ئېكران كەسمىسىنى ساقلاۋاتىدۇ…</string>
+ <string name="screenshot_saving_text">ئېكران كەسمىسى ساقلاندى.</string>
+ <string name="screenshot_saved_title">ئېكران كەسمىسىگە ئېرىشتى.</string>
+ <string name="screenshot_saved_text">چېكىلسە ئېكران كەسمىسىنى كۆرسىتىدۇ.</string>
+ <string name="screenshot_failed_title">ئېكران كەسمىسىگە ئېرىشەلمەيدۇ.</string>
+ <string name="usb_preference_title">USB ھۆججەت يوللاش تاللانمىسى</string>
+ <string name="use_mtp_button_title">ۋاستە چالغۇچ سۈپىتىدە ئېگەرلە (MTP)</string>
+ <string name="use_ptp_button_title">كامېرا سۈپىتىدە ئېگەرلە (PTP)</string>
+ <string name="installer_cd_button_title">Mac ئۈچۈن Android ھۆججەت يوللايدىغان ئەپنى ئورنات</string>
+ <string name="accessibility_back">قايت</string>
+ <string name="accessibility_home">باش بەت</string>
+ <string name="accessibility_menu">تىزىملىك</string>
+ <string name="accessibility_search_light">ئىزدە</string>
+ <string name="accessibility_camera_button">كامېرا</string>
+ <string name="accessibility_compatibility_zoom_button">ماسلىشىشچان چوڭايت كىچىكلەت توپچىسى.</string>
+ <string name="accessibility_compatibility_zoom_example">ئېكراننى كىچىكتىن چوڭايتىدۇ.</string>
+ <string name="accessibility_bluetooth_connected">كۆكچىش باغلاندى.</string>
+ <string name="accessibility_bluetooth_disconnected">كۆكچىش ئۈزۈلدى.</string>
+ <string name="accessibility_no_battery">توكدان يوق.</string>
+ <string name="accessibility_battery_one_bar">توكدان بىر بالداق.</string>
+ <string name="accessibility_battery_two_bars">توكدان ئىككى بالداق.</string>
+ <string name="accessibility_battery_three_bars">توكدان ئۈچ بالداق.</string>
+ <string name="accessibility_battery_full">توكدان لىق.</string>
+ <string name="accessibility_no_phone">تېلېفون يوق.</string>
+ <string name="accessibility_phone_one_bar">تېلېفون بىر بالداق.</string>
+ <string name="accessibility_phone_two_bars">تېلېفون ئىككى بالداق.</string>
+ <string name="accessibility_phone_three_bars">تېلېفون ئۈچ بالداق.</string>
+ <string name="accessibility_phone_signal_full">تېلېفون سىگنالى لىق.</string>
+ <string name="accessibility_no_data">سانلىق مەلۇمات يوق.</string>
+ <string name="accessibility_data_one_bar">سانلىق مەلۇمات بىر بالداق.</string>
+ <string name="accessibility_data_two_bars">سانلىق مەلۇمات ئىككى بالداق.</string>
+ <string name="accessibility_data_three_bars">سانلىق مەلۇمات ئۈچ بالداق.</string>
+ <string name="accessibility_data_signal_full">سانلىق مەلۇمات سىگنالى لىق.</string>
+ <string name="accessibility_no_wimax">WiMAX يوق.</string>
+ <string name="accessibility_wimax_one_bar">WiMAX بىر بالداق.</string>
+ <string name="accessibility_wimax_two_bars">WiMAX ئىككى بالداق.</string>
+ <string name="accessibility_wimax_three_bars">WiMAX ئۈچ بالداق.</string>
+ <string name="accessibility_wimax_signal_full">WiMAX سىگنالى لىق.</string>
+ <string name="accessibility_no_signal">سىگنال يوق.</string>
+ <string name="accessibility_not_connected">باغلانمىدى.</string>
+ <string name="accessibility_zero_bars">نۆل بالداق.</string>
+ <string name="accessibility_one_bar">بىر بالداق.</string>
+ <string name="accessibility_two_bars">ئىككى بالداق.</string>
+ <string name="accessibility_three_bars">ئۈچ بالداق.</string>
+ <string name="accessibility_signal_full">سىگنال لىق.</string>
+ <string name="accessibility_desc_on">ئوچۇق.</string>
+ <string name="accessibility_desc_off">تاقاق.</string>
+ <string name="accessibility_desc_connected">باغلاندى.</string>
+ <string name="accessibility_data_connection_gprs">GPRS</string>
+ <string name="accessibility_data_connection_1x">1 X</string>
+ <string name="accessibility_data_connection_hspa">HSPA</string>
+ <string name="accessibility_data_connection_3g">3G</string>
+ <string name="accessibility_data_connection_3.5g">3.5G</string>
+ <string name="accessibility_data_connection_4g">4G</string>
+ <string name="accessibility_data_connection_lte">LTE</string>
+ <string name="accessibility_data_connection_cdma">CDMA</string>
+ <string name="accessibility_data_connection_roaming">كەزمە</string>
+ <string name="accessibility_data_connection_edge">Edge</string>
+ <string name="accessibility_no_sim">SIM كارتا يوق.</string>
+ <string name="accessibility_bluetooth_tether">كۆكچىش ھەمبەھىر</string>
+ <string name="accessibility_airplane_mode">ئايروپىلان ھالىتى</string>
+ <string name="accessibility_battery_level">توكدان <xliff:g id="NUMBER">%d</xliff:g> پىرسەنت.</string>
+ <string name="accessibility_settings_button">سىستېما تەڭشەكلىرى</string>
+ <string name="accessibility_notifications_button">ئۇقتۇرۇشلار.</string>
+ <string name="accessibility_remove_notification">ئۇقتۇرۇشنى تازىلا.</string>
+ <string name="accessibility_gps_enabled">GPS قوزغىتىلدى.</string>
+ <string name="accessibility_gps_acquiring">GPS بايقاۋاتىدۇ.</string>
+ <string name="accessibility_tty_enabled">TeleTypewriter قوزغىتىلدى.</string>
+ <string name="accessibility_ringer_vibrate">قوڭغۇراق تىترەت.</string>
+ <string name="accessibility_ringer_silent">قوڭغۇراق ئۈنسىز.</string>
+ <string name="accessibility_recents_item_dismissed"><xliff:g id="APP">%s</xliff:g> بوشىتىلدى.</string>
+ <string name="accessibility_notification_dismissed">ئۇقتۇرۇش رەت قىلىندى.</string>
+ <string name="accessibility_desc_notification_shade">ئۇقتۇرۇش سايەسى.</string>
+ <string name="accessibility_desc_quick_settings">تېز تەڭشەكلەر.</string>
+ <string name="accessibility_quick_settings_user">ئىشلەتكۈچى <xliff:g id="USER">%s.</xliff:g></string>
+ <string name="accessibility_quick_settings_mobile">كۆچمە <xliff:g id="SIGNAL">%1$s</xliff:g>، <xliff:g id="TYPE">%2$s</xliff:g>،<xliff:g id="NETWORK">%3$s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_battery">توكدان <xliff:g id="STATE">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_alarm">قوڭغۇراق تەڭشەك <xliff:g id="TIME">%s</xliff:g>.</string>
+ <string name="status_bar_settings_signal_meter_disconnected">ئىنتېرنېت باغلىنىشى يوق</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi ئۇلاندى</string>
+ <string name="gps_notification_searching_text">GPS ئىزدەۋاتىدۇ</string>
+ <string name="gps_notification_found_text">GPS تە ئورۇن تەڭشەك</string>
+ <string name="accessibility_location_active">ئورۇن ئۇچۇرى ئىلتىماسى ئاكتىپ</string>
+ <string name="accessibility_clear_all">بارلىق ئۇقتۇرۇشلارنى تازىلا</string>
+ <string name="accessibility_rotation_lock_off">ئېكران ئۆزلۈكىدىن ئايلىنىدۇ.</string>
+ <string name="accessibility_rotation_lock_on_landscape">ئېكران توغرىسىغا كۆز يۈگۈرتۈش ھالىتىگە قۇلۇپلاندى.</string>
+ <string name="accessibility_rotation_lock_on_portrait">ئېكران بويىغا كۆز يۈگۈرتۈش ھالىتىگە قۇلۇپلاندى.</string>
+ <string name="dessert_case">تاتلىق تۈرۈم قۇتىسى</string>
+ <string name="start_dreams">ئېكران قوغدىغۇچ</string>
+ <string name="ethernet_label">دائىرىلىك تور</string>
+ <string name="quick_settings_bluetooth_label">كۆكچىش</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label">كۆكچىش (<xliff:g id="NUMBER">%d</xliff:g> ئۈسكۈنە)</string>
+ <string name="quick_settings_bluetooth_off_label">كۆكچىش تاقاق</string>
+ <string name="quick_settings_brightness_label">يورۇقلۇق</string>
+ <string name="quick_settings_ime_label">كىرگۈزگۈچ</string>
+ <string name="quick_settings_location_label">ئورنى</string>
+ <string name="quick_settings_location_off_label">ئورۇن ئۇچۇرى تاقاق</string>
+ <string name="quick_settings_media_device_label">ۋاستە ئۈسكۈنە</string>
+ <string name="quick_settings_rssi_label">RSSI</string>
+ <string name="quick_settings_rssi_emergency_only">جىددىي تېلېفونلا ئۇرغىلى بولىدۇ</string>
+ <string name="quick_settings_settings_label">تەڭشەكلەر</string>
+ <string name="quick_settings_time_label">ۋاقىت</string>
+ <string name="quick_settings_user_label">مەن</string>
+ <string name="quick_settings_wifi_not_connected">باغلانمىدى</string>
+ <string name="quick_settings_wifi_no_network">تور يوق</string>
+ <string name="quick_settings_wifi_off_label">Wi-Fi تاقاق</string>
+ <string name="quick_settings_brightness_dialog_title">يورۇقلۇق</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label">ئاپتوماتىك</string>
+ <string name="battery_meter_very_low_overlay_symbol">!</string>
+ <string name="ssl_ca_cert_warning">تور نازارەت قىلىنغان\nبولۇشى مۇمكىن</string>
+ <string name="status_bar_ethernet">دائىرىلىك تور</string>
+ <string name="status_bar_airplane">ئايروپىلان ھالىتى</string>
+</resources>
diff --git a/packages/SystemUI/res/values-uk/cm_arrays.xml b/packages/SystemUI/res/values-uk/cm_arrays.xml
new file mode 100644
index 0000000..8d05dc1
--- /dev/null
+++ b/packages/SystemUI/res/values-uk/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>Пн</item>
+ <item>ПнСх</item>
+ <item>Сх</item>
+ <item>ПдСх</item>
+ <item>Пд</item>
+ <item>ПдЗх</item>
+ <item>Зх</item>
+ <item>ПнЗх</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-uk/cm_strings.xml b/packages/SystemUI/res/values-uk/cm_strings.xml
new file mode 100644
index 0000000..7168559
--- /dev/null
+++ b/packages/SystemUI/res/values-uk/cm_strings.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Проведіть вправо для %1$s</string>
+ <string name="right_shortcut_hint">Проведіть вліво для %1$s</string>
+ <string name="lockscreen_message">Натисніть на іконку ліворуч або праворуч для зміни ярлика екрану блокування.</string>
+ <string name="lockscreen_default_target">За замовчуванням</string>
+ <string name="select_application">Вибрати програму</string>
+ <string name="lockscreen_choose_action_title">Виберіть дію</string>
+ <string name="lockscreen_none_target">НІчого</string>
+ <string name="navbar_dialog_title">Виберіть дію щоб призначити</string>
+ <string name="navbar_home_button">Кнопка Додому</string>
+ <string name="navbar_recent_button">Останні програми</string>
+ <string name="navbar_search_button">Кнопка Пошук</string>
+ <string name="navbar_back_button">Кнопка Назад</string>
+ <string name="navbar_empty_button">Пуста кнопка</string>
+ <string name="navbar_menu_conditional_button">Меню (якщо доступно)</string>
+ <string name="navbar_menu_always_button">Меню (завжди)</string>
+ <string name="navbar_menu_big_button">Кнопка Меню</string>
+ <string name="accessibility_dpad_left">Курсор ліворуч</string>
+ <string name="accessibility_dpad_right">Курсор праворуч</string>
+ <string name="advanced_dev_option_wipe_app">Стерти дані програм</string>
+ <string name="advanced_dev_option_force_stop">Примусово зупинити</string>
+ <string name="advanced_dev_option_uninstall">Деінсталювати</string>
+ <string name="accessibility_notification_brightness">Яскравість</string>
+ <string name="accessibility_quick_settings_profiles_off">Профілі вимкнено.</string>
+ <string name="accessibility_quick_settings_profiles">Профіль: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Профілі вимкнено.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Профіль змінено на <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Ініціалізація\u2026</string>
+ <string name="led_notification_title">Індикатор подій</string>
+ <string name="led_notification_text">Світлодіод увімкнено параметрами</string>
+ <string name="qs_tile_edit_header_instruction">Натисніть і утримуйте плитку, щоб змінити</string>
+ <string name="quick_settings_edit_label">Редагувати плитки</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Не вдалося видалити кнопку редагування</string>
+ <string name="qs_tiles_reset_confirmation">Відновити налаштування плиток за замовчуванням?</string>
+ <string name="quick_settings_tile_reset_to_default">Відновити за замовчуванням</string>
+ <string name="quick_settings_title_header">Заголовок</string>
+ <string name="quick_settings_title_tiles">Плитки</string>
+ <string name="quick_settings_title_show_weather">Показати погоду</string>
+ <string name="quick_settings_title_enlarge_first_row">Збільшити перший рядок</string>
+ <string name="screen_pinning_description_no_navbar">Триматиме це перед Вами, доки не відкріпите. Торкніться й утримуйте кнопку «Назад», щоб відкріпити.</string>
+ <string name="quick_settings_custom_tile_detail_title">Власна плитка</string>
+ <string name="quick_settings_remove">Видалити плитку</string>
+ <string name="quick_settings_network_adb_label">Налагодження по мережі</string>
+ <string name="quick_settings_compass_label">Компас</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Системні профілі</string>
+ <string name="quick_settings_profiles_off">Профілі вимкнуто</string>
+ <string name="quick_settings_heads_up_label">Спливаючі сповіщення</string>
+ <string name="quick_settings_battery_saver_label">Енергозбереження</string>
+ <string name="accessibility_quick_settings_sync_off">Синхронізацію вимкнено.</string>
+ <string name="accessibility_quick_settings_sync_on">Синхронізацію увімкнено.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Синхронізацію вимкнено.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Синхронізація увімкнено.</string>
+ <string name="quick_settings_sync_label">Синхронізація</string>
+ <string name="quick_settings_volume_panel_label">Панель гучності</string>
+ <string name="quick_settings_usb_tether_label">USB-модем</string>
+ <string name="quick_settings_screen_timeout_detail_title">Тайм-аут екрану</string>
+ <string name="quick_settings_lockscreen_label">Заблокувати екран</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Блокування екрану ввімкнено</string>
+ <string name="accessibility_quick_settings_screen_timeout">Вимкнення екрана через: <xliff:g id="timeout" example="30 seconds">%s</xliff:g> секунд.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Вимкнення екрана відбувається через <xliff:g id="timeout" example="30 seconds">%s</xliff:g> секунд бездіяльності.</string>
+ <string name="qs_tile_performance">Енергоспоживання</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Режим батареї: збереження енергії.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Режим батареї: збалансований режим.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Режим батареї: висока продуктивність.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Енергоспоживання: енергоефективне.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Енергоспоживання: продуктивне.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Акумулятор тепер в режимі економії енергії.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Режим акумулятора змінено на збалансований.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Режим акумулятора змінено для високої продуктивності.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Енергоспоживання змінено на ефективне.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Енергоспоживання змінено на продуктивне.</string>
+ <string name="quick_settings_performance_profile_detail_title">Енергоспоживання</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Блокування екрана вимкнено.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Блокування екрана увімкнено.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Блокування екрана вимкнено.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Блокування екрана увімкнено.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display вимкнено.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display увімкнено.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient дисплей вимкнено.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display увімкнено.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Спливаючі сповіщення вимкнено.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Спливаючі сповіщення увімкнено.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Спливаючі сповіщення вимкнено.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Спливаючі сповіщення увімкнено.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Енергозбереження вимкнено.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Енергозбереження увімкнено.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Енергозбереження вимкнено.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Енергозбереження увімкнено.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Динамічні плитки</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Наступний сигнал</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Вибір способу вводу</string>
+ <string name="dynamic_qs_tile_su_label">Root доступ</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay вимкнено.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: автоматичний режим.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: денний режим.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: нічний режим.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: режим «На вулиці».</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay вимкнено.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay у автоматичниому режимі.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay у денному режимі.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay у нічному режимі.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay у режимі «На вулиці».</string>
+ <string name="quick_settings_title_advanced_location">Параметри відправки геоданих</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Надсилання місця розташування: економія батареї.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Надсилання місця розташування: тільки датчики.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Надсилання місця розташування: висока точність.</string>
+ <string name="quick_settings_location_detail_title">Режим розташування</string>
+ <string name="quick_settings_location_battery_saving_label">Економія батареї</string>
+ <string name="quick_settings_location_gps_only_label">По датчиках пристрою</string>
+ <string name="quick_settings_location_high_accuracy_label">Висока точність</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Визначення місцезнаходження у режимі економії батареї.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Визначення місцезнаходження тепер використовує лише датчики пристрою.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Визначення місцезнаходження у режимі високої точності.</string>
+ <string name="quick_settings_tiles_category_system">Системні плитки</string>
+ <string name="quick_settings_tiles_add_tiles">Додати плитку</string>
+</resources>
diff --git a/packages/SystemUI/res/values-vi/cm_arrays.xml b/packages/SystemUI/res/values-vi/cm_arrays.xml
new file mode 100644
index 0000000..582b87c
--- /dev/null
+++ b/packages/SystemUI/res/values-vi/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>B</item>
+ <item>ĐB</item>
+ <item>Đ</item>
+ <item>ĐN</item>
+ <item>N</item>
+ <item>TN</item>
+ <item>T</item>
+ <item>TB</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-vi/cm_strings.xml b/packages/SystemUI/res/values-vi/cm_strings.xml
new file mode 100644
index 0000000..d094a3e
--- /dev/null
+++ b/packages/SystemUI/res/values-vi/cm_strings.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">Vuốt sang phải cho %1$s</string>
+ <string name="right_shortcut_hint">Vuốt sang trái cho %1$s</string>
+ <string name="select_application">Chọn ứng dụng</string>
+ <string name="lockscreen_choose_action_title">Chọn hành động</string>
+ <string name="lockscreen_none_target">Không</string>
+ <string name="navbar_dialog_title">Chọn hành động để gán</string>
+ <string name="navbar_home_button">Nút Home</string>
+ <string name="navbar_recent_button">Nút ứng dụng gần đây</string>
+ <string name="navbar_search_button">Nút tìm kiếm</string>
+ <string name="navbar_back_button">Nút quay lại</string>
+ <string name="navbar_empty_button">Nút trống</string>
+ <string name="navbar_menu_conditional_button">Phím trình đơn (tự ẩn)</string>
+ <string name="navbar_menu_always_button">Nút trình đơn (luôn hiện)</string>
+ <string name="navbar_menu_big_button">Nút trình đơn</string>
+ <string name="accessibility_dpad_left">Trỏ trái</string>
+ <string name="accessibility_dpad_right">Trỏ phải</string>
+ <string name="advanced_dev_option_wipe_app">Xoá dữ liệu ứng dụng</string>
+ <string name="advanced_dev_option_force_stop">Buộc dừng</string>
+ <string name="advanced_dev_option_uninstall">Gỡ cài đặt</string>
+ <string name="accessibility_quick_settings_profiles_off">Hồ sơ tắt.</string>
+ <string name="accessibility_quick_settings_profiles">Hồ sơ: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">Hồ sơ đã tắt.</string>
+ <string name="accessibility_quick_settings_profiles_changed">Hồ sơ đã đổi thành <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+ <string name="quick_settings_compass_init">Đang khởi tạo\u2026</string>
+ <string name="screen_pinning_description_no_navbar">Điều này sẽ giúp nó hiển thị cho đến khi bạn bỏ ghim. Chạm và giữ nút Quay lại để bỏ ghim.</string>
+ <string name="quick_settings_custom_tile_detail_title">Kiểu xếp cạnh nhau tùy chỉnh</string>
+ <string name="quick_settings_remove">Gỡ kiểu xếp cạnh nhau</string>
+ <string name="quick_settings_network_adb_label">ADB qua mạng</string>
+ <string name="quick_settings_compass_label">La bàn</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">Cấu hình hệ thống</string>
+ <string name="quick_settings_profiles_off">Cấu hình bị vô hiệu hóa</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Trình tiết kiệm pin</string>
+ <string name="accessibility_quick_settings_sync_off">Tắt đồng bộ.</string>
+ <string name="accessibility_quick_settings_sync_on">Bật đồng bộ.</string>
+ <string name="accessibility_quick_settings_sync_changed_off">Đã tắt đồng bộ.</string>
+ <string name="accessibility_quick_settings_sync_changed_on">Đã bật đồng bộ.</string>
+ <string name="quick_settings_sync_label">Đồng bộ</string>
+ <string name="quick_settings_volume_panel_label">Bảng điều khiển âm lượng</string>
+ <string name="quick_settings_usb_tether_label">Kết nối mạng qua USB</string>
+ <string name="quick_settings_screen_timeout_detail_title">Thời gian sáng màn hình</string>
+ <string name="quick_settings_lockscreen_label">Màn hình khoá</string>
+ <string name="quick_settings_ambient_display_label">Hiển thị môi trường xung quanh</string>
+ <string name="quick_settings_lockscreen_label_enforced">Buộc khoá màn hình</string>
+ <string name="accessibility_quick_settings_screen_timeout">Thời gian chờ của màn hình: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">Thời gian chờ của màn hình đã đổi thành <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Chế độ pin</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Chế độ pin: chế độ tiết kiệm năng lượng.</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">Chế độ pin: chế độ cân bằng.</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">Pin chế độ: chế độ hiệu suất.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Chế độ pin: chế độ hiệu quả.</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Chế độ pin: chế độ nhanh.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Chế độ pin đã đổi sang chế độ tiết kiệm năng lượng.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Chế độ pin đã đổi sang chế độ cân bằng.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Chế độ pin đã đổi sang chế độ hiệu suất.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Chế độ pin được chuyển sang hiệu quả.</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Chế độ pin được chuyển sang nhanh.</string>
+ <string name="quick_settings_performance_profile_detail_title">Chế độ pin</string>
+ <string name="accessibility_quick_settings_lock_screen_off">Màn hình khóa tắt.</string>
+ <string name="accessibility_quick_settings_lock_screen_on">Màn hình khóa bật.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Màn hình khóa đã tắt.</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Màn hình khóa đã bật.</string>
+ <string name="accessibility_quick_settings_ambient_display_off">Tắt hiển thị môi trường xung quanh.</string>
+ <string name="accessibility_quick_settings_ambient_display_on">Hiển thị môi trường xung quanh bật.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Hiển thị môi trường xung quanh đã tắt.</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Hiển thị môi trường xung quanh đã bật.</string>
+ <string name="accessibility_quick_settings_heads_up_off">Heads up tắt.</string>
+ <string name="accessibility_quick_settings_heads_up_on">Heads up bật.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up đã tắt.</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up đã bật.</string>
+ <string name="accessibility_quick_settings_battery_saver_off">Trình tiết kiệm pin: Tắt.</string>
+ <string name="accessibility_quick_settings_battery_saver_on">Trình tiết kiệm pin: Bật.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Đã tắt Trinh tiết kiệm pin.</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Đã bật Trình tiết kiệm pin.</string>
+ <string name="quick_settings_dynamic_tile_detail_title">Kiểu xếp cạnh nhau động</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Báo thức tiếp theo</string>
+ <string name="dynamic_qs_tile_ime_selector_label">Trình chọn IME</string>
+ <string name="dynamic_qs_tile_su_label">Truy cập root</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay tắt.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: chế độ tự động.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: chế độ ban ngày.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: chế độ ban đêm.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: chế độ ngoài trời.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay đã tắt.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay đã đổi sang chế độ tự động.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay đã đổi sang chế độ ban ngày.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay đã đổi sang chế độ ban đêm.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay đã đổi sang chế độ ngoài trời.</string>
+ <string name="accessibility_quick_settings_location_battery_saving">Báo cáo vị trí: chế độ tiết kiệm pin.</string>
+ <string name="accessibility_quick_settings_location_gps_only">Báo cáo vị trí: chế độ chỉ cám biến.</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">Báo cáo vị trí: chế độ chính xác cao.</string>
+ <string name="quick_settings_location_detail_title">Chế độ vị trí</string>
+ <string name="quick_settings_location_battery_saving_label">Tiết kiệm pin</string>
+ <string name="quick_settings_location_gps_only_label">Chỉ thiết bị</string>
+ <string name="quick_settings_location_high_accuracy_label">Chính xác cao</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Báo cáo vị trí đã đổi sang chế độ tiết kiệm pin.</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">Báo cáo vị trí đã đổi sang chế độ chỉ cảm biến.</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Báo cáo vị trí đã đổi sang chế độ chính xác cao.</string>
+</resources>
diff --git a/packages/SystemUI/res/values-xhdpi/cm_dimens.xml b/packages/SystemUI/res/values-xhdpi/cm_dimens.xml
new file mode 100644
index 0000000..eacf1d9
--- /dev/null
+++ b/packages/SystemUI/res/values-xhdpi/cm_dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<resources>
+ <dimen name="weather_text_size">12sp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-xxhdpi/cm_dimens.xml b/packages/SystemUI/res/values-xxhdpi/cm_dimens.xml
new file mode 100644
index 0000000..eacf1d9
--- /dev/null
+++ b/packages/SystemUI/res/values-xxhdpi/cm_dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<resources>
+ <dimen name="weather_text_size">12sp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-zh-rCN/cm_arrays.xml b/packages/SystemUI/res/values-zh-rCN/cm_arrays.xml
new file mode 100644
index 0000000..e8a8e90
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rCN/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>北</item>
+ <item>东北</item>
+ <item>东</item>
+ <item>东南</item>
+ <item>南</item>
+ <item>西南</item>
+ <item>西</item>
+ <item>西北</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/cm_strings.xml b/packages/SystemUI/res/values-zh-rCN/cm_strings.xml
new file mode 100644
index 0000000..612b327
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rCN/cm_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">向右滑动以%1$s</string>
+ <string name="right_shortcut_hint">向左滑动以%1$s</string>
+ <string name="lockscreen_message">轻触左边或右边的图标来重新分配锁屏快捷方式。</string>
+ <string name="lockscreen_default_target">默认</string>
+ <string name="select_application">选择应用</string>
+ <string name="lockscreen_choose_action_title">选择操作</string>
+ <string name="lockscreen_none_target">无</string>
+ <string name="navbar_dialog_title">选择要分配的动作</string>
+ <string name="navbar_home_button">Home 键</string>
+ <string name="navbar_recent_button">任务键</string>
+ <string name="navbar_search_button">搜索键</string>
+ <string name="navbar_back_button">返回键</string>
+ <string name="navbar_empty_button">空白键</string>
+ <string name="navbar_menu_conditional_button">菜单键 (自动隐藏)</string>
+ <string name="navbar_menu_always_button">菜单键 (总是显示)</string>
+ <string name="navbar_menu_big_button">菜单键</string>
+ <string name="accessibility_dpad_left">光标左移</string>
+ <string name="accessibility_dpad_right">光标右移</string>
+ <string name="advanced_dev_option_wipe_app">擦除应用数据</string>
+ <string name="advanced_dev_option_force_stop">强行停止</string>
+ <string name="advanced_dev_option_uninstall">卸载</string>
+ <string name="accessibility_notification_brightness">指示灯亮度</string>
+ <string name="accessibility_quick_settings_profiles_off">情景模式关闭。</string>
+ <string name="accessibility_quick_settings_profiles">情景模式:<xliff:g id="profile" example="Default">%s</xliff:g>。</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">情景模式已关闭。</string>
+ <string name="accessibility_quick_settings_profiles_changed">情景模式已修改为<xliff:g id="profile" example="Default">%s</xliff:g>。</string>
+ <string name="quick_settings_compass_init">正在初始化\u2026</string>
+ <string name="led_notification_title">指示灯设置</string>
+ <string name="led_notification_text">LED 灯由设置启用</string>
+ <string name="qs_tile_edit_header_instruction">长按瓷块来重新排列</string>
+ <string name="quick_settings_edit_label">编辑瓷块</string>
+ <string name="quick_settings_cannot_delete_edit_tile">不能删除“编辑”瓷块</string>
+ <string name="qs_tiles_reset_confirmation">重置快速设置瓷块位置为默认配置?</string>
+ <string name="quick_settings_tile_reset_to_default">重置为默认布局</string>
+ <string name="quick_settings_title_header">标题</string>
+ <string name="quick_settings_title_tiles">瓷块</string>
+ <string name="quick_settings_title_show_weather">显示天气</string>
+ <string name="quick_settings_title_show_brightness_slider">显示亮度滑块</string>
+ <string name="quick_settings_title_enlarge_first_row">扩大第一行</string>
+ <string name="screen_pinning_description_no_navbar">这将会固定显示此屏幕,直到您取消固定为止。触摸并按住返回键即可取消固定。</string>
+ <string name="quick_settings_custom_tile_detail_title">自定义瓷片</string>
+ <string name="quick_settings_remove">移除瓷片</string>
+ <string name="quick_settings_network_adb_label">网络 ADB 调试</string>
+ <string name="quick_settings_compass_label">指南针</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">情景模式</string>
+ <string name="quick_settings_profiles_off">已禁用情景模式</string>
+ <string name="quick_settings_heads_up_label">浮动通知</string>
+ <string name="quick_settings_battery_saver_label">省电模式</string>
+ <string name="quick_settings_caffeine_label">咖啡因</string>
+ <string name="accessibility_quick_settings_sync_off">同步关闭。</string>
+ <string name="accessibility_quick_settings_sync_on">同步开启。</string>
+ <string name="accessibility_quick_settings_sync_changed_off">同步已关闭。</string>
+ <string name="accessibility_quick_settings_sync_changed_on">同步已开启。</string>
+ <string name="quick_settings_sync_label">同步</string>
+ <string name="quick_settings_volume_panel_label">音量面板</string>
+ <string name="quick_settings_usb_tether_label">USB 共享网络</string>
+ <string name="quick_settings_screen_timeout_detail_title">屏幕超时</string>
+ <string name="quick_settings_lockscreen_label">锁屏</string>
+ <string name="quick_settings_ambient_display_label">环境显示</string>
+ <string name="quick_settings_lockscreen_label_enforced">强制锁屏</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">已在情景模式中禁用</string>
+ <string name="accessibility_quick_settings_screen_timeout">屏幕超时:<xliff:g id="timeout" example="30 seconds">%s</xliff:g>。</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">屏幕超时已修改为<xliff:g id="timeout" example="30 seconds">%s</xliff:g>。</string>
+ <string name="qs_tile_performance">电池模式</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">电池模式:节电模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">电池模式:平衡模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">电池模式:性能模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_power">电池模式:效率模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">电池模式:快速模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">电池模式已更改为省电模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">电池模式已修改为平衡模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">电池模式已修改为性能模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">电池模式已修改为效率模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">电池模式已修改为快速模式。</string>
+ <string name="quick_settings_performance_profile_detail_title">电池模式</string>
+ <string name="accessibility_quick_settings_lock_screen_off">锁屏关闭。</string>
+ <string name="accessibility_quick_settings_lock_screen_on">锁屏开启。</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">锁屏已关闭。</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">锁屏已开启。</string>
+ <string name="accessibility_quick_settings_ambient_display_off">关闭环境显示。</string>
+ <string name="accessibility_quick_settings_ambient_display_on">开启环境显示。</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">环境显示已关闭。</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">环境显示已开启。</string>
+ <string name="accessibility_quick_settings_heads_up_off">浮动通知关。</string>
+ <string name="accessibility_quick_settings_heads_up_on">浮动通知开。</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">浮动通知已关闭。</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">浮动通知已开启。</string>
+ <string name="accessibility_quick_settings_caffeine_off">咖啡因模式关闭</string>
+ <string name="accessibility_quick_settings_caffeine_on">咖啡因模式开启</string>
+ <string name="accessibility_quick_settings_battery_saver_off">省电模式关闭。</string>
+ <string name="accessibility_quick_settings_battery_saver_on">省电模式开启。</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_off">已关闭省电模式。</string>
+ <string name="accessibility_quick_settings_battery_saver_changed_on">已开启省电模式。</string>
+ <string name="quick_settings_dynamic_tile_detail_title">动态按钮</string>
+ <string name="dynamic_qs_tile_next_alarm_label">下一个闹铃</string>
+ <string name="dynamic_qs_tile_ime_selector_label">输入法选择器</string>
+ <string name="dynamic_qs_tile_su_label">Root 授权</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay 关闭。</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay:自动模式。</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay:白天模式。</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay:夜晚模式。</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay:户外模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay 已关闭。</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay 已修改为自动模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay 已修改为白天模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay 已修改为夜晚模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay 已修改为户外模式。</string>
+ <string name="quick_settings_title_advanced_location">三种状态的位置设置</string>
+ <string name="accessibility_quick_settings_location_battery_saving">位置报告:节电模式。</string>
+ <string name="accessibility_quick_settings_location_gps_only">位置报告:仅传感器模式。</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">位置报告:高准确度模式。</string>
+ <string name="quick_settings_location_detail_title">位置信息模式</string>
+ <string name="quick_settings_location_battery_saving_label">耗电量低</string>
+ <string name="quick_settings_location_gps_only_label">仅限设备</string>
+ <string name="quick_settings_location_high_accuracy_label">准确度高</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">地理位置报告已修改为节能模式。</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">位置报告已修改为仅使用传感器模式。</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">位置报告已修改为准确度高模式。</string>
+ <string name="quick_settings_tiles_category_system">系统磁块</string>
+ <string name="quick_settings_tiles_add_tiles">添加磁块</string>
+ <string name="hotspot_apm_message">飞行模式启用时无法连接到移动网络。请禁用飞行模式并重试。</string>
+ <string name="quick_settings_tile_flashlight_not_title">手电筒已开</string>
+ <string name="quick_settings_tile_flashlight_not_summary">轻按以关闭</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/cm_arrays.xml b/packages/SystemUI/res/values-zh-rHK/cm_arrays.xml
new file mode 100644
index 0000000..1808f89
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rHK/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>北</item>
+ <item>東北</item>
+ <item>東</item>
+ <item>東南</item>
+ <item>南</item>
+ <item>西南</item>
+ <item>西</item>
+ <item>西北</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/cm_strings.xml b/packages/SystemUI/res/values-zh-rHK/cm_strings.xml
new file mode 100644
index 0000000..9d6d7ed
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rHK/cm_strings.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">向右滑動即可%1$s</string>
+ <string name="right_shortcut_hint">向左滑動即可%1$s</string>
+ <string name="select_application">選擇應用程式</string>
+ <string name="lockscreen_choose_action_title">選擇操作</string>
+ <string name="lockscreen_none_target">無</string>
+ <string name="navbar_empty_button">清空按鈕</string>
+ <string name="navbar_menu_conditional_button">功能表(自動隱藏)按鈕</string>
+ <string name="navbar_menu_always_button">功能表(一律顯示)按鈕</string>
+ <string name="navbar_menu_big_button">功能表按鈕</string>
+ <string name="accessibility_dpad_left">游標向左</string>
+ <string name="accessibility_dpad_right">游標向右</string>
+ <string name="advanced_dev_option_wipe_app">擦除應用程式數據</string>
+ <string name="advanced_dev_option_force_stop">強制停止</string>
+ <string name="advanced_dev_option_uninstall">解除安裝</string>
+ <string name="accessibility_quick_settings_profiles_off">設定檔已關閉。</string>
+ <string name="accessibility_quick_settings_profiles">設定檔:<xliff:g id="profile" example="Default">%s</xliff:g>。</string>
+ <string name="accessibility_quick_settings_profiles_changed_off">設定檔已關閉。</string>
+ <string name="accessibility_quick_settings_profiles_changed">設定檔已改為<xliff:g id="profile" example="Default">%s</xliff:g>。</string>
+ <string name="quick_settings_compass_init">正在初始化\u2026</string>
+ <string name="screen_pinning_description_no_navbar">這將保持畫面在視野範圍內,直至您解鎖畫面位置。觸摸并按住返回按鈕即可解鎖畫面。</string>
+ <string name="quick_settings_custom_tile_detail_title">自訂方塊</string>
+ <string name="quick_settings_remove">移除方塊</string>
+ <string name="quick_settings_network_adb_label">透過網絡連接 ADB</string>
+ <string name="quick_settings_compass_label">指南針</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">系統設定檔</string>
+ <string name="quick_settings_heads_up_label">浮動通知</string>
+ <string name="accessibility_quick_settings_sync_off">已關閉同步。</string>
+ <string name="accessibility_quick_settings_sync_on">已開啟同步。</string>
+ <string name="accessibility_quick_settings_sync_changed_off">同步已關閉。</string>
+ <string name="accessibility_quick_settings_sync_changed_on">同步已開啟。</string>
+ <string name="quick_settings_sync_label">同步</string>
+ <string name="quick_settings_volume_panel_label">音量區</string>
+ <string name="quick_settings_usb_tether_label">USB 網絡共享</string>
+ <string name="quick_settings_screen_timeout_detail_title">螢幕逾時</string>
+ <string name="quick_settings_ambient_display_label">環境顯示</string>
+ <string name="quick_settings_lockscreen_label_enforced">強制執行鎖定螢幕</string>
+ <string name="accessibility_quick_settings_screen_timeout">螢幕逾時:<xliff:g id="timeout" example="30 seconds">%s</xliff:g>。</string>
+ <string name="accessibility_quick_settings_screen_timeout_changed">螢幕逾時設定已改為<xliff:g id="timeout" example="30 seconds">%s</xliff:g>。</string>
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">電池模式:省電模式</string>
+ <string name="accessibility_quick_settings_perf_profile_bal">電池模式:平衡模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_perf">電池模式:性能模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">電池模式已改為省電模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">電池模式已改為平衡模式。</string>
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">電池模式已改為性能模式。</string>
+ <string name="accessibility_quick_settings_lock_screen_off">已關閉鎖定螢幕功能。</string>
+ <string name="accessibility_quick_settings_lock_screen_on">已開啟鎖定螢幕功能。</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_off">已關閉鎖定螢幕功能。</string>
+ <string name="accessibility_quick_settings_lock_screen_changed_on">已開啟鎖定螢幕功能。</string>
+ <string name="accessibility_quick_settings_heads_up_off">已關閉浮動通知。</string>
+ <string name="accessibility_quick_settings_heads_up_on">已開啟浮動通知。</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">已關閉浮動通知。</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">已開啟浮動通知。</string>
+ <string name="quick_settings_dynamic_tile_detail_title">動態方塊</string>
+ <string name="dynamic_qs_tile_next_alarm_label">下一個鬧鐘</string>
+ <string name="dynamic_qs_tile_ime_selector_label">輸入法選擇器</string>
+ <string name="dynamic_qs_tile_su_label">Root 權限</string>
+ <string name="accessibility_quick_settings_live_display_off">已關閉 LiveDisplay。</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: 自動模式。</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: 日間模式。</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: 夜間模式。</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: 戶外模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay 已關閉。</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay 已改為自動模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay 已改為日間模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay 已改為夜間模式。</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay 已改為戶外模式。</string>
+ <string name="accessibility_quick_settings_location_battery_saving">定位報告:省電模式。</string>
+ <string name="accessibility_quick_settings_location_gps_only">定位報告:僅感應器模式。</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">定位報告:高精度模式。</string>
+ <string name="quick_settings_location_detail_title">定位模式</string>
+ <string name="quick_settings_location_battery_saving_label">省電</string>
+ <string name="quick_settings_location_gps_only_label">僅限裝置</string>
+ <string name="quick_settings_location_high_accuracy_label">高精度</string>
+ <string name="accessibility_quick_settings_location_changed_battery_saving">定位報告已改為省電模式。</string>
+ <string name="accessibility_quick_settings_location_changed_gps_only">定位報告已改為僅感應器模式。</string>
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">定位報告已改為高精度模式。</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/cm_arrays.xml b/packages/SystemUI/res/values-zh-rTW/cm_arrays.xml
new file mode 100644
index 0000000..1808f89
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rTW/cm_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="cardinal_directions">
+ <item>北</item>
+ <item>東北</item>
+ <item>東</item>
+ <item>東南</item>
+ <item>南</item>
+ <item>西南</item>
+ <item>西</item>
+ <item>西北</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/cm_strings.xml b/packages/SystemUI/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 0000000..17b1c99
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+ <string name="left_shortcut_hint">向右滑動即可%1$s</string>
+ <string name="right_shortcut_hint">向左滑動即可%1$s</string>
+ <string name="lockscreen_message">輕觸左側或右側的圖示以設定鎖定畫面捷徑</string>
+ <string name="lockscreen_default_target">預設</string>
+ <string name="select_application">選取應用程式</string>
+ <string name="lockscreen_choose_action_title">選取操作</string>
+ <string name="lockscreen_none_target">無</string>
+ <string name="navbar_dialog_title">選擇要指定的操作</string>
+ <string name="navbar_home_button">主螢幕鍵</string>
+ <string name="navbar_recent_button">多工鍵</string>
+ <string name="navbar_search_button">搜尋鍵</string>
+ <string name="navbar_back_button">返回鍵</string>
+ <string name="navbar_empty_button">空鍵</string>
+ <string name="navbar_menu_conditional_button">選單鍵 (自動隱藏)</string>
+ <string name="navbar_menu_always_button">選單鍵 (一律顯示)</string>
+ <string name="navbar_menu_big_button">選單鍵</string>
+ <string name="accessibility_dpad_left">游標左移</string>
+ <string name="accessibility_dpad_right">游標右移</string>
+ <string name="advanced_dev_option_wipe_app">清除應用程式資料</string>
+ <string name="advanced_dev_option_force_stop">強制停止</string>
+ <string name="advanced_dev_option_uninstall">解除安裝</string>
+ <string name="accessibility_notification_brightness">亮度</string>
+ <string name="quick_settings_compass_init">正在初始化\u2026</string>
+ <string name="led_notification_title">指示燈設定</string>
+ <string name="led_notification_text">已透過設定啟用 LED 指示燈</string>
+ <string name="qs_tile_edit_header_instruction">按住瓷磚以重新排列</string>
+ <string name="quick_settings_edit_label">編輯瓷磚</string>
+ <string name="quick_settings_cannot_delete_edit_tile">無法刪除編輯瓷磚</string>
+ <string name="qs_tiles_reset_confirmation">將快速設定瓷磚還原至預設配置?</string>
+ <string name="quick_settings_tile_reset_to_default">還原至預設布局</string>
+ <string name="quick_settings_title_header">標題</string>
+ <string name="quick_settings_title_tiles">瓷磚</string>
+ <string name="quick_settings_title_show_weather">顯示天氣資訊</string>
+ <string name="quick_settings_title_show_brightness_slider">顯示亮度滑桿</string>
+ <string name="quick_settings_title_enlarge_first_row">擴大首行</string>
+ <string name="quick_settings_custom_tile_detail_title">自訂瓷磚</string>
+ <string name="quick_settings_remove">移除瓷磚</string>
+ <string name="quick_settings_network_adb_label">網路 ADB</string>
+ <string name="quick_settings_compass_label">指南針</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">系統設定檔</string>
+ <string name="quick_settings_profiles_off">已停用設定檔</string>
+ <string name="quick_settings_heads_up_label">浮動通知</string>
+ <string name="accessibility_quick_settings_sync_off">同步關閉</string>
+ <string name="accessibility_quick_settings_sync_on">同步開啟</string>
+ <string name="accessibility_quick_settings_sync_changed_off">同步已關閉</string>
+ <string name="accessibility_quick_settings_sync_changed_on">同步已開啟</string>
+ <string name="quick_settings_sync_label">同步</string>
+ <string name="quick_settings_usb_tether_label">USB 網路共用</string>
+ <string name="quick_settings_screen_timeout_detail_title">螢幕閒置時間</string>
+ <string name="quick_settings_lockscreen_label">鎖定畫面</string>
+ <string name="quick_settings_ambient_display_label">環境顯示</string>
+ <string name="quick_settings_lockscreen_label_enforced">強制執行鎖定畫面</string>
+ <string name="accessibility_quick_settings_ambient_display_off">環境顯示關閉</string>
+ <string name="accessibility_quick_settings_ambient_display_on">環境顯示開啟</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_off">環境顯示已關閉</string>
+ <string name="accessibility_quick_settings_ambient_display_changed_on">環境顯示已開啟</string>
+ <string name="accessibility_quick_settings_heads_up_off">浮動通知關閉</string>
+ <string name="accessibility_quick_settings_heads_up_on">浮動通知開啟</string>
+ <string name="accessibility_quick_settings_heads_up_changed_off">浮動通知已關閉</string>
+ <string name="accessibility_quick_settings_heads_up_changed_on">浮動通知已開啟</string>
+ <string name="quick_settings_dynamic_tile_detail_title">動態磚</string>
+ <string name="dynamic_qs_tile_next_alarm_label">下一個鬧鐘</string>
+ <string name="dynamic_qs_tile_ime_selector_label">輸入法選擇器</string>
+ <string name="dynamic_qs_tile_su_label">Root 權限</string>
+ <string name="quick_settings_title_advanced_location">定位模式</string>
+ <string name="accessibility_quick_settings_location_battery_saving">位置回報:節約耗電量</string>
+ <string name="accessibility_quick_settings_location_gps_only">位置回報:僅限裝置</string>
+ <string name="accessibility_quick_settings_location_high_accuracy">位置回報:高精確度</string>
+ <string name="quick_settings_location_detail_title">定位模式</string>
+ <string name="quick_settings_location_battery_saving_label">節約耗電量</string>
+ <string name="quick_settings_location_gps_only_label">僅限裝置</string>
+ <string name="quick_settings_location_high_accuracy_label">高精確度</string>
+ <string name="quick_settings_tiles_category_system">系統瓷磚</string>
+ <string name="quick_settings_tiles_add_tiles">新增瓷磚</string>
+</resources>
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index 6102aa6..79a4649 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -26,7 +26,7 @@
</array>
<array name="batterymeter_color_values">
<item>@*android:color/battery_saver_mode_color</item>
- <item>#FFFFFFFF</item>
+ <item>@color/batterymeter_base_color</item>
</array>
<array name="batterymeter_bolt_points">
<item>73</item> <item>0</item>
diff --git a/packages/SystemUI/res/values/cm_arrays.xml b/packages/SystemUI/res/values/cm_arrays.xml
new file mode 100644
index 0000000..7508a65
--- /dev/null
+++ b/packages/SystemUI/res/values/cm_arrays.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012-2014 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <array name="batterymeter_inverted_bolt_points" translatable="false">
+ <item>743</item><item>73</item>
+ <item>743</item><item>292</item>
+ <item>442</item><item>201</item>
+ <item>442</item><item>400</item>
+ <item>0</item><item>20</item>
+ <item>369</item><item>157</item>
+ <item>369</item><item>0</item>
+ </array>
+
+ <!-- Cardinal directions for the compass tile -->
+ <string-array name="cardinal_directions">
+ <item>N</item> <!-- North -->
+ <item>NE</item> <!-- North east -->
+ <item>E</item> <!-- East -->
+ <item>SE</item> <!-- South east -->
+ <item>S</item> <!-- South -->
+ <item>SW</item> <!-- South west -->
+ <item>W</item> <!-- West -->
+ <item>NW</item> <!-- North west -->
+ </string-array>
+
+ <!-- Performance profiles description-->
+ <string-array name="perf_profile_description" translatable="false">
+ <item>@string/accessibility_quick_settings_perf_profile_pwrsv</item>
+ <item>@string/accessibility_quick_settings_perf_profile_bias_power</item>
+ <item>@string/accessibility_quick_settings_perf_profile_bal</item>
+ <item>@string/accessibility_quick_settings_perf_profile_bias_perf</item>
+ <item>@string/accessibility_quick_settings_perf_profile_perf</item>
+ </string-array>
+
+ <!-- Performance profiles announcement-->
+ <string-array name="perf_profile_announcement" translatable="false">
+ <item>@string/accessibility_quick_settings_perf_profile_changed_pwrsv</item>
+ <item>@string/accessibility_quick_settings_perf_profile_changed_bias_power</item>
+ <item>@string/accessibility_quick_settings_perf_profile_changed_bal</item>
+ <item>@string/accessibility_quick_settings_perf_profile_changed_bias_perf</item>
+ <item>@string/accessibility_quick_settings_perf_profile_changed_perf</item>
+ </string-array>
+
+ <!-- Dynamic tiles -->
+ <string-array name="dynamic_qs_tiles_labels" translatable="false">
+ <item>@string/dynamic_qs_tile_next_alarm_label</item>
+ <item>@string/dynamic_qs_tile_ime_selector_label</item>
+ <item>@string/dynamic_qs_tile_su_label</item>
+ <item>@string/dynamic_qs_tile_adb_label</item>
+ </string-array>
+ <string-array name="dynamic_qs_tiles_icons_resources_ids" translatable="false">
+ <item>ic_dynamic_qs_next_alarm</item>
+ <item>ic_dynamic_qs_ime_selector</item>
+ <item>ic_dynamic_qs_su</item>
+ <item>ic_dynamic_qs_adb</item>
+ </string-array>
+ <string-array name="dynamic_qs_tiles_values" translatable="false">
+ <item>next_alarm</item>
+ <item>ime_selector</item>
+ <item>su</item>
+ <item>adb</item>
+ </string-array>
+
+ <!-- LiveDisplay drawables -->
+ <string-array name="live_display_drawables" translatable="false">
+ <item>@drawable/ic_livedisplay_auto</item>
+ <item>@drawable/ic_livedisplay_off</item>
+ <item>@drawable/ic_livedisplay_day</item>
+ <item>@drawable/ic_livedisplay_night</item>
+ <item>@drawable/ic_livedisplay_outdoor</item>
+ </string-array>
+
+ <!-- LiveDisplay description-->
+ <string-array name="live_display_description" translatable="false">
+ <item>@string/accessibility_quick_settings_live_display_auto</item>
+ <item>@string/accessibility_quick_settings_live_display_off</item>
+ <item>@string/accessibility_quick_settings_live_display_day</item>
+ <item>@string/accessibility_quick_settings_live_display_night</item>
+ <item>@string/accessibility_quick_settings_live_display_outdoor</item>
+ </string-array>
+
+ <!-- LiveDisplay announcement-->
+ <string-array name="live_display_announcement" translatable="false">
+ <item>@string/accessibility_quick_settings_live_display_changed_auto</item>
+ <item>@string/accessibility_quick_settings_live_display_changed_off</item>
+ <item>@string/accessibility_quick_settings_live_display_changed_day</item>
+ <item>@string/accessibility_quick_settings_live_display_changed_night</item>
+ <item>@string/accessibility_quick_settings_live_display_changed_outdoor</item>
+ </string-array>
+
+ <array name="dockbatterymeter_bolt_points" translatable="false">
+ <item>129</item><item>0</item>
+ <item>199</item><item>0</item>
+ <item>199</item><item>168</item>
+ <item>240</item><item>168</item>
+ <item>240</item><item>0</item>
+ <item>312</item><item>0</item>
+ <item>312</item><item>168</item>
+ <item>441</item><item>168</item>
+ <item>441</item><item>252</item>
+ <item>312</item><item>400</item>
+ <item>286</item><item>400</item>
+ <item>286</item><item>702</item>
+ <item>157</item><item>702</item>
+ <item>154</item><item>400</item>
+ <item>129</item><item>400</item>
+ <item>0</item><item>251</item>
+ <item>0</item><item>168</item>
+ <item>129</item><item>168</item>
+ </array>
+
+ <array name="dockbatterymeter_inverted_bolt_points" translatable="false">
+ <item>0</item><item>154</item>
+ <item>302</item><item>154</item>
+ <item>302</item><item>129</item>
+ <item>451</item><item>0</item>
+ <item>534</item><item>0</item>
+ <item>534</item><item>129</item>
+ <item>702</item><item>129</item>
+ <item>702</item><item>199</item>
+ <item>534</item><item>199</item>
+ <item>534</item><item>265</item>
+ <item>702</item><item>265</item>
+ <item>702</item><item>312</item>
+ <item>534</item><item>312</item>
+ <item>534</item><item>441</item>
+ <item>451</item><item>441</item>
+ <item>302</item><item>312</item>
+ <item>302</item><item>286</item>
+ <item>0</item><item>286</item>
+ </array>
+</resources>
diff --git a/packages/SystemUI/res/values/cm_attrs.xml b/packages/SystemUI/res/values/cm_attrs.xml
new file mode 100644
index 0000000..0e4933a
--- /dev/null
+++ b/packages/SystemUI/res/values/cm_attrs.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The CyanogenMod 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.
+-->
+
+<resources>
+ <declare-styleable name="QuickSettingsRow">
+ <attr name="table" format="enum">
+ <enum name="system" value="0"/>
+ <enum name="global" value="1"/>
+ <enum name="secure" value="2"/>
+
+ <enum name="cm_system" value="3"/>
+ <enum name="cm_global" value="4"/>
+ <enum name="cm_secure" value="5"/>
+ </attr>
+
+ <attr name="android:key"/>
+ <attr name="android:title" />
+ <attr name="defaultValue" format="integer"/>
+ </declare-styleable>
+</resources>
+
diff --git a/packages/SystemUI/res/values/cm_colors.xml b/packages/SystemUI/res/values/cm_colors.xml
new file mode 100644
index 0000000..37b34b0
--- /dev/null
+++ b/packages/SystemUI/res/values/cm_colors.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<resources>
+
+ <!-- Color for the "No recent apps" text in the recent apps list. -->
+ <color name="no_recent_apps">#bebebe</color>
+
+ <!-- Colors for the system bars -->
+ <color name="status_bar_background_opaque">@color/system_bar_background_opaque</color>
+ <color name="status_bar_background_semi_transparent">
+ @color/system_bar_background_semi_transparent
+ </color>
+ <color name="status_bar_background_transparent">@color/system_bar_background_transparent</color>
+ <color name="navigation_bar_background_opaque">@color/system_bar_background_opaque</color>
+ <color name="navigation_bar_background_semi_transparent">
+ @color/system_bar_background_semi_transparent
+ </color>
+ <color name="navigation_bar_background_transparent">
+ @color/system_bar_background_transparent
+ </color>
+
+ <!-- Expanded Status Bar Weather Text Colors -->
+ <color name="status_bar_temperature_text_color">#FFFFFFFF</color>
+ <color name="status_bar_temperature_location_text_color">#FFFFFFFF</color>
+
+ <!-- tint of the Visualizer tile -->
+ <color name="visualizer_fill_color">#96FFFFFF</color>
+
+ <!-- Background of the volume panel. See also: volume_dialog_background -->
+ <color name="volume_panel_background_color">@color/system_secondary_color</color>
+
+ <!-- Battery base color -->
+ <color name="batterymeter_base_color">#FFFFFFFF</color>
+
+ <!-- Color for notification icons -->
+ <color name="notification_icon_color">#FFFFFFFF</color>
+
+ <!-- Navigation button ripple color -->
+ <color name="navbutton_ripple_color">#FFFFFFFF</color>
+
+ <!-- Expanded Status Bar Weather Text Colors -->
+ <color name="status_bar_temperature_text_color">#FFFFFFFF</color>
+ <color name="status_bar_temperature_location_text_color">#FFFFFFFF</color>
+
+ <!-- Expanded Status Bar Alarm Status Text Color -->
+ <color name="status_bar_alarm_status_text_color">#64ffffff</color>
+
+ <!-- Expanded Status Bar Battery Level Text Color -->
+ <color name="status_bar_battery_level_text_color">#ffffff</color>
+
+ <!-- QS Toast Text color -->
+ <color name="quick_settings_toast_color">#ffbe1b</color>
+
+ <!-- SystemUI Tuner Icon Tint Color -->
+ <color name="tuner_icon_tint">#4dffffff</color>
+
+ <!-- QS Settings Text Colors -->
+ <color name="qs_tile_reset_to_default_text_color">@android:color/white</color>
+ <color name="qs_title_text_color">#80cbc4</color>
+ <color name="qs_edit_header_instruction_text_color">@android:color/white</color>
+ <color name="qs_row_text_color">@android:color/white</color>
+
+ <!-- natural color of the trash can -->
+ <color name="qs_tile_trash_normal_tint">@android:color/transparent</color>
+ <!-- tint to color trash can when tile is hovering over it -->
+ <color name="qs_tile_trash_delete_tint">#EF5350</color>
+ <!-- Tint to color trash can when hovering edit tile, user cannot delete it.
+ Transparent because we have an animation by default. -->
+ <color name="qs_tile_trash_delete_tint_warning">@android:color/transparent</color>
+
+ <!-- More exposed hard coded colors -->
+ <color name="toggle_slider_text_color">#666666</color>
+ <color name="no_recent_apps_text_color">@android:color/holo_blue_light</color>
+ <color name="no_notifications_text_color">#ffffff</color>
+ <color name="keyguard_overflow_number_text_color">#ff686868</color>
+ <color name="keyguard_carrier_text_color">#ffffff</color>
+ <color name="screen_pinning_description_text_color">@android:color/white</color>
+ <color name="screen_pinning_cancel_button_text_color">@android:color/white</color>
+ <color name="recents_empty_message_text_color">#ffffffff</color>
+ <color name="task_view_header_text_color">#ffffffff</color>
+ <color name="recents_search_bar_label_text_color">#99ffffff</color>
+ <color name="recents_empty_background_color">#80000000</color>
+ <color name="qs_tile_edit_header_instruction_text_color">@android:color/white</color>
+ <color name="mland_scorefield_text_color">#FFAAAAAA</color>
+ <color name="keyguard_indication_text_color">#ffffff</color>
+ <color name="speedbump_line_divider">#6fdddddd</color>
+ <color name="quick_settings_panel_background">#0000</color>
+ <color name="lockscreen_message_text_color">#424242</color>
+ <color name="lockscreen_middle_button_tint_color">#666666</color>
+ <color name="play_button_image_tint_color">#000000</color>
+ <color name="play_button_text_color">#000000</color>
+ <color name="zen_ic_close_tint_color">@android:color/white</color>
+ <color name="header_debug_info_text_color">#00A040</color>
+
+ <!-- QS Detailed View Text and Icon Colors -->
+ <color name="qs_detailed_default_text_color">@android:color/white</color>
+ <color name="qs_detailed_expansion_indicator_color">@color/qs_title_text_color</color>
+ <color name="qs_detailed_title_text_color">@color/qs_title_text_color</color>
+ <color name="qs_detailed_icon_tint_color">@color/qs_title_text_color</color>
+
+ <!-- Quick tile text color when the tile is disabled -->
+ <color name="qs_tile_text_disabled">#ff747474</color>
+
+ <!-- Active color for volume slider -->
+ <color name="volume_slider_active">@color/system_accent_color</color>
+</resources>
diff --git a/packages/SystemUI/res/values/cm_dimens.xml b/packages/SystemUI/res/values/cm_dimens.xml
new file mode 100644
index 0000000..3bce97b
--- /dev/null
+++ b/packages/SystemUI/res/values/cm_dimens.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod 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.
+-->
+<resources>
+
+ <dimen name="detail_radio_group_padding_left">16dp</dimen>
+ <dimen name="detail_radio_group_padding">8dp</dimen>
+
+ <!-- Themes: radius of the corners of the notification dropshadow
+ See also: notification_material_rounded_rect_radius
+ -->
+ <dimen name="notification_material_shadow_rounded_rect_radius">0dp</dimen>
+
+ <dimen name="zen_mode_panel_radius">@dimen/notification_material_rounded_rect_radius</dimen>
+
+ <dimen name="status_bar_expanded_header_elevation">4dp</dimen>
+
+ <dimen name="volume_panel_z">4dp</dimen>
+
+ <!-- Side padding for the status bar header -->
+ <dimen name="notification_header_side_padding">@dimen/notification_side_padding</dimen>
+
+ <!-- Side padding for the Quick Settings panel -->
+ <dimen name="qs_panel_side_padding">@dimen/notification_side_padding</dimen>
+
+ <!-- Padding end for weather text -->
+ <dimen name="status_bar_weather_padding_end">16dp</dimen>
+
+ <!-- height of the qs page indicator -->
+ <dimen name="qs_panel_page_indicator_height">8dp</dimen>
+
+ <dimen name="lockscreen_icon_side_padding">10dp</dimen>
+ <dimen name="lockscreen_icon_size">35dp</dimen>
+ <dimen name="phone_side_padding">10dp</dimen>
+ <dimen name="phone_bottom_padding">40dp</dimen>
+ <dimen name="phone_width">320dp</dimen>
+ <dimen name="phone_height">420dp</dimen>
+
+ <dimen name="qs_detail_item_height_twoline">72dp</dimen>
+
+ <dimen name="detail_exterior_padding">8dp</dimen>
+
+ <!-- Size of unlock FAB used when showing external keyguard views -->
+ <dimen name="unlock_fab_size">48dp</dimen>
+
+</resources>
diff --git a/packages/SystemUI/res/values/cm_strings.xml b/packages/SystemUI/res/values/cm_strings.xml
new file mode 100644
index 0000000..200a236
--- /dev/null
+++ b/packages/SystemUI/res/values/cm_strings.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012-2015 The CyanogenMod 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Content description of the data connection type HSPA+ for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_connection_hspap">HSPA+</string>
+ <!-- Content description of the data connection type 4G+ for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+
+ <!-- Weather string format in expanded statusbar header -->
+ <string name="status_bar_expanded_header_weather_format"><xliff:g id="temp">%1$s</xliff:g> - <xliff:g id="condition">%2$s</xliff:g></string>
+
+ <!-- Text to use when the number in a notification info is too large
+ (greater than status_bar_notification_info_maxnum, defined in
+ values/config.xml) and must be truncated.
+ [CHAR LIMIT=4] -->
+ <string name="status_bar_notification_info_overflow" translatable="false">\u221E</string>
+
+ <!-- Strings for lockscreen shortcut hints -->
+ <string name="left_shortcut_hint">Swipe right for %1$s</string>
+ <string name="right_shortcut_hint">Swipe left for %1$s</string>
+
+ <string name="lockscreen_message">Tap an icon on the left or right to reassign a lock screen shortcut.</string>
+ <string name="lockscreen_default_target">Default</string>
+ <string name="select_application">Select application</string>
+ <string name="lockscreen_choose_action_title">Choose action</string>
+ <string name="lockscreen_none_target">None</string>
+
+ <!-- Dialog title for navigation bar button selection -->
+ <string name="navbar_dialog_title">Choose action to assign</string>
+ <string name="navbar_home_button">Home button</string>
+ <string name="navbar_recent_button">Recent button</string>
+ <string name="navbar_search_button">Search button</string>
+ <string name="navbar_back_button">Back button</string>
+ <string name="navbar_empty_button">Empty button</string>
+ <string name="navbar_menu_conditional_button">Menu (autoHide) button</string>
+ <string name="navbar_menu_always_button">Menu (alwaysShow) button</string>
+ <string name="navbar_menu_big_button">Menu button</string>
+ <string name="accessibility_dpad_left">Cursor left</string>
+ <string name="accessibility_dpad_right">Cursor right</string>
+
+ <!-- Development shortcuts -->
+ <!-- Title shown in recents popup for wiping application's data -->
+ <string name="advanced_dev_option_wipe_app">Wipe app data</string>
+ <!-- Title shown in recents popup for force stopping the application -->
+ <string name="advanced_dev_option_force_stop">Force stop</string>
+ <!-- Title shown in recents popup for uninstalling the application -->
+ <string name="advanced_dev_option_uninstall">Uninstall</string>
+
+ <!-- Content description of the light brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_notification_brightness">Light brightness</string>
+
+ <!-- Content description of the profiles tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_profiles_off">Profiles off.</string>
+ <!-- Content description of the profiles tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_profiles">Profile: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+
+ <!-- Announcement made when the profiles tile changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_profiles_changed_off">Profiles turned off.</string>
+ <!-- Announcement made when the profiles tile changes (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_profiles_changed">Profile changed to <xliff:g id="profile" example="Default">%s</xliff:g>.</string>
+
+ <string name="quick_settings_compass_value" translatable="false"><xliff:g id="degrees">%1$.0f</xliff:g>\u00b0 <xliff:g id="direction">%2$s</xliff:g></string>
+ <string name="quick_settings_compass_init">Initializing\u2026</string>
+
+ <!-- Lights settings, LED notification -->
+ <string name="led_notification_title">Light settings</string>
+ <string name="led_notification_text">LED light enabled by settings</string>
+
+ <string name="qs_tile_edit_header_instruction">Press and hold tiles to rearrange</string>
+ <string name="quick_settings_edit_label">Edit tiles</string>
+ <string name="quick_settings_cannot_delete_edit_tile">Cannot delete the Edit tile</string>
+ <string name="qs_tiles_reset_confirmation">Reset quick settings tiles to default configuration?</string>
+ <string name="quick_settings_tile_reset_to_default">Reset to default layout</string>
+ <string name="quick_settings_title_header">Header</string>
+ <string name="quick_settings_title_tiles">Tiles</string>
+ <string name="quick_settings_title_show_weather">Show weather</string>
+ <string name="quick_settings_title_show_brightness_slider">Show brightness slider</string>
+ <string name="quick_settings_title_enlarge_first_row">Enlarge first row</string>
+
+ <!-- Screen pinning dialog description (for devices without navbar) -->
+ <string name="screen_pinning_description_no_navbar">This keeps it in view until you unpin. Touch and hold the Back button to unpin.</string>
+
+ <string name="quick_settings_custom_tile_detail_title">Custom tile</string>
+ <string name="quick_settings_remove">Remove tile</string>
+ <string name="quick_settings_network_adb_label">ADB over network</string>
+ <string name="quick_settings_compass_label">Compass</string>
+ <string name="quick_settings_nfc_label">NFC</string>
+ <string name="quick_settings_profiles">System profiles</string>
+ <string name="quick_settings_profiles_off">Profiles disabled</string>
+ <string name="quick_settings_heads_up_label">Heads up</string>
+ <string name="quick_settings_battery_saver_label">Battery saver</string>
+ <string name="quick_settings_caffeine_label">Caffeine</string>
+
+ <!-- Content description of the sync tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_sync_off">Sync off.</string>
+ <!-- Content description of the sync tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_sync_on">Sync on.</string>
+
+ <!-- Announcement made when sync changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_sync_changed_off">Sync turned off.</string>
+ <!-- Announcement made when sync changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_sync_changed_on">Sync turned on.</string>
+ <string name="quick_settings_sync_label">Sync</string>
+ <string name="quick_settings_volume_panel_label">Volume panel</string>
+ <string name="quick_settings_usb_tether_label">USB tethering</string>
+ <string name="quick_settings_screen_timeout_detail_title">Screen timeout</string>
+ <string name="quick_settings_lockscreen_label">Lock screen</string>
+ <string name="quick_settings_ambient_display_label">Ambient display</string>
+ <string name="quick_settings_lockscreen_label_enforced">Lock screen enforced</string>
+ <string name="quick_settings_lockscreen_label_locked_by_profile">Disabled by profile</string>
+ <!-- Content description of the screen timeout tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_screen_timeout">Screen timeout: <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+
+ <!-- Announcement made when the screen timeout tile changes (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_screen_timeout_changed">Screen timeout changed to <xliff:g id="timeout" example="30 seconds">%s</xliff:g>.</string>
+ <string name="qs_tile_performance">Battery mode</string>
+
+ <!-- Content description of the battery mode tile in quick settings when on, power save mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_pwrsv">Battery mode: power save mode.</string>
+ <!-- Content description of the battery mode tile in quick settings when on, balanced mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_bal">Battery mode: balanced mode.</string>
+ <!-- Content description of the battery mode tile in quick settings when on, performance mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_perf">Battery mode: performance mode.</string>
+ <!-- Content description of the battery mode tile in quick settings when on, efficiency mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_bias_power">Battery mode: efficiency mode.</string>
+ <!-- Content description of the battery mode tile in quick settings when on, quick mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_bias_perf">Battery mode: quick mode.</string>
+
+ <!-- Announcement made when the battery mode tile changes to power save (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_changed_pwrsv">Battery mode changed to power save mode.</string>
+ <!-- Announcement made when the battery mode tile changes to balanced (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_changed_bal">Battery mode changed to balanced mode.</string>
+ <!-- Announcement made when the battery mode tile changes to performance (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_changed_perf">Battery mode changed to performance mode.</string>
+ <!-- Announcement made when the battery mode tile changes to efficiency (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_power">Battery mode changed to efficiency mode.</string>
+ <!-- Announcement made when the battery mode tile changes to quick (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_perf_profile_changed_bias_perf">Battery mode changed to quick mode.</string>
+ <string name="quick_settings_performance_profile_detail_title">Battery mode</string>
+
+ <!-- Content description of the lock screen tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_lock_screen_off">Lock screen off.</string>
+ <!-- Content description of the lock screen tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_lock_screen_on">Lock screen on.</string>
+
+ <!-- Announcement made when lock screen changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_lock_screen_changed_off">Lock screen turned off.</string>
+ <!-- Announcement made when lock screen changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_lock_screen_changed_on">Lock screen turned on.</string>
+
+ <!-- Content description of the ambient display tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_ambient_display_off">Ambient display off.</string>
+ <!-- Content description of the ambient display tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_ambient_display_on">Ambient display on.</string>
+
+ <!-- Announcement made when ambient display changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_ambient_display_changed_off">Ambient display turned off.</string>
+ <!-- Announcement made when ambient display changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display turned on.</string>
+
+ <!-- Content description of the heads up tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_heads_up_off">Heads up off.</string>
+ <!-- Content description of the heads up tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_heads_up_on">Heads up on.</string>
+
+ <!-- Announcement made when heads up changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_heads_up_changed_off">Heads up turned off.</string>
+ <!-- Announcement made when heads up changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_heads_up_changed_on">Heads up turned on.</string>
+
+ <!-- Content description of the caffeine tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_caffeine_off">Caffeine off.</string>
+ <!-- Content description of the caffeine tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_caffeine_on">Caffeine on.</string>
+
+ <!-- Content description of the battery saver tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_battery_saver_off">Battery saver off.</string>
+ <!-- Content description of the battery saver tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_battery_saver_on">Battery saver on.</string>
+
+ <!-- Announcement made when battery saver changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_battery_saver_changed_off">Battery saver turned off.</string>
+ <!-- Announcement made when battery saver changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_battery_saver_changed_on">Battery saver turned on.</string>
+
+ <!-- Dynamic tiles -->
+ <string name="quick_settings_dynamic_tile_detail_title">Dynamic tile</string>
+ <string name="dynamic_qs_tile_next_alarm_label">Next alarm</string>
+ <string name="dynamic_qs_tile_ime_selector_label">IME selector</string>
+ <string name="dynamic_qs_tile_su_label">Root access</string>
+ <string name="dynamic_qs_tile_adb_label" translatable="false">ADB</string>
+
+ <!-- LiveDisplay strings -->
+ <string name="live_display_title" translatable="false">LiveDisplay</string>
+ <string name="accessibility_quick_settings_live_display_off">LiveDisplay off.</string>
+ <string name="accessibility_quick_settings_live_display_auto">LiveDisplay: auto mode.</string>
+ <string name="accessibility_quick_settings_live_display_day">LiveDisplay: day mode.</string>
+ <string name="accessibility_quick_settings_live_display_night">LiveDisplay: night mode.</string>
+ <string name="accessibility_quick_settings_live_display_outdoor">LiveDisplay: outdoor mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_off">LiveDisplay turned off.</string>
+ <string name="accessibility_quick_settings_live_display_changed_auto">LiveDisplay changed to auto mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_day">LiveDisplay changed to day mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_night">LiveDisplay changed to night mode.</string>
+ <string name="accessibility_quick_settings_live_display_changed_outdoor">LiveDisplay changed to outdoor mode.</string>
+ <string name="quick_settings_title_advanced_location">Tri-state location</string>
+
+ <!-- Content description of the location tile in quick settings when on, battery saving mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_battery_saving">Location reporting: battery saving mode.</string>
+ <!-- Content description of the location tile in quick settings when on, sensors only mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_gps_only">Location reporting: sensors only mode.</string>
+ <!-- Content description of the location tile in quick settings when on, high accuracy mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_high_accuracy">Location reporting: high accuracy mode.</string>
+
+ <!-- QuickSettings: Location detail panel title [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_location_detail_title">Location mode</string>
+ <!-- QuickSettings: Location (On, low-power) [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_location_battery_saving_label">Battery saving</string>
+ <!-- QuickSettings: Location (On, gps-only) [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_location_gps_only_label">Device only</string>
+ <!-- QuickSettings: Location (On, high-accuracy) [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_location_high_accuracy_label">High accuracy</string>
+
+ <!-- Announcement made when the location tile changes to battery saving (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_changed_battery_saving">Location reporting changed to battery saving mode.</string>
+ <!-- Announcement made when the location tile changes to sensors only (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_changed_gps_only">Location reporting changed to sensors only mode.</string>
+ <!-- Announcement made when the location tile changes to high accuracy (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_changed_high_accuracy">Location reporting changed to high accuracy mode.</string>
+
+ <string name="quick_settings_tiles_category_system">System tiles</string>
+ <!-- detail header when adding a tile -->
+ <string name="quick_settings_tiles_add_tiles">Add a tile</string>
+
+ <!-- Hotspot dialog message -->
+ <string name="hotspot_apm_message">Unable to connect to cellular networks while Airplane mode is enabled. Disable Airplane mode and try again.</string>
+
+ <!-- Notification which notifies user flashlight is enabled -->
+ <string name="quick_settings_tile_flashlight_not_title">Flashlight is on</string>
+ <string name="quick_settings_tile_flashlight_not_summary">Tap to turn off</string>
+
+ <!-- Wi-Fi hotspot label when enabled -->
+ <plurals name="wifi_hotspot_connected_clients_label">
+ <item quantity="one">%1$d client</item>
+ <item quantity="other">%1$d clients</item>
+ </plurals>
+
+ <!-- CellularTile data sim not configured state string -->
+ <string name="data_sim_not_configured">No data SIM</string>
+
+ <!-- Content description of the dock battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_dock_battery_level">Dock battery <xliff:g id="number">%d</xliff:g> percent.</string>
+</resources>
diff --git a/packages/SystemUI/res/values/cm_styles.xml b/packages/SystemUI/res/values/cm_styles.xml
new file mode 100644
index 0000000..8caa89d
--- /dev/null
+++ b/packages/SystemUI/res/values/cm_styles.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<resources>
+
+ <style name="SettingRow">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">48dp</item>
+ <item name="android:paddingLeft">16dp</item>
+ <item name="android:paddingRight">16dp</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ <item name="android:clickable">true</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Expanded.WeatherTemp">
+ <item name="android:textSize">12sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">@color/status_bar_temperature_text_color</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Expanded.WeatherLocation">
+ <item name="android:textSize">12sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">@color/status_bar_temperature_location_text_color</item>
+ </style>
+
+ <style name="TextAppearance.QS.DetailItemSub">
+ <item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
+ </style>
+
+</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0dcbe88..f116f05 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -17,7 +17,7 @@
*/
-->
<resources>
- <drawable name="notification_number_text_color">#ffffffff</drawable>
+ <drawable name="notification_number_text_color">#ff000000</drawable>
<drawable name="ticker_background_color">#ff1d1d1d</drawable>
<drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
<color name="system_bar_background_opaque">#ff000000</color>
@@ -35,6 +35,7 @@
<color name="batterymeter_bolt_color">#FFFFFFFF</color>
<color name="qs_batterymeter_frame_color">#FF404040</color>
<color name="system_primary_color">#ff263238</color><!-- blue grey 900 -->
+ <color name="system_primary_color_translucent">#90aaaaaa</color><!-- blue grey 900 -->
<color name="system_secondary_color">#ff384248</color>
<color name="system_accent_color">#ff80CBC4</color><!-- deep teal 200 -->
<color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5d06768..cdbe2fd 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -117,11 +117,6 @@
<!-- The number of columns that the top level tiles span in the QuickSettings -->
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
- <!-- The default tiles to display in QuickSettings -->
- <string name="quick_settings_tiles_default" translatable="false">
- wifi,bt,inversion,dnd,cell,airplane,rotation,flashlight,location,cast,hotspot
- </string>
-
<!-- The tiles to display in QuickSettings -->
<string name="quick_settings_tiles" translatable="false">default</string>
@@ -138,6 +133,9 @@
<!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
<bool name="config_show4GForLTE">true</bool>
+ <!-- Whether or not we also show rsrp level for LTE. -->
+ <bool name="config_showRsrpSignalLevelforLTE">false</bool>
+
<!-- milliseconds before the heads up notification auto-dismisses. -->
<integer name="heads_up_notification_decay">5000</integer>
@@ -239,6 +237,9 @@
<!-- Doze: check proximity sensor before pulsing? -->
<bool name="doze_proximity_check_before_pulse">true</bool>
+ <!-- Doze: check proximity sensor before pulsing from intent? -->
+ <bool name="doze_proximity_check_before_pulse_intent">false</bool>
+
<!-- Doze: should notifications be used as a pulse signal? -->
<bool name="doze_pulse_on_notifications">true</bool>
@@ -260,6 +261,12 @@
<!-- Doze: pulse parameter - how long does it take to fade in after a pickup? -->
<integer name="doze_pulse_duration_in_pickup">300</integer>
+ <!-- Doze: pulse parameter - how long does it take to fade in after an intent? -->
+ <integer name="doze_pulse_duration_in_intent">300</integer>
+
+ <!-- Doze: pulse parameter - delay to wait for the screen to wake up after an intent -->
+ <integer name="doze_pulse_delay_in_intent">200</integer>
+
<!-- Doze: pulse parameter - once faded in, how long does it stay visible? -->
<integer name="doze_pulse_duration_visible">3000</integer>
@@ -290,5 +297,8 @@
<!-- Duration of the expansion animation in the volume dialog -->
<item name="volume_expand_animation_duration" type="integer">300</item>
+ <!-- Allow Flashlight service to use wakelock -->
+ <bool name="flashlight_use_wakelock">false</bool>
+
</resources>
diff --git a/packages/SystemUI/res/values/vpi__attrs.xml b/packages/SystemUI/res/values/vpi__attrs.xml
new file mode 100644
index 0000000..911df54
--- /dev/null
+++ b/packages/SystemUI/res/values/vpi__attrs.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Jake Wharton
+ Copyright (C) 2011 Patrik Åkerfeldt
+
+ 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.
+-->
+
+<resources>
+ <attr name="centered" format="boolean" />
+ <attr name="selectedColor" format="color" />
+ <attr name="strokeWidth" format="dimension" />
+ <attr name="unselectedColor" format="color" />
+
+ <declare-styleable name="CirclePageIndicator">
+ <!-- Whether or not the indicators should be centered. -->
+ <attr name="centered" />
+ <!-- Color of the filled circle that represents the current page. -->
+ <attr name="indicatorFillColor" format="color" />
+ <!-- Color of the filled circles that represents pages. -->
+ <attr name="pageColor" format="color" />
+ <!-- Orientation of the indicator. -->
+ <attr name="android:orientation"/>
+ <!-- Radius of the circles. This is also the spacing between circles. -->
+ <attr name="radius" format="dimension" />
+ <!-- Whether or not the selected indicator snaps to the circles. -->
+ <attr name="snap" format="boolean" />
+ <!-- Color of the open circles. -->
+ <attr name="strokeColor" format="color" />
+ <!-- Width of the stroke used to draw the circles. -->
+ <attr name="strokeWidth" />
+ <!-- View background -->
+ <attr name="android:background"/>
+ </declare-styleable>
+</resources>
diff --git a/packages/SystemUI/res/values/vpi__defaults.xml b/packages/SystemUI/res/values/vpi__defaults.xml
new file mode 100644
index 0000000..7aabee4
--- /dev/null
+++ b/packages/SystemUI/res/values/vpi__defaults.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Jake Wharton
+
+ 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.
+-->
+
+<resources>
+ <bool name="default_circle_indicator_centered">true</bool>
+ <color name="default_circle_indicator_fill_color">#ffFFFFFF</color>
+ <color name="default_circle_indicator_page_color">#ffcccccc</color>
+ <integer name="default_circle_indicator_orientation">0</integer>
+ <dimen name="default_circle_indicator_radius">3dp</dimen>
+ <bool name="default_circle_indicator_snap">false</bool>
+ <color name="default_circle_indicator_stroke_color">#ffcccccc</color>
+ <dimen name="default_circle_indicator_stroke_width">0dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 3a41c3c..2d70faa 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -18,59 +18,8 @@
android:title="@string/system_ui_tuner">
<Preference
- android:key="qs_tuner"
- android:title="@string/quick_settings" />
-
- <PreferenceScreen
- android:title="@string/status_bar" >
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="cast"
- android:title="@string/quick_settings_cast_title" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="hotspot"
- android:title="@string/quick_settings_hotspot_label" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="bluetooth"
- android:title="@string/quick_settings_bluetooth_label" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="zen"
- android:title="@string/quick_settings_dnd_label" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="alarm_clock"
- android:title="@string/status_bar_alarm" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="managed_profile"
- android:title="@string/status_bar_work" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="wifi"
- android:title="@string/quick_settings_wifi_label" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="ethernet"
- android:title="@string/status_bar_ethernet" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="mobile"
- android:title="@string/quick_settings_cellular_detail_title" />
-
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="airplane"
- android:title="@string/status_bar_airplane" />
-
- </PreferenceScreen>
-
- <SwitchPreference
- android:key="battery_pct"
- android:title="@string/show_battery_percentage"
- android:summary="@string/show_battery_percentage_summary"
- android:persistent="false" />
+ android:key="statusbar_icon_blacklist"
+ android:title="@string/status_bar" />
<Preference
android:key="demo_mode"
diff --git a/packages/SystemUI/res/xml/tuner_statusbar_icons.xml b/packages/SystemUI/res/xml/tuner_statusbar_icons.xml
new file mode 100644
index 0000000..863c8b0
--- /dev/null
+++ b/packages/SystemUI/res/xml/tuner_statusbar_icons.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The CyanogenMod 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/status_bar">
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="cast"
+ android:title="@string/quick_settings_cast_title"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="hotspot"
+ android:title="@string/quick_settings_hotspot_label"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="bluetooth"
+ android:title="@string/quick_settings_bluetooth_label"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="zen"
+ android:title="@string/quick_settings_dnd_label"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="alarm_clock"
+ android:title="@string/status_bar_alarm"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="managed_profile"
+ android:title="@string/status_bar_work"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="wifi"
+ android:title="@string/quick_settings_wifi_label"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="ethernet"
+ android:title="@string/status_bar_ethernet"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="mobile"
+ android:title="@string/quick_settings_cellular_detail_title"/>
+
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="airplane"
+ android:title="@string/status_bar_airplane"/>
+
+</PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java
new file mode 100644
index 0000000..247e965
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryStateRegistar;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.TextView;
+
+import java.text.NumberFormat;
+
+public class BatteryLevelTextView extends TextView implements
+ BatteryController.BatteryStateChangeCallback{
+
+ private BatteryStateRegistar mBatteryStateRegistar;
+ private boolean mBatteryPresent;
+
+ private boolean mBatteryCharging;
+ private boolean mForceShow;
+ private boolean mAttached;
+ private int mRequestedVisibility;
+ private int mStyle;
+ private int mPercentMode;
+
+ public BatteryLevelTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ // setBatteryStateRegistar (if called) will made the view visible and ready to be hidden
+ // if the view shouldn't be displayed. Otherwise this view should be hidden from start.
+ mRequestedVisibility = GONE;
+ }
+
+ public void setForceShown(boolean forceShow) {
+ mForceShow = forceShow;
+ updateVisibility();
+ }
+
+ public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) {
+ mRequestedVisibility = VISIBLE;
+ mBatteryStateRegistar = batteryStateRegistar;
+ if (mAttached) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
+ }
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ mRequestedVisibility = visibility;
+ updateVisibility();
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Respect font size setting.
+ setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ getResources().getDimensionPixelSize(R.dimen.battery_level_text_size));
+ }
+
+ @Override
+ public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn,
+ boolean charging) {
+ String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
+ setText(percentage);
+ if (mBatteryPresent != present || mBatteryCharging != charging) {
+ mBatteryPresent = present;
+ mBatteryCharging = charging;
+ updateVisibility();
+ }
+ }
+
+ @Override
+ public void onPowerSaveChanged() {
+ // Not used
+ }
+
+ @Override
+ public void onBatteryStyleChanged(int style, int percentMode) {
+ mStyle = style;
+ mPercentMode = percentMode;
+ updateVisibility();
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
+ }
+
+ mAttached = true;
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mAttached = false;
+
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.removeStateChangedCallback(this);
+ }
+ }
+
+ private void updateVisibility() {
+ boolean showNextPercent = mBatteryPresent && (
+ mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE
+ || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE));
+ if (mStyle == BatteryController.STYLE_GONE) {
+ showNextPercent = false;
+ } else if (mStyle == BatteryController.STYLE_TEXT) {
+ showNextPercent = true;
+ }
+
+ if (mBatteryStateRegistar != null && (showNextPercent || mForceShow)) {
+ super.setVisibility(mRequestedVisibility);
+ } else {
+ super.setVisibility(GONE);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 95b58e5..e606156 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-14 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.
@@ -16,6 +16,9 @@
package com.android.systemui;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryStateRegistar;
+
import android.animation.ArgbEvaluator;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -23,30 +26,22 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
-import android.net.Uri;
import android.os.BatteryManager;
import android.os.Bundle;
-import android.os.Handler;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
-import com.android.systemui.statusbar.policy.BatteryController;
-
public class BatteryMeterView extends View implements DemoMode,
BatteryController.BatteryStateChangeCallback {
public static final String TAG = BatteryMeterView.class.getSimpleName();
public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
- public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent";
-
- private static final boolean SINGLE_DIGIT_PERCENT = false;
private static final int FULL = 96;
@@ -54,30 +49,32 @@ public class BatteryMeterView extends View implements DemoMode,
private final int[] mColors;
- private boolean mShowPercent;
+ protected boolean mShowPercent = true;
private float mButtonHeightFraction;
private float mSubpixelSmoothingLeft;
private float mSubpixelSmoothingRight;
- private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
- private float mTextHeight, mWarningTextHeight;
- private int mIconTint = Color.WHITE;
+
+ public enum BatteryMeterMode {
+ BATTERY_METER_GONE,
+ BATTERY_METER_ICON_PORTRAIT,
+ BATTERY_METER_ICON_LANDSCAPE,
+ BATTERY_METER_CIRCLE,
+ BATTERY_METER_TEXT
+ }
private int mHeight;
private int mWidth;
private String mWarningString;
private final int mCriticalLevel;
- private int mChargeColor;
- private final float[] mBoltPoints;
- private final Path mBoltPath = new Path();
+ private final int mFrameColor;
- private final RectF mFrame = new RectF();
- private final RectF mButtonFrame = new RectF();
- private final RectF mBoltFrame = new RectF();
+ private boolean mAnimationsEnabled;
private final Path mShapePath = new Path();
private final Path mClipPath = new Path();
private final Path mTextPath = new Path();
+ private BatteryStateRegistar mBatteryStateRegistar;
private BatteryController mBatteryController;
private boolean mPowerSaveEnabled;
@@ -87,8 +84,132 @@ public class BatteryMeterView extends View implements DemoMode,
private int mLightModeBackgroundColor;
private int mLightModeFillColor;
- private BatteryTracker mTracker = new BatteryTracker();
- private final SettingObserver mSettingObserver = new SettingObserver();
+ protected BatteryMeterMode mMeterMode = null;
+
+ protected boolean mAttached;
+
+ private boolean mDemoMode;
+ protected BatteryTracker mDemoTracker = new BatteryTracker();
+ protected BatteryTracker mTracker = new BatteryTracker();
+ private BatteryMeterDrawable mBatteryMeterDrawable;
+ private int mIconTint = Color.WHITE;
+
+ protected class BatteryTracker extends BroadcastReceiver {
+ public static final int UNKNOWN_LEVEL = -1;
+
+ // current battery status
+ boolean present = true;
+ int level = UNKNOWN_LEVEL;
+ String percentStr;
+ int plugType;
+ boolean plugged;
+ int health;
+ int status;
+ String technology;
+ int voltage;
+ int temperature;
+ boolean testmode = false;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
+
+ level = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
+
+ present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
+ plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+ plugged = plugType != 0;
+ health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH,
+ BatteryManager.BATTERY_HEALTH_UNKNOWN);
+ status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
+ voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
+ temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
+ setContentDescription(
+ context.getString(R.string.accessibility_battery_level, level));
+ if (mBatteryMeterDrawable != null) {
+ setVisibility(View.VISIBLE);
+ invalidate();
+ }
+ } else if (action.equals(ACTION_LEVEL_TEST)) {
+ testmode = true;
+ post(new Runnable() {
+ int curLevel = 0;
+ int incr = 1;
+ int saveLevel = level;
+ int savePlugged = plugType;
+ Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ @Override
+ public void run() {
+ if (curLevel < 0) {
+ testmode = false;
+ dummy.putExtra("level", saveLevel);
+ dummy.putExtra("plugged", savePlugged);
+ dummy.putExtra("testmode", false);
+ } else {
+ dummy.putExtra("level", curLevel);
+ dummy.putExtra("plugged", incr > 0
+ ? BatteryManager.BATTERY_PLUGGED_AC : 0);
+ dummy.putExtra("testmode", true);
+ }
+ getContext().sendBroadcast(dummy);
+
+ if (!testmode) return;
+
+ curLevel += incr;
+ if (curLevel == 100) {
+ incr *= -1;
+ }
+ postDelayed(this, 200);
+ }
+ });
+ }
+ }
+
+ protected boolean shouldIndicateCharging() {
+ if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+ return true;
+ }
+ if (plugged) {
+ return status == BatteryManager.BATTERY_STATUS_FULL;
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ filter.addAction(ACTION_LEVEL_TEST);
+ final Intent sticky = getContext().registerReceiver(mTracker, filter);
+ if (sticky != null) {
+ // preload the battery level
+ mTracker.onReceive(getContext(), sticky);
+ }
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
+ }
+ mAttached = true;
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ mAttached = false;
+ getContext().unregisterReceiver(mTracker);
+ if (mBatteryStateRegistar != null) {
+ mBatteryStateRegistar.removeStateChangedCallback(this);
+ }
+ }
public BatteryMeterView(Context context) {
this(context, null, 0);
@@ -104,8 +225,8 @@ public class BatteryMeterView extends View implements DemoMode,
final Resources res = context.getResources();
TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView,
defStyle, 0);
- final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
- context.getColor(R.color.batterymeter_frame_color));
+ mFrameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
+ res.getColor(R.color.batterymeter_frame_color));
TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
@@ -118,9 +239,8 @@ public class BatteryMeterView extends View implements DemoMode,
levels.recycle();
colors.recycle();
atts.recycle();
- updateShowPercent();
mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
- mCriticalLevel = mContext.getResources().getInteger(
+ mCriticalLevel = getContext().getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mButtonHeightFraction = context.getResources().getFraction(
R.fraction.battery_button_height_fraction, 1, 1);
@@ -129,66 +249,53 @@ public class BatteryMeterView extends View implements DemoMode,
mSubpixelSmoothingRight = context.getResources().getFraction(
R.fraction.battery_subpixel_smoothing_right, 1, 1);
- mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mFramePaint.setColor(frameColor);
- mFramePaint.setDither(true);
- mFramePaint.setStrokeWidth(0);
- mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
-
- mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mBatteryPaint.setDither(true);
- mBatteryPaint.setStrokeWidth(0);
- mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-
- mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
- mTextPaint.setTypeface(font);
- mTextPaint.setTextAlign(Paint.Align.CENTER);
-
- mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mWarningTextPaint.setColor(mColors[1]);
- font = Typeface.create("sans-serif", Typeface.BOLD);
- mWarningTextPaint.setTypeface(font);
- mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
-
- mChargeColor = context.getColor(R.color.batterymeter_charge_color);
-
- mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color));
- mBoltPoints = loadBoltPoints(res);
-
mDarkModeBackgroundColor =
context.getColor(R.color.dark_mode_icon_color_dual_tone_background);
mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill);
mLightModeBackgroundColor =
context.getColor(R.color.light_mode_icon_color_dual_tone_background);
mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill);
- }
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
+ setAnimationsEnabled(true);
+ }
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(ACTION_LEVEL_TEST);
- final Intent sticky = getContext().registerReceiver(mTracker, filter);
- if (sticky != null) {
- // preload the battery level
- mTracker.onReceive(getContext(), sticky);
+ protected BatteryMeterDrawable createBatteryMeterDrawable(BatteryMeterMode mode) {
+ Resources res = mContext.getResources();
+ switch (mode) {
+ case BATTERY_METER_CIRCLE:
+ return new CircleBatteryMeterDrawable(res);
+ case BATTERY_METER_ICON_LANDSCAPE:
+ return new NormalBatteryMeterDrawable(res, true);
+ case BATTERY_METER_TEXT:
+ case BATTERY_METER_GONE:
+ return null;
+ default:
+ return new NormalBatteryMeterDrawable(res, false);
}
- mBatteryController.addStateChangedCallback(this);
- getContext().getContentResolver().registerContentObserver(
- Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
}
@Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (mMeterMode == BatteryMeterMode.BATTERY_METER_CIRCLE) {
+ height += (CircleBatteryMeterDrawable.STROKE_WITH / 3);
+ width = height;
+ } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_TEXT) {
+ onSizeChanged(width, height, 0, 0); // Force a size changed event
+ } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) {
+ width = (int)(height * 1.2f);
+ }
- getContext().unregisterReceiver(mTracker);
- mBatteryController.removeStateChangedCallback(this);
- getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
+ setMeasuredDimension(width, height);
+ }
+
+ public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) {
+ mBatteryStateRegistar = batteryStateRegistar;
+ if (!mAttached) {
+ mBatteryStateRegistar.addStateChangedCallback(this);
+ }
}
public void setBatteryController(BatteryController batteryController) {
@@ -197,7 +304,8 @@ public class BatteryMeterView extends View implements DemoMode,
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn,
+ boolean charging) {
// TODO: Use this callback instead of own broadcast receiver.
}
@@ -207,35 +315,85 @@ public class BatteryMeterView extends View implements DemoMode,
invalidate();
}
- private static float[] loadBoltPoints(Resources res) {
- final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
- int maxX = 0, maxY = 0;
- for (int i = 0; i < pts.length; i += 2) {
- maxX = Math.max(maxX, pts[i]);
- maxY = Math.max(maxY, pts[i + 1]);
+ public void setAnimationsEnabled(boolean enabled) {
+ if (mAnimationsEnabled != enabled) {
+ mAnimationsEnabled = enabled;
+ setLayerType(mAnimationsEnabled ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE, null);
+ invalidate();
}
- final float[] ptsF = new float[pts.length];
- for (int i = 0; i < pts.length; i += 2) {
- ptsF[i] = (float)pts[i] / maxX;
- ptsF[i + 1] = (float)pts[i + 1] / maxY;
+ }
+
+ @Override
+ public void onBatteryStyleChanged(int style, int percentMode) {
+ boolean showInsidePercent = percentMode == BatteryController.PERCENTAGE_MODE_INSIDE;
+ BatteryMeterMode meterMode = BatteryMeterMode.BATTERY_METER_ICON_PORTRAIT;
+
+ switch (style) {
+ case BatteryController.STYLE_CIRCLE:
+ meterMode = BatteryMeterMode.BATTERY_METER_CIRCLE;
+ break;
+ case BatteryController.STYLE_GONE:
+ meterMode = BatteryMeterMode.BATTERY_METER_GONE;
+ showInsidePercent = false;
+ break;
+ case BatteryController.STYLE_ICON_LANDSCAPE:
+ meterMode = BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE;
+ break;
+ case BatteryController.STYLE_TEXT:
+ meterMode = BatteryMeterMode.BATTERY_METER_TEXT;
+ showInsidePercent = false;
+ break;
+ default:
+ break;
}
- return ptsF;
+
+ setMode(meterMode);
+ mShowPercent = showInsidePercent;
+ invalidate();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
mHeight = h;
mWidth = w;
- mWarningTextPaint.setTextSize(h * 0.75f);
- mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
+ if (mBatteryMeterDrawable != null) {
+ mBatteryMeterDrawable.onSizeChanged(w, h, oldw, oldh);
+ }
}
- private void updateShowPercent() {
- mShowPercent = 0 != Settings.System.getInt(getContext().getContentResolver(),
- SHOW_PERCENT_SETTING, 0);
+ public void setMode(BatteryMeterMode mode) {
+ if (mMeterMode == mode) {
+ return;
+ }
+
+ mMeterMode = mode;
+ BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
+ if (mode == BatteryMeterMode.BATTERY_METER_GONE ||
+ mode == BatteryMeterMode.BATTERY_METER_TEXT) {
+ setVisibility(View.GONE);
+ mBatteryMeterDrawable = null;
+ } else {
+ if (mBatteryMeterDrawable != null) {
+ mBatteryMeterDrawable.onDispose();
+ }
+ mBatteryMeterDrawable = createBatteryMeterDrawable(mode);
+ if (mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_PORTRAIT ||
+ mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) {
+ ((NormalBatteryMeterDrawable)mBatteryMeterDrawable).loadBoltPoints(
+ mContext.getResources());
+ }
+ if (tracker.present) {
+ setVisibility(View.VISIBLE);
+ requestLayout();
+ invalidate();
+ } else {
+ setVisibility(View.GONE);
+ }
+ }
}
- private int getColorForLevel(int percent) {
+ public int getColorForLevel(int percent) {
// If we are in power save mode, always use the normal color.
if (mPowerSaveEnabled) {
@@ -259,13 +417,11 @@ public class BatteryMeterView extends View implements DemoMode,
}
public void setDarkIntensity(float darkIntensity) {
- int backgroundColor = getBackgroundColor(darkIntensity);
- int fillColor = getFillColor(darkIntensity);
- mIconTint = fillColor;
- mFramePaint.setColor(backgroundColor);
- mBoltPaint.setColor(fillColor);
- mChargeColor = fillColor;
- invalidate();
+ if (mBatteryMeterDrawable != null) {
+ int backgroundColor = getBackgroundColor(darkIntensity);
+ int fillColor = getFillColor(darkIntensity);
+ mBatteryMeterDrawable.setDarkIntensity(backgroundColor, fillColor);
+ }
}
private int getBackgroundColor(float darkIntensity) {
@@ -283,261 +439,584 @@ public class BatteryMeterView extends View implements DemoMode,
}
@Override
- public void draw(Canvas c) {
- BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
- final int level = tracker.level;
-
- if (level == BatteryTracker.UNKNOWN_LEVEL) return;
-
- float drawFrac = (float) level / 100f;
- final int pt = getPaddingTop();
- final int pl = getPaddingLeft();
- final int pr = getPaddingRight();
- final int pb = getPaddingBottom();
- final int height = mHeight - pt - pb;
- final int width = mWidth - pl - pr;
-
- final int buttonHeight = (int) (height * mButtonHeightFraction);
-
- mFrame.set(0, 0, width, height);
- mFrame.offset(pl, pt);
-
- // button-frame: area above the battery body
- mButtonFrame.set(
- mFrame.left + Math.round(width * 0.25f),
- mFrame.top,
- mFrame.right - Math.round(width * 0.25f),
- mFrame.top + buttonHeight);
-
- mButtonFrame.top += mSubpixelSmoothingLeft;
- mButtonFrame.left += mSubpixelSmoothingLeft;
- mButtonFrame.right -= mSubpixelSmoothingRight;
-
- // frame: battery body area
- mFrame.top += buttonHeight;
- mFrame.left += mSubpixelSmoothingLeft;
- mFrame.top += mSubpixelSmoothingLeft;
- mFrame.right -= mSubpixelSmoothingRight;
- mFrame.bottom -= mSubpixelSmoothingRight;
-
- // set the battery charging color
- mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level));
-
- if (level >= FULL) {
- drawFrac = 1f;
- } else if (level <= mCriticalLevel) {
- drawFrac = 0f;
- }
-
- final float levelTop = drawFrac == 1f ? mButtonFrame.top
- : (mFrame.top + (mFrame.height() * (1f - drawFrac)));
-
- // define the battery shape
- mShapePath.reset();
- mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
- mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
- mShapePath.lineTo(mButtonFrame.right, mFrame.top);
- mShapePath.lineTo(mFrame.right, mFrame.top);
- mShapePath.lineTo(mFrame.right, mFrame.bottom);
- mShapePath.lineTo(mFrame.left, mFrame.bottom);
- mShapePath.lineTo(mFrame.left, mFrame.top);
- mShapePath.lineTo(mButtonFrame.left, mFrame.top);
- mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
-
- if (tracker.plugged) {
- // define the bolt shape
- final float bl = mFrame.left + mFrame.width() / 4.5f;
- final float bt = mFrame.top + mFrame.height() / 6f;
- final float br = mFrame.right - mFrame.width() / 7f;
- final float bb = mFrame.bottom - mFrame.height() / 10f;
- if (mBoltFrame.left != bl || mBoltFrame.top != bt
- || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
- mBoltFrame.set(bl, bt, br, bb);
- mBoltPath.reset();
- mBoltPath.moveTo(
- mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
- mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
- for (int i = 2; i < mBoltPoints.length; i += 2) {
+ protected void onDraw(Canvas canvas) {
+ if (mBatteryMeterDrawable != null) {
+ BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
+ mBatteryMeterDrawable.onDraw(canvas, tracker);
+ }
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+ if (getVisibility() == View.VISIBLE) {
+ if (!mDemoMode && command.equals(COMMAND_ENTER)) {
+ mDemoMode = true;
+ mDemoTracker.level = mTracker.level;
+ mDemoTracker.plugged = mTracker.plugged;
+ } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
+ mDemoMode = false;
+ postInvalidate();
+ } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
+ String level = args.getString("level");
+ String plugged = args.getString("plugged");
+ if (level != null) {
+ mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100);
+ }
+ if (plugged != null) {
+ mDemoTracker.plugged = Boolean.parseBoolean(plugged);
+ }
+ postInvalidate();
+ }
+ }
+ }
+
+ protected interface BatteryMeterDrawable {
+ void onDraw(Canvas c, BatteryTracker tracker);
+ void onSizeChanged(int w, int h, int oldw, int oldh);
+ void onDispose();
+ void setDarkIntensity(int backgroundColor, int fillColor);
+ }
+
+ protected class NormalBatteryMeterDrawable implements BatteryMeterDrawable {
+ private static final boolean SINGLE_DIGIT_PERCENT = false;
+ private static final boolean SHOW_100_PERCENT = false;
+
+ private boolean mDisposed;
+
+ protected final boolean mHorizontal;
+
+ private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
+ private float mTextHeight, mWarningTextHeight;
+
+ private int mChargeColor;
+ private final float[] mBoltPoints;
+ private final Path mBoltPath = new Path();
+
+ private final RectF mFrame = new RectF();
+ private final RectF mButtonFrame = new RectF();
+ private final RectF mBoltFrame = new RectF();
+
+ public NormalBatteryMeterDrawable(Resources res, boolean horizontal) {
+ super();
+ mHorizontal = horizontal;
+ mDisposed = false;
+
+ mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mFramePaint.setColor(mFrameColor);
+ mFramePaint.setDither(true);
+ mFramePaint.setStrokeWidth(0);
+ mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBatteryPaint.setDither(true);
+ mBatteryPaint.setStrokeWidth(0);
+ mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
+ mTextPaint.setTypeface(font);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mWarningTextPaint.setColor(mColors[1]);
+ font = Typeface.create("sans-serif", Typeface.BOLD);
+ mWarningTextPaint.setTypeface(font);
+ mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mChargeColor = getResources().getColor(R.color.batterymeter_charge_color);
+
+ mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color));
+ mBoltPoints = loadBoltPoints(res);
+ }
+
+ @Override
+ public void onDraw(Canvas c, BatteryTracker tracker) {
+ if (mDisposed) return;
+
+ final int level = tracker.level;
+
+ if (level == BatteryTracker.UNKNOWN_LEVEL) return;
+
+ float drawFrac = (float) level / 100f;
+ final int pt = getPaddingTop() + (mHorizontal ? (int)(mHeight * 0.12f) : 0);
+ final int pl = getPaddingLeft();
+ final int pr = getPaddingRight();
+ final int pb = getPaddingBottom() + (mHorizontal ? (int)(mHeight * 0.08f) : 0);
+ final int height = mHeight - pt - pb;
+ final int width = mWidth - pl - pr;
+
+ final int buttonHeight = (int) ((mHorizontal ? width : height) * mButtonHeightFraction);
+
+ mFrame.set(0, 0, width, height);
+ mFrame.offset(pl, pt);
+
+ if (mHorizontal) {
+ mButtonFrame.set(
+ /*cover frame border of intersecting area*/
+ width - buttonHeight - mFrame.left,
+ mFrame.top + Math.round(height * 0.25f),
+ mFrame.right,
+ mFrame.bottom - Math.round(height * 0.25f));
+
+ mButtonFrame.top += mSubpixelSmoothingLeft;
+ mButtonFrame.bottom -= mSubpixelSmoothingRight;
+ mButtonFrame.right -= mSubpixelSmoothingRight;
+ } else {
+ // button-frame: area above the battery body
+ mButtonFrame.set(
+ mFrame.left + Math.round(width * 0.25f),
+ mFrame.top,
+ mFrame.right - Math.round(width * 0.25f),
+ mFrame.top + buttonHeight);
+
+ mButtonFrame.top += mSubpixelSmoothingLeft;
+ mButtonFrame.left += mSubpixelSmoothingLeft;
+ mButtonFrame.right -= mSubpixelSmoothingRight;
+ }
+
+ // frame: battery body area
+
+ if (mHorizontal) {
+ mFrame.right -= buttonHeight;
+ } else {
+ mFrame.top += buttonHeight;
+ }
+ mFrame.left += mSubpixelSmoothingLeft;
+ mFrame.top += mSubpixelSmoothingLeft;
+ mFrame.right -= mSubpixelSmoothingRight;
+ mFrame.bottom -= mSubpixelSmoothingRight;
+
+ // set the battery charging color
+ mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level));
+
+ if (level >= FULL) {
+ drawFrac = 1f;
+ } else if (level <= mCriticalLevel) {
+ drawFrac = 0f;
+ }
+
+ final float levelTop;
+
+ if (drawFrac == 1f) {
+ if (mHorizontal) {
+ levelTop = mButtonFrame.right;
+ } else {
+ levelTop = mButtonFrame.top;
+ }
+ } else {
+ if (mHorizontal) {
+ levelTop = (mFrame.right - (mFrame.width() * (1f - drawFrac)));
+ } else {
+ levelTop = (mFrame.top + (mFrame.height() * (1f - drawFrac)));
+ }
+ }
+
+ // define the battery shape
+ mShapePath.reset();
+ mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
+ if (mHorizontal) {
+ mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
+ mShapePath.lineTo(mButtonFrame.right, mButtonFrame.bottom);
+ mShapePath.lineTo(mButtonFrame.left, mButtonFrame.bottom);
+ mShapePath.lineTo(mFrame.right, mFrame.bottom);
+ mShapePath.lineTo(mFrame.left, mFrame.bottom);
+ mShapePath.lineTo(mFrame.left, mFrame.top);
+ mShapePath.lineTo(mButtonFrame.left, mFrame.top);
+ mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
+ } else {
+ mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
+ mShapePath.lineTo(mButtonFrame.right, mFrame.top);
+ mShapePath.lineTo(mFrame.right, mFrame.top);
+ mShapePath.lineTo(mFrame.right, mFrame.bottom);
+ mShapePath.lineTo(mFrame.left, mFrame.bottom);
+ mShapePath.lineTo(mFrame.left, mFrame.top);
+ mShapePath.lineTo(mButtonFrame.left, mFrame.top);
+ mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
+ }
+
+ if (tracker.plugged) {
+ // define the bolt shape
+ final float bl = mFrame.left + mFrame.width() / (mHorizontal ? 9f : 4.5f);
+ final float bt = mFrame.top + mFrame.height() / (mHorizontal ? 4.5f : 6f);
+ final float br = mFrame.right - mFrame.width() / (mHorizontal ? 6f : 7f);
+ final float bb = mFrame.bottom - mFrame.height() / (mHorizontal ? 7f : 10f);
+ if (mBoltFrame.left != bl || mBoltFrame.top != bt
+ || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
+ mBoltFrame.set(bl, bt, br, bb);
+ mBoltPath.reset();
+ mBoltPath.moveTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ for (int i = 2; i < mBoltPoints.length; i += 2) {
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
+ }
mBoltPath.lineTo(
- mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
- mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ }
+
+ float boltPct = mHorizontal ?
+ (mBoltFrame.left - levelTop) / (mBoltFrame.left - mBoltFrame.right) :
+ (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
+ boltPct = Math.min(Math.max(boltPct, 0), 1);
+ if (boltPct <= BOLT_LEVEL_THRESHOLD) {
+ // draw the bolt if opaque
+ c.drawPath(mBoltPath, mBoltPaint);
+ } else {
+ // otherwise cut the bolt out of the overall shape
+ mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
+ }
+ }
+
+ // compute percentage text
+ boolean pctOpaque = false;
+ float pctX = 0, pctY = 0;
+ String pctText = null;
+ if (!tracker.plugged && level > mCriticalLevel && mShowPercent) {
+ mTextPaint.setColor(getColorForLevel(level));
+ final float full = mHorizontal ? 0.60f : 0.45f;
+ final float nofull = mHorizontal ? 0.75f : 0.6f;
+ final float single = mHorizontal ? 0.86f : 0.75f;
+ mTextPaint.setTextSize(height *
+ (SINGLE_DIGIT_PERCENT ? single
+ : (tracker.level == 100 ? full : nofull)));
+ mTextHeight = -mTextPaint.getFontMetrics().ascent;
+ pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
+ pctX = mWidth * 0.5f;
+ pctY = (mHeight + mTextHeight) * 0.47f;
+ if (mHorizontal) {
+ pctOpaque = pctX > levelTop;
+ } else {
+ pctOpaque = levelTop > pctY;
+ }
+ if (!pctOpaque) {
+ mTextPath.reset();
+ mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath);
+ // cut the percentage text out of the overall shape
+ mShapePath.op(mTextPath, Path.Op.DIFFERENCE);
}
- mBoltPath.lineTo(
- mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
- mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
}
- float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
- boltPct = Math.min(Math.max(boltPct, 0), 1);
- if (boltPct <= BOLT_LEVEL_THRESHOLD) {
- // draw the bolt if opaque
- c.drawPath(mBoltPath, mBoltPaint);
+ // draw the battery shape background
+ c.drawPath(mShapePath, mFramePaint);
+
+ // draw the battery shape, clipped to charging level
+ if (mHorizontal) {
+ mFrame.right = levelTop;
} else {
- // otherwise cut the bolt out of the overall shape
- mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
+ mFrame.top = levelTop;
+ }
+ mClipPath.reset();
+ mClipPath.addRect(mFrame, Path.Direction.CCW);
+ mShapePath.op(mClipPath, Path.Op.INTERSECT);
+ c.drawPath(mShapePath, mBatteryPaint);
+
+ if (!tracker.plugged) {
+ if (level <= mCriticalLevel) {
+ // draw the warning text
+ final float x = mWidth * 0.5f;
+ final float y = (mHeight + mWarningTextHeight) * 0.48f;
+ c.drawText(mWarningString, x, y, mWarningTextPaint);
+ } else if (pctOpaque) {
+ // draw the percentage text
+ c.drawText(pctText, pctX, pctY, mTextPaint);
+ }
}
}
- // compute percentage text
- boolean pctOpaque = false;
- float pctX = 0, pctY = 0;
- String pctText = null;
- if (!tracker.plugged && level > mCriticalLevel && mShowPercent) {
- mTextPaint.setColor(getColorForLevel(level));
- mTextPaint.setTextSize(height *
- (SINGLE_DIGIT_PERCENT ? 0.75f
- : (tracker.level == 100 ? 0.38f : 0.5f)));
- mTextHeight = -mTextPaint.getFontMetrics().ascent;
- pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
- pctX = mWidth * 0.5f;
- pctY = (mHeight + mTextHeight) * 0.47f;
- pctOpaque = levelTop > pctY;
- if (!pctOpaque) {
- mTextPath.reset();
- mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath);
- // cut the percentage text out of the overall shape
- mShapePath.op(mTextPath, Path.Op.DIFFERENCE);
- }
+ @Override
+ public void onDispose() {
+ mDisposed = true;
+ }
+
+ @Override
+ public void setDarkIntensity(int backgroundColor, int fillColor) {
+ mIconTint = fillColor;
+ mFramePaint.setColor(backgroundColor);
+ mBoltPaint.setColor(fillColor);
+ mChargeColor = fillColor;
+ invalidate();
+ }
+
+ @Override
+ public void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mHeight = h;
+ mWidth = w;
+ mWarningTextPaint.setTextSize(h * 0.75f);
+ mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
}
- // draw the battery shape background
- c.drawPath(mShapePath, mFramePaint);
-
- // draw the battery shape, clipped to charging level
- mFrame.top = levelTop;
- mClipPath.reset();
- mClipPath.addRect(mFrame, Path.Direction.CCW);
- mShapePath.op(mClipPath, Path.Op.INTERSECT);
- c.drawPath(mShapePath, mBatteryPaint);
-
- if (!tracker.plugged) {
- if (level <= mCriticalLevel) {
- // draw the warning text
- final float x = mWidth * 0.5f;
- final float y = (mHeight + mWarningTextHeight) * 0.48f;
- c.drawText(mWarningString, x, y, mWarningTextPaint);
- } else if (pctOpaque) {
- // draw the percentage text
- c.drawText(pctText, pctX, pctY, mTextPaint);
+ private float[] loadBoltPoints(Resources res) {
+ final int[] pts = res.getIntArray(getBoltPointsArrayResource());
+ int maxX = 0, maxY = 0;
+ for (int i = 0; i < pts.length; i += 2) {
+ maxX = Math.max(maxX, pts[i]);
+ maxY = Math.max(maxY, pts[i + 1]);
+ }
+ final float[] ptsF = new float[pts.length];
+ for (int i = 0; i < pts.length; i += 2) {
+ ptsF[i] = (float)pts[i] / maxX;
+ ptsF[i + 1] = (float)pts[i + 1] / maxY;
}
+ return ptsF;
}
- }
- @Override
- public boolean hasOverlappingRendering() {
- return false;
+ protected int getBoltPointsArrayResource() {
+ return mHorizontal
+ ? R.array.batterymeter_inverted_bolt_points
+ : R.array.batterymeter_bolt_points;
+ }
}
- private boolean mDemoMode;
- private BatteryTracker mDemoTracker = new BatteryTracker();
+ protected class CircleBatteryMeterDrawable implements BatteryMeterDrawable {
+ private static final boolean SINGLE_DIGIT_PERCENT = false;
+ private static final boolean SHOW_100_PERCENT = false;
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- if (!mDemoMode && command.equals(COMMAND_ENTER)) {
- mDemoMode = true;
- mDemoTracker.level = mTracker.level;
- mDemoTracker.plugged = mTracker.plugged;
- } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
- mDemoMode = false;
- postInvalidate();
- } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
- String level = args.getString("level");
- String plugged = args.getString("plugged");
- if (level != null) {
- mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100);
- }
- if (plugged != null) {
- mDemoTracker.plugged = Boolean.parseBoolean(plugged);
- }
- postInvalidate();
+ private static final int FULL = 96;
+
+ public static final float STROKE_WITH = 6.5f;
+
+ private boolean mDisposed;
+
+ private int mAnimOffset;
+ private boolean mIsAnimating; // stores charge-animation status to reliably
+ //remove callbacks
+
+ private int mCircleSize; // draw size of circle
+ private RectF mRectLeft; // contains the precalculated rect used in drawArc(),
+ // derived from mCircleSize
+ private float mTextX, mTextY; // precalculated position for drawText() to appear centered
+
+ private Paint mTextPaint;
+ private Paint mFrontPaint;
+ private Paint mBackPaint;
+ private Paint mBoltPaint;
+ private Paint mWarningTextPaint;
+
+ private final RectF mBoltFrame = new RectF();
+
+ private int mChargeColor;
+ private final float[] mBoltPoints;
+ private final Path mBoltPath = new Path();
+
+ public CircleBatteryMeterDrawable(Resources res) {
+ super();
+ mDisposed = false;
+
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
+ mTextPaint.setTypeface(font);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mFrontPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mFrontPaint.setStrokeCap(Paint.Cap.BUTT);
+ mFrontPaint.setDither(true);
+ mFrontPaint.setStrokeWidth(0);
+ mFrontPaint.setStyle(Paint.Style.STROKE);
+
+ mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBackPaint.setColor(res.getColor(R.color.batterymeter_frame_color));
+ mBackPaint.setStrokeCap(Paint.Cap.BUTT);
+ mBackPaint.setDither(true);
+ mBackPaint.setStrokeWidth(0);
+ mBackPaint.setStyle(Paint.Style.STROKE);
+
+ mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mWarningTextPaint.setColor(mColors[1]);
+ font = Typeface.create("sans-serif", Typeface.BOLD);
+ mWarningTextPaint.setTypeface(font);
+ mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mChargeColor = getResources().getColor(R.color.batterymeter_charge_color);
+
+ mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color));
+ mBoltPoints = loadBoltPoints(res);
}
- }
- private final class BatteryTracker extends BroadcastReceiver {
- public static final int UNKNOWN_LEVEL = -1;
+ @Override
+ public void onDraw(Canvas c, BatteryTracker tracker) {
+ if (mDisposed) return;
- // current battery status
- int level = UNKNOWN_LEVEL;
- String percentStr;
- int plugType;
- boolean plugged;
- int health;
- int status;
- String technology;
- int voltage;
- int temperature;
- boolean testmode = false;
+ if (mRectLeft == null) {
+ initSizeBasedStuff();
+ }
+
+ drawCircle(c, tracker, mTextX, mRectLeft);
+ if (mAnimationsEnabled) {
+ updateChargeAnim(tracker);
+ }
+ }
@Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
+ public void onDispose() {
+ mDisposed = true;
+ }
- level = (int)(100f
- * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
- / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
+ @Override
+ public void setDarkIntensity(int backgroundColor, int fillColor) {
+ mIconTint = fillColor;
+ mBoltPaint.setColor(fillColor);
+ mChargeColor = fillColor;
+ invalidate();
+ }
- plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
- plugged = plugType != 0;
- health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH,
- BatteryManager.BATTERY_HEALTH_UNKNOWN);
- status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
- voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
- temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
+ @Override
+ public void onSizeChanged(int w, int h, int oldw, int oldh) {
+ initSizeBasedStuff();
+ }
- setContentDescription(
- context.getString(R.string.accessibility_battery_level, level));
- postInvalidate();
- } else if (action.equals(ACTION_LEVEL_TEST)) {
- testmode = true;
- post(new Runnable() {
- int curLevel = 0;
- int incr = 1;
- int saveLevel = level;
- int savePlugged = plugType;
- Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
- @Override
- public void run() {
- if (curLevel < 0) {
- testmode = false;
- dummy.putExtra("level", saveLevel);
- dummy.putExtra("plugged", savePlugged);
- dummy.putExtra("testmode", false);
- } else {
- dummy.putExtra("level", curLevel);
- dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
- : 0);
- dummy.putExtra("testmode", true);
- }
- getContext().sendBroadcast(dummy);
+ private float[] loadBoltPoints(Resources res) {
+ final int[] pts = res.getIntArray(getBoltPointsArrayResource());
+ int maxX = 0, maxY = 0;
+ for (int i = 0; i < pts.length; i += 2) {
+ maxX = Math.max(maxX, pts[i]);
+ maxY = Math.max(maxY, pts[i + 1]);
+ }
+ final float[] ptsF = new float[pts.length];
+ for (int i = 0; i < pts.length; i += 2) {
+ ptsF[i] = (float)pts[i] / maxX;
+ ptsF[i + 1] = (float)pts[i + 1] / maxY;
+ }
+ return ptsF;
+ }
- if (!testmode) return;
+ protected int getBoltPointsArrayResource() {
+ return R.array.batterymeter_bolt_points;
+ }
- curLevel += incr;
- if (curLevel == 100) {
- incr *= -1;
- }
- postDelayed(this, 200);
- }
- });
+ private void drawCircle(Canvas canvas, BatteryTracker tracker,
+ float textX, RectF drawRect) {
+ boolean unknownStatus = tracker.status == BatteryManager.BATTERY_STATUS_UNKNOWN;
+ int level = tracker.level;
+ Paint paint;
+
+ if (unknownStatus) {
+ paint = mBackPaint;
+ level = 100; // Draw all the circle;
+ } else {
+ paint = mFrontPaint;
+ paint.setColor(getColorForLevel(level));
+ if (tracker.status == BatteryManager.BATTERY_STATUS_FULL) {
+ level = 100;
+ }
+ }
+
+ // draw thin gray ring first
+ canvas.drawArc(drawRect, 270, 360, false, mBackPaint);
+ if (level != 0) {
+ // draw colored arc representing charge level
+ canvas.drawArc(drawRect, 270 + mAnimOffset, 3.6f * level, false, paint);
+ }
+ // if chosen by options, draw percentage text in the middle
+ // always skip percentage when 100, so layout doesnt break
+ if (unknownStatus) {
+ mTextPaint.setColor(paint.getColor());
+ canvas.drawText("?", textX, mTextY, mTextPaint);
+
+ } else if (tracker.plugged) {
+ canvas.drawPath(mBoltPath, mBoltPaint);
+ } else {
+ if (level > mCriticalLevel
+ && (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT))) {
+ // draw the percentage text
+ String pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
+ mTextPaint.setColor(paint.getColor());
+ canvas.drawText(pctText, textX, mTextY, mTextPaint);
+ } else if (level <= mCriticalLevel) {
+ // draw the warning text
+ canvas.drawText(mWarningString, textX, mTextY, mWarningTextPaint);
+ }
}
}
- }
- private final class SettingObserver extends ContentObserver {
- public SettingObserver() {
- super(new Handler());
+ /**
+ * updates the animation counter
+ * cares for timed callbacks to continue animation cycles
+ * uses mInvalidate for delayed invalidate() callbacks
+ */
+ private void updateChargeAnim(BatteryTracker tracker) {
+ // Stop animation when battery is full or after the meter
+ // rotated back to 0 after unplugging.
+ if (!tracker.shouldIndicateCharging()
+ || tracker.status == BatteryManager.BATTERY_STATUS_FULL
+ || tracker.level == 0) {
+ mIsAnimating = false;
+ } else {
+ mIsAnimating = true;
+ }
+
+ if (mAnimOffset > 360) {
+ mAnimOffset = 0;
+ }
+
+ boolean continueAnimation = mIsAnimating || mAnimOffset != 0;
+
+ if (continueAnimation) {
+ mAnimOffset += 3;
+ }
+
+ if (continueAnimation) {
+ postInvalidateDelayed(50);
+ }
}
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- super.onChange(selfChange, uri);
- updateShowPercent();
- postInvalidate();
+ /**
+ * initializes all size dependent variables
+ * sets stroke width and text size of all involved paints
+ * YES! i think the method name is appropriate
+ */
+ private void initSizeBasedStuff() {
+ mCircleSize = Math.min(getMeasuredWidth(), getMeasuredHeight());
+ mTextPaint.setTextSize(mCircleSize / 2f);
+ mWarningTextPaint.setTextSize(mCircleSize / 2f);
+
+ float strokeWidth = mCircleSize / STROKE_WITH;
+ mFrontPaint.setStrokeWidth(strokeWidth);
+ mBackPaint.setStrokeWidth(strokeWidth);
+
+ // calculate rectangle for drawArc calls
+ int pLeft = getPaddingLeft();
+ mRectLeft = new RectF(pLeft + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize
+ - strokeWidth / 2.0f + pLeft, mCircleSize - strokeWidth / 2.0f);
+
+ // calculate Y position for text
+ Rect bounds = new Rect();
+ mTextPaint.getTextBounds("99", 0, "99".length(), bounds);
+ mTextX = mCircleSize / 2.0f + getPaddingLeft();
+ // the +1dp at end of formula balances out rounding issues.works out on all resolutions
+ mTextY = mCircleSize / 2.0f + (bounds.bottom - bounds.top) / 2.0f
+ - strokeWidth / 2.0f + getResources().getDisplayMetrics().density;
+
+ // draw the bolt
+ final float bl = (int) (mRectLeft.left + mRectLeft.width() / 3.2f);
+ final float bt = (int) (mRectLeft.top + mRectLeft.height() / 4f);
+ final float br = (int) (mRectLeft.right - mRectLeft.width() / 5.2f);
+ final float bb = (int) (mRectLeft.bottom - mRectLeft.height() / 8f);
+ if (mBoltFrame.left != bl || mBoltFrame.top != bt
+ || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
+ mBoltFrame.set(bl, bt, br, bb);
+ mBoltPath.reset();
+ mBoltPath.moveTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ for (int i = 2; i < mBoltPoints.length; i += 2) {
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
+ }
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ }
}
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java
new file mode 100644
index 0000000..1678e94
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+
+public class DockBatteryLevelTextView extends BatteryLevelTextView {
+
+ public DockBatteryLevelTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setPaintFlags(getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java
new file mode 100755
index 0000000..b80e6d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.BatteryManager;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class DockBatteryMeterView extends BatteryMeterView {
+
+ private BatteryManager mBatteryService;
+ private final boolean mSupported;
+
+ private class DockBatteryTracker extends BatteryTracker {
+
+ public DockBatteryTracker() {
+ super();
+ present = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
+
+ if (mSupported) {
+ level = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100));
+
+ present = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false);
+ plugType = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0);
+ // We need to add a extra check over the status because of dock batteries
+ // PlugType doesn't means that the dock battery is charging (some devices
+ // doesn't charge under dock usb)
+ plugged = plugType != 0 && (status == BatteryManager.BATTERY_STATUS_CHARGING ||
+ status == BatteryManager.BATTERY_STATUS_FULL);
+ health = intent.getIntExtra(BatteryManager.EXTRA_DOCK_HEALTH,
+ BatteryManager.BATTERY_HEALTH_UNKNOWN);
+ status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ technology = intent.getStringExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY);
+ voltage = intent.getIntExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, 0);
+ temperature = intent.getIntExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE, 0);
+
+
+ if (present && (mMeterMode != BatteryMeterMode.BATTERY_METER_GONE &&
+ mMeterMode != BatteryMeterMode.BATTERY_METER_TEXT)) {
+ setContentDescription(context.getString(
+ R.string.accessibility_dock_battery_level, level));
+ setVisibility(View.VISIBLE);
+ invalidate();
+ } else {
+ setContentDescription(null);
+ setVisibility(View.GONE);
+ }
+ } else {
+ setContentDescription(null);
+ setVisibility(View.GONE);
+
+ // If dock is not supported then we don't need this receiver anymore
+ getContext().unregisterReceiver(this);
+ }
+ } else if (action.equals(ACTION_LEVEL_TEST)) {
+ testmode = true;
+ post(new Runnable() {
+ int curLevel = 0;
+ int incr = 1;
+ int saveLevel = level;
+ int savePlugged = plugType;
+ Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ @Override
+ public void run() {
+ if (curLevel < 0) {
+ testmode = false;
+ dummy.putExtra("level", saveLevel);
+ dummy.putExtra("plugged", savePlugged);
+ dummy.putExtra("testmode", false);
+ } else {
+ dummy.putExtra("level", curLevel);
+ dummy.putExtra("plugged", incr > 0
+ ? BatteryManager.BATTERY_DOCK_PLUGGED_AC : 0);
+ dummy.putExtra("testmode", true);
+ }
+ getContext().sendBroadcast(dummy);
+
+ if (!testmode) return;
+
+ curLevel += incr;
+ if (curLevel == 100) {
+ incr *= -1;
+ }
+ postDelayed(this, 200);
+ }
+ });
+ }
+ }
+ }
+
+ public DockBatteryMeterView(Context context) {
+ this(context, null, 0);
+ }
+
+ public DockBatteryMeterView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DockBatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE));
+ mSupported = mBatteryService.isDockBatterySupported();
+ mDemoTracker = new DockBatteryTracker();
+ mTracker = new DockBatteryTracker();
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ // We already unregistered the listener once when we decided
+ // support was absent. Don't do it again.
+ if (mSupported) {
+ super.onDetachedFromWindow();
+ }
+ }
+
+ @Override
+ public void setMode(BatteryMeterMode mode) {
+ super.setMode(mode);
+ int visibility = getVisibility();
+ if (visibility == View.VISIBLE && !mSupported) {
+ setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ protected BatteryMeterDrawable createBatteryMeterDrawable(BatteryMeterMode mode) {
+ Resources res = mContext.getResources();
+ switch (mode) {
+ case BATTERY_METER_CIRCLE:
+ return new DockCircleBatteryMeterDrawable(res);
+ case BATTERY_METER_ICON_LANDSCAPE:
+ return new DockNormalBatteryMeterDrawable(res, true);
+ case BATTERY_METER_TEXT:
+ case BATTERY_METER_GONE:
+ return null;
+ default:
+ return new DockNormalBatteryMeterDrawable(res, false);
+ }
+ }
+
+ protected class DockNormalBatteryMeterDrawable extends NormalBatteryMeterDrawable {
+
+ public DockNormalBatteryMeterDrawable(Resources res, boolean horizontal) {
+ super(res, horizontal);
+ }
+
+ @Override
+ protected int getBoltPointsArrayResource() {
+ return mHorizontal
+ ? R.array.dockbatterymeter_inverted_bolt_points
+ : R.array.dockbatterymeter_bolt_points;
+ }
+ }
+
+ protected class DockCircleBatteryMeterDrawable extends CircleBatteryMeterDrawable {
+ public DockCircleBatteryMeterDrawable(Resources res) {
+ super(res);
+ }
+
+ @Override
+ protected int getBoltPointsArrayResource() {
+ return R.array.dockbatterymeter_bolt_points;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 8556afc..5a6f3c9 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -236,7 +236,9 @@ public class ImageWallpaper extends WallpaperService {
Log.d(TAG, "Visibility changed to visible=" + visible);
}
mVisible = visible;
- drawFrame();
+ if (visible) {
+ drawFrame();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 0b066af..565fbd7 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.content.res.ThemeConfig;
import android.os.SystemProperties;
import android.util.Log;
@@ -58,6 +59,7 @@ public class SystemUIApplication extends Application {
private boolean mServicesStarted;
private boolean mBootCompleted;
private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>();
+ private Configuration mConfig;
@Override
public void onCreate() {
@@ -85,6 +87,7 @@ public class SystemUIApplication extends Application {
}
}
}, filter);
+ mConfig = new Configuration(getResources().getConfiguration());
}
/**
@@ -134,6 +137,12 @@ public class SystemUIApplication extends Application {
@Override
public void onConfigurationChanged(Configuration newConfig) {
+ if (isThemeChange(mConfig, newConfig)) {
+ // theme resource changed so recreate styles and attributes
+ recreateTheme();
+ }
+
+ mConfig.setTo(newConfig);
if (mServicesStarted) {
int len = mServices.length;
for (int i = 0; i < len; i++) {
@@ -150,4 +159,11 @@ public class SystemUIApplication extends Application {
public SystemUI[] getServices() {
return mServices;
}
+
+ private static boolean isThemeChange(Configuration oldConfig, Configuration newConfig) {
+ final ThemeConfig oldThemeConfig = oldConfig != null ? oldConfig.themeConfig : null;
+ final ThemeConfig newThemeConfig = newConfig != null ? newConfig.themeConfig : null;
+
+ return newThemeConfig != null && !newThemeConfig.equals(oldThemeConfig);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/cm/GlowBackground.java b/packages/SystemUI/src/com/android/systemui/cm/GlowBackground.java
new file mode 100644
index 0000000..8b4bf06
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/GlowBackground.java
@@ -0,0 +1,83 @@
+package com.android.systemui.cm;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.view.animation.AnticipateOvershootInterpolator;
+
+public class GlowBackground extends Drawable implements ValueAnimator.AnimatorUpdateListener {
+
+ private static final int MAX_CIRCLE_SIZE = 150;
+
+ private final Paint mPaint;
+ private Animator mAnimator;
+ private float mCircleSize;
+
+ public GlowBackground(int color) {
+ mPaint = new Paint();
+ mPaint.setColor(color);
+ }
+
+ private void startAnimation(boolean hide) {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ if (hide && mCircleSize == 0f) {
+ return;
+ } else if (!hide && mCircleSize == MAX_CIRCLE_SIZE) {
+ return;
+ }
+ mAnimator = getAnimator(hide);
+ mAnimator.start();
+ }
+
+ private Animator getAnimator(boolean hide) {
+ float start = mCircleSize;
+ float end = MAX_CIRCLE_SIZE;
+ if (hide) {
+ end = 0f;
+ }
+ ValueAnimator animator = ObjectAnimator.ofFloat(start, end);
+ animator.setInterpolator(new AnticipateOvershootInterpolator());
+ animator.setDuration(300);
+ animator.addUpdateListener(this);
+ return animator;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawCircle(getBounds().width() / 2, getBounds().height() / 2, mCircleSize, mPaint);
+ }
+
+ @Override
+ public void setAlpha(int i) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ mCircleSize = (Float) valueAnimator.getAnimatedValue();
+ invalidateSelf();
+ }
+
+ public void hideGlow() {
+ startAnimation(true);
+ }
+
+ public void showGlow() {
+ startAnimation(false);
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java
new file mode 100644
index 0000000..d8cfa5e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java
@@ -0,0 +1,239 @@
+package com.android.systemui.cm;
+
+import com.android.settingslib.cm.ShortcutPickHelper;
+import com.android.systemui.R;
+import com.android.systemui.cm.LockscreenShortcutsHelper.Shortcuts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+
+public class LockscreenShortcutsActivity extends Activity implements View.OnClickListener,
+ ShortcutPickHelper.OnPickListener, View.OnTouchListener, LockscreenShortcutsHelper.OnChangeListener {
+
+ private static final int[] sIconIds = new int[]{R.id.left_button, R.id.right_button};
+ private static final String ACTION_APP = "action_app";
+
+ private ActionHolder mActions;
+ private ShortcutPickHelper mPicker;
+ private LockscreenShortcutsHelper mShortcutHelper;
+ private View mSelectedView;
+ private ColorMatrixColorFilter mFilter;
+ private ColorStateList mDefaultTintList;
+
+ @Override
+ public void shortcutPicked(String uri, String friendlyName, boolean isApplication) {
+ onTargetChange(uri);
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ GlowBackground background = (GlowBackground) v.getBackground();
+ background.showGlow();
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ background = (GlowBackground) v.getBackground();
+ background.hideGlow();
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public void onChange() {
+ updateDrawables();
+ }
+
+ private class ActionHolder {
+ private ArrayList<CharSequence> mAvailableEntries = new ArrayList<CharSequence>();
+ private ArrayList<String> mAvailableValues = new ArrayList<String>();
+
+ public void addAction(String action, int entryResId) {
+ mAvailableEntries.add(getString(entryResId));
+ mAvailableValues.add(action);
+ }
+
+ public int getActionIndex(String action) {
+ int count = mAvailableValues.size();
+ for (int i = 0; i < count; i++) {
+ if (TextUtils.equals(mAvailableValues.get(i), action)) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public String getAction(int index) {
+ if (index > mAvailableValues.size()) {
+ return null;
+ }
+
+ return mAvailableValues.get(index);
+ }
+
+ public CharSequence[] getEntries() {
+ return mAvailableEntries.toArray(new CharSequence[mAvailableEntries.size()]);
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.lockscreen_shortcuts);
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+
+ mPicker = new ShortcutPickHelper(this, this);
+ mShortcutHelper = new LockscreenShortcutsHelper(this, this);
+ ColorMatrix cm = new ColorMatrix();
+ cm.setSaturation(0);
+ mFilter = new ColorMatrixColorFilter(cm);
+ ImageView unlockButton = (ImageView) findViewById(R.id.middle_button);
+ mDefaultTintList = unlockButton.getImageTintList();
+ createActionList();
+ initiateViews();
+ updateDrawables();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void initiateViews() {
+ int size = getResources().getDimensionPixelSize(R.dimen.lockscreen_icon_size);
+ for (int id : sIconIds) {
+ View v = findViewById(id);
+ v.setOnClickListener(this);
+ v.setOnTouchListener(this);
+ GlowBackground background = new GlowBackground(Color.WHITE);
+ background.setBounds(0, 0, size, size);
+ v.setBackground(background);
+ }
+ }
+
+ private void updateDrawables() {
+ for (int i = 0; i < sIconIds.length; i++) {
+ int id = sIconIds[i];
+ ImageView v = (ImageView) findViewById(id);
+ v.setImageTintList(null);
+ v.setColorFilter(null);
+ Shortcuts shortcut = Shortcuts.values()[i];
+ v.setTag(mShortcutHelper.getUriForTarget(shortcut));
+ Drawable drawable;
+ if (mShortcutHelper.isTargetEmpty(shortcut)) {
+ drawable = getResources().getDrawable(R.drawable.ic_lockscreen_shortcuts_blank);
+ } else {
+ drawable = mShortcutHelper.getDrawableForTarget(shortcut);
+ if (drawable == null) {
+ drawable = getResources().getDrawable(shortcut == Shortcuts.LEFT_SHORTCUT
+ ? R.drawable.ic_phone_24dp : R.drawable.ic_camera_alt_24dp);
+ v.setImageTintList(mDefaultTintList);
+ } else {
+ v.setColorFilter(mFilter);
+ }
+ }
+ v.setImageDrawable(drawable);
+ }
+ }
+
+ private void createActionList() {
+ mActions = new ActionHolder();
+ mActions.addAction(LockscreenShortcutsHelper.NONE, R.string.lockscreen_none_target);
+ mActions.addAction(LockscreenShortcutsHelper.DEFAULT, R.string.lockscreen_default_target);
+ mActions.addAction(ACTION_APP, R.string.select_application);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mPicker.onActivityResult(requestCode, resultCode, data);
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public void onClick(View v) {
+ mSelectedView = v;
+
+ final GlowBackground background = (GlowBackground) mSelectedView.getBackground();
+
+ mSelectedView.postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ background.showGlow();
+ }
+ });
+
+ final DialogInterface.OnClickListener l = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int item) {
+ onTargetChange(mActions.getAction(item));
+ dialog.dismiss();
+ }
+ };
+
+ final DialogInterface.OnCancelListener cancel = new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ onTargetChange(null);
+ }
+ };
+
+ final AlertDialog dialog = new AlertDialog.Builder(this)
+ .setTitle(R.string.lockscreen_choose_action_title)
+ .setItems(mActions.getEntries(), l)
+ .setOnCancelListener(cancel)
+ .create();
+
+ dialog.show();
+ }
+
+ private void onTargetChange(String uri) {
+ if (uri == null) {
+ final GlowBackground background = (GlowBackground) mSelectedView.getBackground();
+ background.hideGlow();
+ return;
+ }
+
+ if (uri.equals(ACTION_APP)) {
+ mPicker.pickShortcut(null, null, 0);
+ } else {
+ mSelectedView.setTag(uri);
+ saveCustomActions();
+ GlowBackground background = (GlowBackground) mSelectedView.getBackground();
+ background.hideGlow();
+ }
+ }
+
+ private void saveCustomActions() {
+ ArrayList<String> targets = new ArrayList<String>();
+ for (int id : sIconIds) {
+ View v = findViewById(id);
+ String uri = (String) v.getTag();
+ targets.add(uri);
+ }
+ mShortcutHelper.saveTargets(targets);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java
new file mode 100644
index 0000000..12b9810
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java
@@ -0,0 +1,196 @@
+package com.android.systemui.cm;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.graphics.Bitmap;
+import android.graphics.ColorFilter;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.android.systemui.R;
+import cyanogenmod.providers.CMSettings;
+
+public class LockscreenShortcutsHelper {
+
+ private Handler mHandler;
+
+ public enum Shortcuts {
+ LEFT_SHORTCUT(0),
+ RIGHT_SHORTCUT(1);
+
+ private final int index;
+
+ Shortcuts(int index) {
+ this.index = index;
+ }
+ }
+
+ public static final String DEFAULT = "default";
+ public static final String NONE = "none";
+ private static final String DELIMITER = "|";
+
+ private final Context mContext;
+ private OnChangeListener mListener;
+ private List<String> mTargetActivities;
+
+ public interface OnChangeListener {
+ void onChange();
+ }
+
+ public LockscreenShortcutsHelper(Context context, OnChangeListener listener) {
+ mContext = context;
+ if (listener != null) {
+ mListener = listener;
+ mHandler = new Handler(Looper.getMainLooper());
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.Secure.getUriFor(CMSettings.Secure.LOCKSCREEN_TARGETS), false, mObserver);
+ }
+ fetchTargets();
+ }
+
+ private ContentObserver mObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ fetchTargets();
+ if (mListener != null && mHandler != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mListener.onChange();
+ }
+ });
+ }
+ }
+ };
+
+ public void cleanup() {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ mListener = null;
+ }
+
+ public static class TargetInfo {
+ public Drawable icon;
+ public ColorFilter colorFilter;
+ public String uri;
+ public TargetInfo(Drawable icon, ColorFilter colorFilter, String uri) {
+ this.icon = icon;
+ this.colorFilter = colorFilter;
+ this.uri = uri;
+ }
+ }
+
+ private void fetchTargets() {
+ mTargetActivities = CMSettings.Secure.getDelimitedStringAsList(mContext.getContentResolver(),
+ CMSettings.Secure.LOCKSCREEN_TARGETS, DELIMITER);
+ int itemsToPad = Shortcuts.values().length - mTargetActivities.size();
+ if (itemsToPad > 0) {
+ for (int i = 0; i < itemsToPad; i++) {
+ mTargetActivities.add(DEFAULT);
+ }
+ }
+ }
+
+ public Drawable getDrawableForTarget(Shortcuts shortcut) {
+ Intent intent = getIntent(shortcut);
+ if (intent != null) {
+ PackageManager pm = mContext.getPackageManager();
+ ActivityInfo info = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES);
+ if (info != null) {
+ return getScaledDrawable(info.loadIcon(pm));
+ }
+ }
+ return null;
+ }
+
+ public String getUriForTarget(Shortcuts shortcuts) {
+ return mTargetActivities.get(shortcuts.index);
+ }
+
+ private Drawable getScaledDrawable(Drawable drawable) {
+ if (drawable instanceof BitmapDrawable) {
+ Resources res = mContext.getResources();
+ int width = res.getDimensionPixelSize(R.dimen.keyguard_affordance_icon_width);
+ int height = res.getDimensionPixelSize(R.dimen.keyguard_affordance_icon_height);
+ return new BitmapDrawable(mContext.getResources(),
+ Bitmap.createScaledBitmap(((BitmapDrawable) drawable).getBitmap(),
+ width, height, true));
+ } else {
+ return drawable;
+ }
+ }
+
+ private String getFriendlyActivityName(Intent intent, boolean labelOnly) {
+ PackageManager pm = mContext.getPackageManager();
+ ActivityInfo ai = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES);
+ String friendlyName = null;
+ if (ai != null) {
+ friendlyName = ai.loadLabel(pm).toString();
+ if (friendlyName == null && !labelOnly) {
+ friendlyName = ai.name;
+ }
+ }
+ return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0);
+ }
+
+ private String getFriendlyShortcutName(Intent intent) {
+ String activityName = getFriendlyActivityName(intent, true);
+ String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+
+ if (activityName != null && name != null) {
+ return activityName + ": " + name;
+ }
+ return name != null ? name : intent.toUri(0);
+ }
+
+ public String getFriendlyNameForUri(Shortcuts shortcut) {
+ Intent intent = getIntent(shortcut);
+ if (Intent.ACTION_MAIN.equals(intent.getAction())) {
+ return getFriendlyActivityName(intent, false);
+ }
+ return getFriendlyShortcutName(intent);
+ }
+
+ public boolean isTargetCustom(Shortcuts shortcut) {
+ if (mTargetActivities == null || mTargetActivities.isEmpty()) {
+ return false;
+ }
+ String action = mTargetActivities.get(shortcut.index);
+ if (DEFAULT.equals(action)) {
+ return false;
+ }
+
+ return NONE.equals(action) || getIntent(shortcut) != null;
+ }
+
+ public boolean isTargetEmpty(Shortcuts shortcut) {
+ return mTargetActivities != null &&
+ !mTargetActivities.isEmpty() &&
+ mTargetActivities.get(shortcut.index).equals(NONE);
+ }
+
+ public Intent getIntent(Shortcuts shortcut) {
+ Intent intent = null;
+ try {
+ intent = Intent.parseUri(mTargetActivities.get(shortcut.index), 0);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ return intent;
+ }
+
+ public void saveTargets(ArrayList<String> targets) {
+ CMSettings.Secure.putListAsDelimitedString(mContext.getContentResolver(),
+ CMSettings.Secure.LOCKSCREEN_TARGETS, DELIMITER, targets);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java b/packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java
new file mode 100644
index 0000000..7afa04d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java
@@ -0,0 +1,204 @@
+package com.android.systemui.cm;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.internal.util.cm.SpamFilter;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+
+public class SpamMessageProvider extends ContentProvider {
+ public static final String AUTHORITY = SpamFilter.AUTHORITY;
+
+ private static final String UPDATE_COUNT_QUERY =
+ "UPDATE " + NotificationTable.TABLE_NAME +
+ " SET " + NotificationTable.LAST_BLOCKED + "=%d," +
+ NotificationTable.COUNT + "=" + NotificationTable.COUNT + "+1 " +
+ " WHERE " + NotificationTable.ID + "='%s'";
+
+ private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ private static final int PACKAGES = 0;
+ private static final int MESSAGES = 1;
+ private static final int PACKAGE_FOR_ID = 2;
+ private static final int MESSAGE_UPDATE_COUNT = 3;
+ private static final int MESSAGE_FOR_ID = 4;
+ static {
+ sURIMatcher.addURI(AUTHORITY, "packages", PACKAGES);
+ sURIMatcher.addURI(AUTHORITY, "messages", MESSAGES);
+ sURIMatcher.addURI(AUTHORITY, "message/#", MESSAGE_FOR_ID);
+ sURIMatcher.addURI(AUTHORITY, "message/inc_count/#", MESSAGE_UPDATE_COUNT);
+ }
+
+ private SpamOpenHelper mDbHelper;
+
+ @Override
+ public boolean onCreate() {
+ mDbHelper = new SpamOpenHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case PACKAGE_FOR_ID:
+ return mDbHelper.getReadableDatabase().query(PackageTable.TABLE_NAME,
+ new String[]{NotificationTable.ID}, PackageTable.PACKAGE_NAME + "=?",
+ new String[]{uri.getLastPathSegment()}, null, null, null);
+ case PACKAGES:
+ return mDbHelper.getReadableDatabase().query(PackageTable.TABLE_NAME,
+ projection, selection, selectionArgs, null, null, sortOrder);
+ case MESSAGES:
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(NotificationTable.TABLE_NAME + " LEFT OUTER JOIN " + PackageTable.TABLE_NAME +
+ " ON (" + NotificationTable.TABLE_NAME + "." + NotificationTable.PACKAGE_ID + " = "
+ + PackageTable.TABLE_NAME + "." + PackageTable.ID + ")");
+ SQLiteDatabase db = mDbHelper.getReadableDatabase();
+ return qb.query(db, projection, selection, selectionArgs,
+ null, null, null);
+ case MESSAGE_FOR_ID:
+ qb = new SQLiteQueryBuilder();
+ qb.setTables(NotificationTable.TABLE_NAME + " LEFT OUTER JOIN " + PackageTable.TABLE_NAME +
+ " ON (" + NotificationTable.TABLE_NAME + "." + NotificationTable.PACKAGE_ID + " = "
+ + PackageTable.TABLE_NAME + "." + PackageTable.ID + ")");
+ qb.appendWhere(NotificationTable.TABLE_NAME + "." + NotificationTable.ID + "="
+ + uri.getLastPathSegment());
+ return qb.query(mDbHelper.getReadableDatabase(),
+ null, null, null, null,
+ null, null);
+ default:
+ return null;
+ }
+ }
+
+ private long getPackageId(String pkg) {
+ long rowId = -1;
+ Cursor idCursor = mDbHelper.getReadableDatabase().query(PackageTable.TABLE_NAME,
+ new String[]{NotificationTable.ID}, PackageTable.PACKAGE_NAME + "=?",
+ new String[]{pkg}, null, null, null);
+ if (idCursor != null) {
+ if (idCursor.moveToFirst()) {
+ rowId = idCursor.getLong(0);
+ }
+ idCursor.close();
+ }
+ return rowId;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ if (values == null) {
+ return null;
+ }
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case MESSAGES:
+ String msgText = values.getAsString(NotificationTable.MESSAGE_TEXT);
+ String packageName = values.getAsString(PackageTable.PACKAGE_NAME);
+ if (TextUtils.isEmpty(msgText) || TextUtils.isEmpty(packageName)) {
+ return null;
+ }
+ values.clear();
+ values.put(PackageTable.PACKAGE_NAME, packageName);
+ long packageId = getPackageId(packageName);
+ if (packageId == -1) {
+ SQLiteDatabase writableDb = mDbHelper.getWritableDatabase();
+ packageId = writableDb.insert(
+ PackageTable.TABLE_NAME, null, values);
+ }
+ if (packageId != -1) {
+ values.clear();
+ values.put(NotificationTable.MESSAGE_TEXT, msgText);
+ values.put(NotificationTable.NORMALIZED_TEXT,
+ SpamFilter.getNormalizedContent(msgText));
+ values.put(NotificationTable.PACKAGE_ID, packageId);
+ values.put(NotificationTable.LAST_BLOCKED, System.currentTimeMillis());
+ long id = mDbHelper.getReadableDatabase().insert(NotificationTable.TABLE_NAME,
+ null, values);
+ if (id != -1) {
+ notifyChange(String.valueOf(id));
+ }
+ }
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ private void notifyChange(String id) {
+ Uri uri = Uri.withAppendedPath(SpamFilter.NOTIFICATION_URI,
+ id);
+ getContext().getContentResolver().notifyChange(uri, null);
+ }
+
+ private void removePackageIfNecessary(int packageId) {
+ long numEntries = DatabaseUtils.queryNumEntries(mDbHelper.getReadableDatabase(),
+ NotificationTable.TABLE_NAME, NotificationTable.PACKAGE_ID + "=?",
+ new String[]{String.valueOf(packageId)});
+ if (numEntries == 0) {
+ SQLiteDatabase writableDb = mDbHelper.getWritableDatabase();
+ writableDb.delete(PackageTable.TABLE_NAME, PackageTable.ID + "=?",
+ new String[]{String.valueOf(packageId)});
+ }
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case MESSAGE_FOR_ID:
+ int packageId = -1;
+ Cursor idCursor = mDbHelper.getReadableDatabase().query(NotificationTable.TABLE_NAME,
+ new String[]{NotificationTable.PACKAGE_ID}, NotificationTable.ID + "=?",
+ new String[]{uri.getLastPathSegment()}, null, null, null);
+ if (idCursor != null) {
+ if (idCursor.moveToFirst()) {
+ packageId = idCursor.getInt(0);
+ }
+ idCursor.close();
+ }
+ SQLiteDatabase writableDb = mDbHelper.getWritableDatabase();
+ String id = uri.getLastPathSegment();
+ int result = writableDb.delete(NotificationTable.TABLE_NAME,
+ NotificationTable.ID + "=?", new String[]{id});
+ removePackageIfNecessary(packageId);
+ if (result > 0) {
+ notifyChange(id);
+ }
+ return result;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case MESSAGE_UPDATE_COUNT:
+ String id = uri.getLastPathSegment();
+ String formattedQuery = String.format(UPDATE_COUNT_QUERY,
+ System.currentTimeMillis(), id);
+ SQLiteDatabase writableDb = mDbHelper.getWritableDatabase();
+ writableDb.execSQL(formattedQuery);
+ notifyChange(id);
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java b/packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java
new file mode 100644
index 0000000..45dc91c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java
@@ -0,0 +1,46 @@
+package com.android.systemui.cm;
+
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class SpamOpenHelper extends SQLiteOpenHelper {
+
+ private static final String DATABASE_NAME = "spam.db";
+ private static final int VERSION = 4;
+ private static final String CREATE_PACKAGES_TABLE =
+ "create table " + PackageTable.TABLE_NAME + "(" +
+ PackageTable.ID + " INTEGER PRIMARY KEY," +
+ PackageTable.PACKAGE_NAME + " TEXT UNIQUE);";
+ private static final String CREATE_NOTIFICATIONS_TABLE =
+ "create table " + NotificationTable.TABLE_NAME + "(" +
+ NotificationTable.ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ NotificationTable.PACKAGE_ID + " INTEGER," +
+ NotificationTable.MESSAGE_TEXT + " STRING," +
+ NotificationTable.LAST_BLOCKED + " INTEGER," +
+ NotificationTable.NORMALIZED_TEXT + " STRING," +
+ NotificationTable.COUNT + " INTEGER DEFAULT 0);";
+
+ private Context mContext;
+
+ public SpamOpenHelper(Context context) {
+ super(context, DATABASE_NAME, null, VERSION);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(CREATE_PACKAGES_TABLE);
+ db.execSQL(CREATE_NOTIFICATIONS_TABLE);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ mContext.deleteDatabase(DATABASE_NAME);
+ onCreate(db);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/cm/UserContentObserver.java b/packages/SystemUI/src/com/android/systemui/cm/UserContentObserver.java
new file mode 100644
index 0000000..5ece744
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/UserContentObserver.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.cm;
+
+import android.app.ActivityManagerNative;
+import android.app.IUserSwitchObserver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Simple extension of ContentObserver that also listens for user switch events to call update
+ */
+public abstract class UserContentObserver extends ContentObserver {
+ private static final String TAG = "UserContentObserver";
+
+ private Runnable mUpdateRunnable;
+
+ private IUserSwitchObserver mUserSwitchObserver = new IUserSwitchObserver.Stub() {
+ @Override
+ public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+ }
+ @Override
+ public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ mHandler.post(mUpdateRunnable);
+ }
+ @Override
+ public void onForegroundProfileSwitch(int newProfileId) {
+ }
+ };
+
+ private Handler mHandler;
+
+ public UserContentObserver(Handler handler) {
+ super(handler);
+ mHandler = handler;
+ mUpdateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ update();
+ }
+ };
+ }
+
+ protected void observe() {
+ try {
+ ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchObserver);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to register user switch observer!", e);
+ }
+ }
+
+ protected void unobserve() {
+ try {
+ mHandler.removeCallbacks(mUpdateRunnable);
+ ActivityManagerNative.getDefault().unregisterUserSwitchObserver(mUserSwitchObserver);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to unregister user switch observer!", e);
+ }
+ }
+
+ protected abstract void update();
+
+ @Override
+ public void onChange(boolean selfChange) {
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 39423f2..f223400 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -218,7 +218,7 @@ public class DozeService extends DreamService {
// Here we need a wakelock to stay awake until the pulse is finished.
mWakeLock.acquire();
mPulsing = true;
- if (!mDozeParameters.getProxCheckBeforePulse()) {
+ if (!mDozeParameters.getProxCheckBeforePulse(reason)) {
// skip proximity check
continuePulsing(reason);
return;
@@ -265,6 +265,7 @@ public class DozeService extends DreamService {
@Override
public void onPulseStarted() {
if (mPulsing && mDreaming) {
+ mContext.sendBroadcast(new Intent(Intent.ACTION_DOZE_PULSE_STARTING));
turnDisplayOn();
}
}
@@ -356,7 +357,7 @@ public class DozeService extends DreamService {
if (DEBUG) Log.d(mTag, "No more schedule resets remaining");
return;
}
- final long pulseDuration = mDozeParameters.getPulseDuration(false /*pickup*/);
+ final long pulseDuration = mDozeParameters.getPulseDuration(DozeLog.PULSE_REASON_NOTIFICATION);
boolean pulseImmediately = System.currentTimeMillis() >= notificationTimeMs;
if ((notificationTimeMs - mLastScheduleResetTime) >= pulseDuration) {
mScheduleResetsRemaining--;
diff --git a/packages/SystemUI/src/com/android/systemui/egg/CMLand.java b/packages/SystemUI/src/com/android/systemui/egg/CMLand.java
new file mode 100644
index 0000000..6020b45
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/egg/CMLand.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014-2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.egg;
+
+import com.android.systemui.R;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+public class CMLand extends MLand {
+ public static final String TAG = "CMLand";
+
+ public CMLand(Context context) {
+ this(context, null);
+ }
+
+ public CMLand(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CMLand(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected int getEggPlayer() {
+ return R.drawable.cid;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLand.java b/packages/SystemUI/src/com/android/systemui/egg/MLand.java
index b84777b..1b22e04 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLand.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLand.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2014-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -210,6 +211,8 @@ public class MLand extends FrameLayout {
// we assume everything will be laid out left|top
setLayoutDirection(LAYOUT_DIRECTION_LTR);
+ Player.eggPlayer = getEggPlayer();
+
setupPlayers(DEFAULT_PLAYERS);
MetricsLogger.count(getContext(), "egg_mland_create", 1);
@@ -1007,7 +1010,7 @@ public class MLand extends FrameLayout {
public void step(long t_ms, long dt_ms, float t, float dt);
}
- private static class Player extends ImageView implements GameView {
+ protected static class Player extends ImageView implements GameView {
public float dv;
public int color;
private MLand mLand;
@@ -1017,6 +1020,8 @@ public class MLand extends FrameLayout {
private int mScore;
private TextView mScoreField;
+ protected static int eggPlayer;
+
private final int[] sColors = new int[] {
//0xFF78C557,
0xFFDB4437,
@@ -1088,7 +1093,7 @@ public class MLand extends FrameLayout {
public Player(Context context) {
super(context);
- setBackgroundResource(R.drawable.android);
+ setBackgroundResource(eggPlayer);
getBackground().setTintMode(PorterDuff.Mode.SRC_ATOP);
color = sColors[(sNextColor++%sColors.length)];
getBackground().setTint(color);
@@ -1438,4 +1443,8 @@ public class MLand extends FrameLayout {
v = z = 0;
}
}
+
+ protected int getEggPlayer() {
+ return R.drawable.android;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
index cdda45f..6fd7387 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2014-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +30,14 @@ public class MLandActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.mland);
+ final boolean isCM = getIntent().getBooleanExtra("is_cm", false);
+ if (isCM) {
+ setContentView(R.layout.cmland);
+ mLand = (CMLand) findViewById(R.id.world);
+ } else {
+ setContentView(R.layout.mland);
+ mLand = (MLand) findViewById(R.id.world);
+ }
mLand = (MLand) findViewById(R.id.world);
mLand.setScoreFieldHolder((ViewGroup) findViewById(R.id.scores));
final View welcome = findViewById(R.id.welcome);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 055b5ef..2152ede6 100644..100755
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -23,13 +23,16 @@ import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.app.StatusBarManager;
+import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.UserInfo;
+import android.database.ContentObserver;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
@@ -56,6 +59,11 @@ import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.qs.tiles.LockscreenToggleTile;
+import cyanogenmod.app.Profile;
+import cyanogenmod.app.ProfileManager;
+
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardStateCallback;
@@ -73,6 +81,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import cyanogenmod.providers.CMSettings;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -135,6 +144,13 @@ public class KeyguardViewMediator extends SystemUI {
private static final String DELAYED_KEYGUARD_ACTION =
"com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
+ private static final String DISMISS_KEYGUARD_SECURELY_ACTION =
+ "com.android.keyguard.action.DISMISS_KEYGUARD_SECURELY";
+
+ private static final String KEYGUARD_SERVICE_ACTION_STATE_CHANGE =
+ "com.android.internal.action.KEYGUARD_SERVICE_STATE_CHANGED";
+ private static final String KEYGUARD_SERVICE_EXTRA_ACTIVE = "active";
+
// used for handler messages
private static final int SHOW = 2;
private static final int HIDE = 3;
@@ -187,7 +203,6 @@ public class KeyguardViewMediator extends SystemUI {
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
private boolean mSwitchingUser;
-
private boolean mSystemReady;
private boolean mBootCompleted;
private boolean mBootSendUserPresent;
@@ -250,6 +265,11 @@ public class KeyguardViewMediator extends SystemUI {
*/
private IKeyguardExitCallback mExitSecureCallback;
+ /**
+ * Whether we are bound to the service delegate
+ */
+ private boolean mKeyguardBound;
+
// the properties of the keyguard
private KeyguardUpdateMonitor mUpdateMonitor;
@@ -267,6 +287,11 @@ public class KeyguardViewMediator extends SystemUI {
private boolean mHiding;
/**
+ * Whether we are disabling the lock screen internally
+ */
+ private boolean mInternallyDisabled = false;
+
+ /**
* we send this intent when the keyguard is dismissed.
*/
private static final Intent USER_PRESENT_INTENT = new Intent(Intent.ACTION_USER_PRESENT)
@@ -321,6 +346,50 @@ public class KeyguardViewMediator extends SystemUI {
private boolean mWakeAndUnlocking;
private IKeyguardDrawnCallback mDrawnCallback;
+ private LockscreenEnabledSettingsObserver mSettingsObserver;
+ public static class LockscreenEnabledSettingsObserver extends UserContentObserver {
+
+ private static final String KEY_ENABLED = "lockscreen_enabled";
+
+ private boolean mObserving;
+ private SharedPreferences mPrefs;
+ private Context mContext;
+
+ public LockscreenEnabledSettingsObserver(Context context, Handler handler) {
+ super(handler);
+ mContext = context;
+ mPrefs = mContext.getSharedPreferences("quicksettings", Context.MODE_PRIVATE);
+ }
+
+ public boolean getPersistedDefaultOldSetting() {
+ return mPrefs.getBoolean(KEY_ENABLED, true);
+ }
+
+ @Override
+ public void observe() {
+ if (mObserving) {
+ return;
+ }
+ mObserving = true;
+ mContext.getContentResolver().registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED), false, this,
+ UserHandle.USER_ALL);
+ update();
+ }
+
+ @Override
+ public void unobserve() {
+ if (mObserving) {
+ mObserving = false;
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+
+ @Override
+ public void update() {
+ }
+ }
+
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -447,7 +516,10 @@ public class KeyguardViewMediator extends SystemUI {
break;
case READY:
synchronized (this) {
- if (mShowing) {
+ if ((mInternallyDisabled || isProfileDisablingKeyguard())
+ && !mUpdateMonitor.isSimPinSecure()) {
+ hideLocked();
+ } else if (mShowing) {
resetStateLocked();
}
}
@@ -555,8 +627,12 @@ public class KeyguardViewMediator extends SystemUI {
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
-
mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
+ mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DISMISS_KEYGUARD_SECURELY_ACTION),
+ android.Manifest.permission.CONTROL_KEYGUARD, null);
+ mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(KEYGUARD_SERVICE_ACTION_STATE_CHANGE),
+ android.Manifest.permission.CONTROL_KEYGUARD, null);
+ mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED));
mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);
@@ -608,6 +684,25 @@ public class KeyguardViewMediator extends SystemUI {
mHideAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.lock_screen_behind_enter);
+
+ mSettingsObserver = new LockscreenEnabledSettingsObserver(mContext, new Handler()) {
+ @Override
+ public void update() {
+ boolean newDisabledState = CMSettings.Secure.getIntForUser(mContext.getContentResolver(),
+ CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED,
+ getPersistedDefaultOldSetting() ? 1 : 0,
+ UserHandle.USER_CURRENT) == 0;
+
+ synchronized (KeyguardViewMediator.this) {
+ if (mKeyguardBound) {
+ if (newDisabledState != mInternallyDisabled) {
+ // it was updated,
+ setKeyguardEnabledInternal(!newDisabledState);
+ }
+ }
+ }
+ }
+ };
}
@Override
@@ -662,7 +757,7 @@ public class KeyguardViewMediator extends SystemUI {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
mExitSecureCallback = null;
- if (!mExternallyEnabled) {
+ if (!mInternallyDisabled && !mExternallyEnabled) {
hideLocked();
}
} else if (mShowing) {
@@ -762,6 +857,10 @@ public class KeyguardViewMediator extends SystemUI {
mDelayedShowingSequence++;
}
+ public boolean isKeyguardBound() {
+ return mKeyguardBound;
+ }
+
/**
* Let's us know when the device is waking up.
*/
@@ -793,7 +892,7 @@ public class KeyguardViewMediator extends SystemUI {
}
private void maybeSendUserPresentBroadcast() {
- if (mSystemReady && mLockPatternUtils.isLockScreenDisabled(
+ if (mSystemReady && isKeyguardDisabled(
KeyguardUpdateMonitor.getCurrentUser())) {
// Lock screen is disabled because the user has set the preference to "None".
// In this case, send out ACTION_USER_PRESENT here instead of in
@@ -802,6 +901,26 @@ public class KeyguardViewMediator extends SystemUI {
}
}
+ private boolean isKeyguardDisabled(int userId) {
+ if (!mExternallyEnabled) {
+ if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled externally");
+ return true;
+ }
+ if (mLockPatternUtils.isLockScreenDisabled(userId)) {
+ if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by setting");
+ return true;
+ }
+ if (mInternallyDisabled) {
+ if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled internally");
+ return true;
+ }
+ if (isProfileDisablingKeyguard()) {
+ if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by profile");
+ return true;
+ }
+ return false;
+ }
+
/**
* A dream started. We should lock after the usual screen-off lock timeout but only
* if there is a secure lock pattern.
@@ -827,6 +946,33 @@ public class KeyguardViewMediator extends SystemUI {
}
/**
+ * Set the internal keyguard enabled state. This allows SystemUI to disable the lockscreen,
+ * overriding any apps.
+ * @param enabled
+ */
+ public void setKeyguardEnabledInternal(boolean enabled) {
+ mInternallyDisabled = !enabled;
+ if (!mUpdateMonitor.isSimPinSecure()) {
+ // disable when sim is ready
+ return;
+ }
+ setKeyguardEnabled(enabled);
+ if (mInternallyDisabled) {
+ mNeedToReshowWhenReenabled = false;
+ }
+ }
+
+ public boolean getKeyguardEnabledInternal() {
+ return !mInternallyDisabled;
+ }
+
+ public boolean isProfileDisablingKeyguard() {
+ final Profile activeProfile = ProfileManager.getInstance(mContext).getActiveProfile();
+ return activeProfile != null
+ && activeProfile.getScreenLockMode().getValue() == Profile.LockMode.DISABLE;
+ }
+
+ /**
* Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide
* a way for external stuff to override normal keyguard behavior. For instance
* the phone app disables the keyguard when it receives incoming calls.
@@ -834,8 +980,14 @@ public class KeyguardViewMediator extends SystemUI {
public void setKeyguardEnabled(boolean enabled) {
synchronized (this) {
if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
-
mExternallyEnabled = enabled;
+ if (mInternallyDisabled
+ && enabled
+ && !lockscreenEnforcedByDevicePolicy()) {
+ // if keyguard is forcefully disabled internally (by lock screen tile), don't allow
+ // it to be enabled externally, unless the device policy manager says so.
+ return;
+ }
if (!enabled && mShowing) {
if (mExitSecureCallback != null) {
@@ -848,7 +1000,7 @@ public class KeyguardViewMediator extends SystemUI {
// hiding keyguard that is showing, remember to reshow later
if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
+ "disabling status bar expansion");
- mNeedToReshowWhenReenabled = true;
+ mNeedToReshowWhenReenabled = !isProfileDisablingKeyguard();
updateInputRestrictedLocked();
hideLocked();
} else if (enabled && mNeedToReshowWhenReenabled) {
@@ -1028,22 +1180,6 @@ public class KeyguardViewMediator extends SystemUI {
* Enable the keyguard if the settings are appropriate.
*/
private void doKeyguardLocked(Bundle options) {
- // if another app is disabling us, don't show
- if (!mExternallyEnabled) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
-
- // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
- // for an occasional ugly flicker in this situation:
- // 1) receive a call with the screen on (no keyguard) or make a call
- // 2) screen times out
- // 3) user hits key to turn screen back on
- // instead, we reenable the keyguard when we know the screen is off and the call
- // ends (see the broadcast receiver below)
- // TODO: clean this up when we have better support at the window manager level
- // for apps that wish to be on top of the keyguard
- return;
- }
-
// if the keyguard is already showing, don't bother
if (mStatusBarKeyguardViewManager.isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
@@ -1066,9 +1202,30 @@ public class KeyguardViewMediator extends SystemUI {
return;
}
- if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
+ // if another app is disabling us, don't show
+ if (!mExternallyEnabled && !lockedOrMissing) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
+
+ // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
+ // for an occasional ugly flicker in this situation:
+ // 1) receive a call with the screen on (no keyguard) or make a call
+ // 2) screen times out
+ // 3) user hits key to turn screen back on
+ // instead, we reenable the keyguard when we know the screen is off and the call
+ // ends (see the broadcast receiver below)
+ // TODO: clean this up when we have better support at the window manager level
+ // for apps that wish to be on top of the keyguard
+ return;
+ }
+
+ if (isKeyguardDisabled(KeyguardUpdateMonitor.getCurrentUser())
&& !lockedOrMissing) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+ // update state
+ setShowingLocked(false);
+ updateActivityLockScreenState();
+ adjustStatusBarLocked();
+ userActivity();
return;
}
@@ -1089,6 +1246,15 @@ public class KeyguardViewMediator extends SystemUI {
return !mUpdateMonitor.isDeviceProvisioned() && !isSecure();
}
+ public boolean lockscreenEnforcedByDevicePolicy() {
+ DevicePolicyManager dpm = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (dpm != null) {
+ return dpm.requireSecureKeyguard();
+ }
+ return false;
+ }
+
/**
* Dismiss the keyguard through the security layers.
*/
@@ -1203,6 +1369,20 @@ public class KeyguardViewMediator extends SystemUI {
doKeyguardLocked(null);
}
}
+ } else if (DISMISS_KEYGUARD_SECURELY_ACTION.equals(intent.getAction())) {
+ synchronized (KeyguardViewMediator.this) {
+ dismiss();
+ }
+ } else if (KEYGUARD_SERVICE_ACTION_STATE_CHANGE.equals(intent.getAction())) {
+ mKeyguardBound = intent.getBooleanExtra(KEYGUARD_SERVICE_EXTRA_ACTIVE, false);
+ if (mKeyguardBound) {
+ mSettingsObserver.observe();
+ } else {
+ mSettingsObserver.unobserve();
+ }
+ } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction())) {
+ mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+ if (DEBUG) Log.d(TAG, "phone state change, new state: " + mPhoneState);
}
}
};
@@ -1368,6 +1548,10 @@ public class KeyguardViewMediator extends SystemUI {
private void playSound(int soundId) {
if (soundId == 0) return;
+ if (mInternallyDisabled) {
+ Log.d(TAG, "suppressing lock screen sounds because it is disabled");
+ return;
+ }
final ContentResolver cr = mContext.getContentResolver();
if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
@@ -1437,7 +1621,8 @@ public class KeyguardViewMediator extends SystemUI {
ActivityManagerNative.getDefault().keyguardGoingAway(
mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
|| mWakeAndUnlocking,
- mStatusBarKeyguardViewManager.isGoingToNotificationShade());
+ mStatusBarKeyguardViewManager.isGoingToNotificationShade(),
+ mStatusBarKeyguardViewManager.isKeyguardShowingMedia());
} catch (RemoteException e) {
Log.e(TAG, "Error while calling WindowManager", e);
}
@@ -1497,7 +1682,9 @@ public class KeyguardViewMediator extends SystemUI {
// only play "unlock" noises if not on a call (since the incall UI
// disables the keyguard)
if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
- playSounds(false);
+ if (mShowing && mDeviceInteractive) {
+ playSounds(false);
+ }
}
setShowingLocked(false);
@@ -1550,7 +1737,7 @@ public class KeyguardViewMediator extends SystemUI {
private void handleReset() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleReset");
- mStatusBarKeyguardViewManager.reset();
+ mStatusBarKeyguardViewManager.reset(false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 9459740..e519e34 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -16,23 +16,30 @@
package com.android.systemui.power;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import cyanogenmod.providers.CMSettings;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -57,6 +64,9 @@ public class PowerUI extends SystemUI {
private long mScreenOffTime = -1;
+ // For filtering ACTION_POWER_DISCONNECTED on boot
+ boolean mIgnoreFirstPowerEvent = true;
+
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
@@ -140,6 +150,8 @@ public class PowerUI extends SystemUI {
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
+ filter.addAction(Intent.ACTION_POWER_CONNECTED);
+ filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
mContext.registerReceiver(this, filter, null, mHandler);
updateSaverMode();
}
@@ -165,6 +177,10 @@ public class PowerUI extends SystemUI {
final boolean plugged = mPlugType != 0;
final boolean oldPlugged = oldPlugType != 0;
+ if (mIgnoreFirstPowerEvent && plugged) {
+ mIgnoreFirstPowerEvent = false;
+ }
+
int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
int bucket = findBatteryLevelBucket(mBatteryLevel);
@@ -214,12 +230,44 @@ public class PowerUI extends SystemUI {
updateSaverMode();
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGING.equals(action)) {
setSaverMode(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
+ } else if (Intent.ACTION_POWER_CONNECTED.equals(action)
+ || Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
+ final ContentResolver cr = mContext.getContentResolver();
+
+ if (mIgnoreFirstPowerEvent) {
+ mIgnoreFirstPowerEvent = false;
+ } else {
+ if (Settings.Global.getInt(cr,
+ Settings.Global.CHARGING_SOUNDS_ENABLED, 0) == 1) {
+ playPowerNotificationSound();
+ }
+ }
} else {
Slog.w(TAG, "unknown intent: " + intent);
}
}
};
+ void playPowerNotificationSound() {
+ final ContentResolver cr = mContext.getContentResolver();
+ final String soundPath =
+ CMSettings.Global.getString(cr, CMSettings.Global.POWER_NOTIFICATIONS_RINGTONE);
+
+ if (soundPath != null) {
+ Ringtone powerRingtone = RingtoneManager.getRingtone(mContext, Uri.parse(soundPath));
+ if (powerRingtone != null) {
+ powerRingtone.play();
+ }
+ }
+ if (CMSettings.Global.getInt(cr,
+ CMSettings.Global.POWER_NOTIFICATIONS_VIBRATE, 0) == 1) {
+ Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+ if (vibrator != null) {
+ vibrator.vibrate(250);
+ }
+ }
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mLowBatteryAlertCloseLevel=");
pw.println(mLowBatteryAlertCloseLevel);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java b/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java
new file mode 100644
index 0000000..d2d13ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs;
+
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import cyanogenmod.providers.CMSettings;
+
+public class QSBooleanSettingRow extends LinearLayout implements View.OnClickListener {
+
+ private static final String TAG = "QSSettingRow";
+
+ public static final int TABLE_SYSTEM = 0;
+ public static final int TABLE_GLOBAL = 1;
+ public static final int TABLE_SECURE = 2;
+
+ public static final int TABLE_CM_SYSTEM = 3;
+ public static final int TABLE_CM_GLOBAL = 4;
+ public static final int TABLE_CM_SECURE = 5;
+
+ int mWhichTable;
+ String mTitle;
+ String mKey;
+ private TextView mText;
+ private Switch mSwitch;
+ private int mDefaultValue;
+
+ public QSBooleanSettingRow(Context context) {
+ this(context, null);
+ }
+
+ public QSBooleanSettingRow(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public QSBooleanSettingRow(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public QSBooleanSettingRow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ View.inflate(context, R.layout.qs_settings_row, this);
+
+ setOrientation(HORIZONTAL);
+ setClickable(true);
+ setOnClickListener(this);
+
+ mText = (TextView) findViewById(R.id.title);
+ mSwitch = (Switch) findViewById(R.id.switcher);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.QuickSettingsRow,
+ defStyleAttr, defStyleRes);
+
+ mWhichTable = a.getInteger(R.styleable.QuickSettingsRow_table, -1);
+
+ mTitle = a.getString(R.styleable.QuickSettingsRow_android_title);
+ mKey = a.getString(R.styleable.QuickSettingsRow_android_key);
+ mDefaultValue = a.getInt(R.styleable.QuickSettingsRow_defaultValue, 0);
+
+ if (mText != null) {
+ mText.setText(mTitle);
+ mText.setClickable(false);
+ mText.setFocusable(false);
+ }
+
+ if (mSwitch != null) {
+ mSwitch.setClickable(false);
+ mSwitch.setFocusable(false);
+ mSwitch.setChecked(getCurrent());
+ mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (false) Log.d(TAG, "onCheckedChanged() called with "
+ + "buttonView = [" + buttonView + "], isChecked = [" + isChecked
+ + "] and table: " + mWhichTable + ", and key: " + mKey);
+ applyChange(isChecked);
+ }
+ });
+ }
+
+ a.recycle();
+ }
+
+ private void applyChange(boolean value) {
+ ContentResolver cr = getContext().getContentResolver();
+ switch (mWhichTable) {
+ case TABLE_GLOBAL:
+ Settings.Global.putInt(cr, mKey, value ? 1 : 0);
+ break;
+ case TABLE_SECURE:
+ Settings.Secure.putInt(cr, mKey, value ? 1 : 0);
+ break;
+ case TABLE_SYSTEM:
+ Settings.System.putInt(cr, mKey, value ? 1 : 0);
+ break;
+ case TABLE_CM_GLOBAL:
+ CMSettings.Global.putInt(cr, mKey, value ? 1 : 0);
+ break;
+ case TABLE_CM_SECURE:
+ CMSettings.Secure.putInt(cr, mKey, value ? 1 : 0);
+ break;
+ case TABLE_CM_SYSTEM:
+ CMSettings.System.putInt(cr, mKey, value ? 1 : 0);
+ break;
+ }
+ }
+
+ private boolean getCurrent() {
+ ContentResolver cr = getContext().getContentResolver();
+ int ret = 0;
+ switch (mWhichTable) {
+ case TABLE_GLOBAL:
+ ret = Settings.Global.getInt(cr, mKey, mDefaultValue);
+ break;
+ case TABLE_SECURE:
+ ret = Settings.Secure.getInt(cr, mKey, mDefaultValue);
+ break;
+ case TABLE_SYSTEM:
+ ret = Settings.System.getInt(cr, mKey, mDefaultValue);
+ break;
+ case TABLE_CM_GLOBAL:
+ ret = CMSettings.Global.getInt(cr, mKey, mDefaultValue);
+ break;
+ case TABLE_CM_SECURE:
+ ret = CMSettings.Secure.getInt(cr, mKey, mDefaultValue);
+ break;
+ case TABLE_CM_SYSTEM:
+ ret = CMSettings.System.getInt(cr, mKey, mDefaultValue);
+ break;
+ }
+ return ret == 1;
+ }
+
+ @Override
+ public void onClick(View v) {
+ mSwitch.setChecked(!mSwitch.isChecked());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index cfe8d07..74f4cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -63,7 +63,7 @@ public class QSContainer extends FrameLayout {
*/
public int getDesiredHeight() {
if (mQSPanel.isClosingDetail()) {
- return mQSPanel.getGridHeight() + getPaddingTop() + getPaddingBottom();
+ return mQSPanel.getGridHeight() + getPaddingBottom();
} else {
return getMeasuredHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
index a318efc..8b89a65 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
@@ -36,6 +36,10 @@ public class QSDetailClipper {
mBackground = (TransitionDrawable) detail.getBackground();
}
+ public boolean isAnimating() {
+ return mAnimator != null && mAnimator.isRunning();
+ }
+
public void animateCircularClip(int x, int y, boolean in, AnimatorListener listener) {
if (mAnimator != null) {
mAnimator.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsGrid.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsGrid.java
new file mode 100644
index 0000000..07e01e4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsGrid.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2015, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+import android.widget.BaseAdapter;
+
+import cyanogenmod.app.CustomTile;
+
+import com.android.systemui.qs.tiles.UserDetailItemView;
+import com.android.systemui.R;
+
+/**
+ * Quick settings common detail grid view with circular items.
+ */
+public class QSDetailItemsGrid extends PseudoGridView {
+ private static final String TAG = "QSDetailItemsGrid";
+ private QSDetailItemsGridAdapter mDetailItemsGridAdapter;
+
+ public QSDetailItemsGrid(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public static QSDetailItemsGrid inflate(Context context, ViewGroup parent, boolean attach) {
+ return (QSDetailItemsGrid) LayoutInflater.from(context).inflate(
+ R.layout.qs_detail_items_grid, parent, attach);
+ }
+
+ public QSDetailItemsGridAdapter createAndSetAdapter(String externalPackage,
+ CustomTile.ExpandedItem[] items) {
+ mDetailItemsGridAdapter = new QSDetailItemsGridAdapter(externalPackage, mContext, items);
+ ViewGroupAdapterBridge.link(this, mDetailItemsGridAdapter);
+ return mDetailItemsGridAdapter;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ setOnTouchListener(new OnTouchListener() {
+ // Setting on Touch Listener for handling the touch inside ScrollView
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ // Disallow the touch request for parent scroll on touch of child view
+ v.getParent().requestDisallowInterceptTouchEvent(true);
+ return false;
+ }
+ });
+ }
+
+ public static class QSDetailItemsGridAdapter extends BaseAdapter implements OnClickListener {
+ private String mPkg;
+ private Context mContext;
+ private CustomTile.ExpandedItem[] mItems;
+ private OnPseudoGriditemClickListener mOnPseudoGridItemClickListener;
+
+ public interface OnPseudoGriditemClickListener {
+ void onPsuedoGridItemClick(View view, CustomTile.ExpandedItem item);
+ }
+
+ public QSDetailItemsGridAdapter(String packageName,
+ Context context, CustomTile.ExpandedItem[] items) {
+ mPkg = packageName;
+ mContext = context;
+ mItems = items;
+ }
+
+ public void setOnPseudoGridItemClickListener(OnPseudoGriditemClickListener
+ onPseudoGridItemClickListener) {
+ mOnPseudoGridItemClickListener = onPseudoGridItemClickListener;
+ }
+
+ @Override
+ public int getCount() {
+ return mItems.length;
+ }
+
+ @Override
+ public CustomTile.ExpandedItem getItem(int position) {
+ return mItems[position];
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int i, View convertView, ViewGroup parent) {
+ UserDetailItemView v = UserDetailItemView.convertOrInflate(
+ mContext, convertView, parent);
+ CustomTile.ExpandedItem item = getItem(i);
+ Drawable d = null;
+ if (item.itemDrawableResourceId != 0 && item.itemBitmapResource == null) {
+ try {
+ d = getPackageContext(mPkg, mContext).getResources()
+ .getDrawable(item.itemDrawableResourceId);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + mPkg +
+ " id=" + item.itemDrawableResourceId, t);
+ }
+ } else {
+ d = new BitmapDrawable(mContext.getResources(), item.itemBitmapResource);
+ }
+ if (v != convertView) {
+ v.setOnClickListener(this);
+ }
+ String name = item.itemTitle;
+ v.setActivated(true);
+ v.bind(name, d);
+ v.setTag(item);
+ return v;
+ }
+
+ @Override
+ public void onClick(View view) {
+ CustomTile.ExpandedItem item = (CustomTile.ExpandedItem) view.getTag();
+ mOnPseudoGridItemClickListener.onPsuedoGridItemClick(view, item);
+ }
+ }
+
+ private static Context getPackageContext(String pkg, Context context) {
+ Context packageContext;
+ try {
+ packageContext = context.createPackageContext(pkg, 0);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + pkg, t);
+ return null;
+ }
+ return packageContext;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java
new file mode 100644
index 0000000..578a983
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import android.widget.TextView;
+import com.android.systemui.R;
+
+import cyanogenmod.app.CustomTile;
+
+import java.util.List;
+
+/**
+ * Quick settings common detail list view with line items.
+ */
+public class QSDetailItemsList extends LinearLayout {
+ private static final String TAG = "QSDetailItemsList";
+
+ private ListView mListView;
+ private View mEmpty;
+ private TextView mEmptyText;
+ private ImageView mEmptyIcon;
+
+ public QSDetailItemsList(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ mTag = TAG;
+ }
+
+ public static QSDetailItemsList convertOrInflate(Context context,
+ View convertView, ViewGroup parent) {
+ if (convertView instanceof QSDetailItemsList) {
+ return (QSDetailItemsList) convertView;
+ }
+ LayoutInflater inflater = LayoutInflater.from(context);
+ return (QSDetailItemsList) inflater.inflate(R.layout.qs_detail_items_list, parent, false);
+ }
+
+ public void setAdapter(ListAdapter adapter) {
+ mListView.setAdapter(adapter);
+ }
+
+ public ListView getListView() {
+ return mListView;
+ }
+
+ public void setEmptyState(int icon, int text) {
+ mEmptyIcon.setImageResource(icon);
+ mEmptyText.setText(text);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mListView = (ListView) findViewById(android.R.id.list);
+ mListView.setOnTouchListener(new OnTouchListener() {
+ // Setting on Touch Listener for handling the touch inside ScrollView
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ // Disallow the touch request for parent scroll on touch of child view
+ v.getParent().requestDisallowInterceptTouchEvent(true);
+ return false;
+ }
+ });
+ mEmpty = findViewById(android.R.id.empty);
+ mEmpty.setVisibility(GONE);
+ mEmptyText = (TextView) mEmpty.findViewById(android.R.id.title);
+ mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
+ mListView.setEmptyView(mEmpty);
+ }
+
+ public static class QSCustomDetailListAdapter extends ArrayAdapter<CustomTile.ExpandedItem> {
+ private String mPackage;
+
+ public QSCustomDetailListAdapter(String externalPackage, Context context,
+ List<CustomTile.ExpandedItem> objects) {
+ super(context, R.layout.qs_detail_item, objects);
+ mPackage = externalPackage;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ LinearLayout view = (LinearLayout) inflater.inflate(
+ R.layout.qs_detail_item, parent, false);
+
+ final CustomTile.ExpandedItem item = getItem(position);
+ Drawable d = null;
+ if (item.itemDrawableResourceId != 0 && item.itemBitmapResource == null) {
+ try {
+ d = getPackageContext(mPackage, getContext()).getResources()
+ .getDrawable(item.itemDrawableResourceId);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + mPackage +
+ " id=" + item.itemDrawableResourceId, t);
+ }
+ } else {
+ d = new BitmapDrawable(getContext().getResources(), item.itemBitmapResource);
+ }
+ final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
+ iv.setImageDrawable(d);
+ iv.getOverlay().clear();
+ //TODO: hide icon for the time being until the API supports granular item manipulation
+ final ImageView iv2 = (ImageView) view.findViewById(android.R.id.icon2);
+ iv2.setVisibility(View.GONE);
+ final TextView title = (TextView) view.findViewById(android.R.id.title);
+ title.setText(item.itemTitle);
+ final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+ final boolean twoLines = !TextUtils.isEmpty(item.itemSummary);
+ title.setMaxLines(twoLines ? 1 : 2);
+ summary.setVisibility(twoLines ? VISIBLE : GONE);
+ summary.setText(twoLines ? item.itemSummary : null);
+ view.setMinimumHeight(getContext().getResources().getDimensionPixelSize(
+ twoLines ? R.dimen.qs_detail_item_height_twoline
+ : R.dimen.qs_detail_item_height));
+ return view;
+ }
+ }
+
+ private static Context getPackageContext(String pkg, Context context) {
+ Context packageContext;
+ try {
+ packageContext = context.createPackageContext(pkg, 0);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + pkg, t);
+ return null;
+ }
+ return packageContext;
+ }
+
+ public static class QSDetailListAdapter extends ArrayAdapter<QSDetailItems.Item> {
+ private QSDetailItems.Callback mCallback;
+
+ public QSDetailListAdapter(Context context, List<QSDetailItems.Item> objects) {
+ super(context, R.layout.qs_detail_item, objects);
+ }
+
+ public void setCallback(QSDetailItems.Callback cb) {
+ mCallback = cb;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ LinearLayout view = (LinearLayout) inflater.inflate(
+ R.layout.qs_detail_item, parent, false);
+
+ view.setClickable(false); // let list view handle this
+
+ final QSDetailItems.Item item = getItem(position);
+
+ final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
+ iv.setImageResource(item.icon);
+ iv.getOverlay().clear();
+ if (item.overlay != null) {
+ item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
+ item.overlay.getIntrinsicHeight());
+ iv.getOverlay().add(item.overlay);
+ }
+ final TextView title = (TextView) view.findViewById(android.R.id.title);
+ title.setText(item.line1);
+ final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+ final boolean twoLines = !TextUtils.isEmpty(item.line2);
+ title.setMaxLines(twoLines ? 1 : 2);
+ summary.setVisibility(twoLines ? VISIBLE : GONE);
+ summary.setText(twoLines ? item.line2 : null);
+ view.setMinimumHeight(getContext().getResources().getDimensionPixelSize(
+ twoLines ? R.dimen.qs_detail_item_height_twoline : R.dimen.qs_detail_item_height));
+
+ final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
+ disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
+ disconnect.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemDisconnect(item);
+ }
+ }
+ });
+ return view;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java
new file mode 100644
index 0000000..86fc49e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java
@@ -0,0 +1,2148 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.DragEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.EditText;
+import android.widget.ExpandableListView;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.FontSizeUtils;
+import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.qs.tiles.EditTile;
+import com.android.systemui.qs.tiles.IntentTile;
+import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.settings.ToggleSlider;
+import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.tuner.QsTuner;
+import com.viewpagerindicator.CirclePageIndicator;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+import org.cyanogenmod.internal.util.QSUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+public class QSDragPanel extends QSPanel implements View.OnDragListener, View.OnLongClickListener {
+
+ private static final String TAG = "QSDragPanel";
+
+ public static final boolean DEBUG_TILES = false;
+ public static final boolean DEBUG_DRAG = false;
+
+ private static final int MAX_ROW_COUNT = 3;
+
+ // how long to wait before resetting the page
+ private static final int PAGE_RESET_DELAY = 10000;
+
+ protected final ArrayList<QSPage> mPages = new ArrayList<>();
+
+ protected QSViewPager mViewPager;
+ protected PagerAdapter mPagerAdapter;
+ QSPanelTopView mQsPanelTop;
+ CirclePageIndicator mPageIndicator;
+ private int mPageIndicatorHeight;
+
+ private TextView mDetailRemoveButton;
+ private DragTileRecord mDraggingRecord, mLastDragRecord;
+ private boolean mEditing;
+ private boolean mDragging;
+ private float mLastTouchLocationX, mLastTouchLocationY;
+ private int mLocationHits;
+ private int mLastLeftShift = -1;
+ private int mLastRightShift = -1;
+ private boolean mRestored;
+ private boolean mRestoring;
+ // whether the current view we are dragging in has shifted tiles
+ private boolean mMovedByLocation = false;
+
+ protected boolean mFirstRowLarge = true;
+ private SettingsObserver mSettingsObserver;
+
+ List<TileRecord> mCurrentlyAnimating
+ = Collections.synchronizedList(new ArrayList<TileRecord>());
+
+ private Point mDisplaySize;
+ private int[] mTmpLoc;
+
+ private Runnable mResetPage = new Runnable() {
+ @Override
+ public void run() {
+ if (!mListening) {
+ // only reset when the user isn't interacting at all
+ mViewPager.setCurrentItem(0);
+ }
+ }
+ };
+
+ public QSDragPanel(Context context) {
+ this(context, null);
+ }
+
+ public QSDragPanel(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void setupViews() {
+ updateResources();
+
+ mDetail = LayoutInflater.from(mContext).inflate(R.layout.qs_detail, this, false);
+ mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
+ mDetailRemoveButton = (TextView) mDetail.findViewById(android.R.id.button3);
+ mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
+ mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
+ updateDetailText();
+ mDetail.setVisibility(GONE);
+ mDetail.setClickable(true);
+
+ mQsPanelTop = (QSPanelTopView) LayoutInflater.from(mContext).inflate(R.layout.qs_tile_top,
+ this, false);
+
+ mBrightnessView = mQsPanelTop.getBrightnessView();
+ mFooter = new QSFooter(this, mContext);
+
+ // add target click listener
+ mQsPanelTop.getAddTarget().setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ TilesListAdapter adapter = new TilesListAdapter(mContext, QSDragPanel.this);
+ showDetailAdapter(true, adapter, v.getLocationOnScreen());
+ mDetail.bringToFront();
+ }
+ });
+ mViewPager = new QSViewPager(getContext());
+ mViewPager.setDragPanel(this);
+
+ mPageIndicator = new CirclePageIndicator(getContext());
+ addView(mDetail);
+ addView(mQsPanelTop);
+ addView(mViewPager);
+ addView(mPageIndicator);
+ addView(mFooter.getView());
+
+ mClipper = new QSDetailClipper(mDetail);
+
+ mBrightnessController = new BrightnessController(getContext(),
+ (ImageView) mQsPanelTop.getBrightnessView().findViewById(R.id.brightness_icon),
+ (ToggleSlider) mQsPanelTop.getBrightnessView().findViewById(R.id.brightness_slider));
+
+ mDetailDoneButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ announceForAccessibility(
+ mContext.getString(R.string.accessibility_desc_quick_settings));
+ closeDetail();
+ }
+ });
+
+ mPagerAdapter = new PagerAdapter() {
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ if (DEBUG_TILES) {
+ Log.d(TAG, "instantiateItem() called with "
+ + "container = [" + container + "], position = [" + position + "]");
+ }
+
+ if (mEditing && position == 0) {
+ QSSettings qss = (QSSettings)
+ View.inflate(container.getContext(), R.layout.qs_settings, null);
+ qss.setHost(mHost);
+ container.addView(qss, 0);
+ return qss;
+ } else {
+ final int adjustedPosition = mEditing ? position - 1 : position;
+ QSPage page = mPages.get(adjustedPosition);
+ if (!page.isAttachedToWindow()) {
+ container.addView(page);
+ }
+ return page;
+ }
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ if (DEBUG_TILES) {
+ Log.d(TAG, "destroyItem() called with " + "container = ["
+ + container + "], position = [" + position + "], object = ["
+ + object + "]");
+ }
+ if (object instanceof View) {
+ container.removeView((View) object);
+ }
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ if (object instanceof QSPage) {
+ if (mEditing != ((QSPage) object).getAdapterEditingState()) {
+ // position of item changes when we set change the editing mode,
+ // sync it and send the new position
+ ((QSPage) object).setAdapterEditingState(mEditing);
+
+ // calculate new position
+ int indexOf = ((QSPage) object).getPageIndex();
+ if (mEditing) return indexOf + 1;
+ else return indexOf;
+
+ } else if (!mPages.contains(object) && !mDragging) {
+ // only return none if we aren't dragging (object may be removed from
+ // the records array temporarily and we might think we have less pages,
+ // we don't want to prematurely remove this page
+ return POSITION_NONE;
+ } else {
+
+ return POSITION_UNCHANGED;
+ }
+
+ } else if (object instanceof QSSettings) {
+ if (((QSSettings) object).getAdapterEditingState() != mEditing) {
+ ((QSSettings) object).setAdapterEditingState(mEditing);
+ if (mEditing) return 0 /* locked at position 0 */;
+ else return POSITION_NONE;
+ } else {
+ return POSITION_UNCHANGED;
+ }
+ }
+ return super.getItemPosition(object);
+ }
+
+ @Override
+ public int getCount() {
+ final int qsPages = Math.max(getCurrentMaxPageCount(), 1);
+
+ if (mPages != null && qsPages > mPages.size()) {
+ for(int i = mPages.size(); i < qsPages; i++) {
+ mPages.add(i, new QSPage(mViewPager.getContext(), QSDragPanel.this, i));
+ }
+ }
+
+ if (mEditing) return qsPages + 1;
+ return qsPages;
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+ };
+ mViewPager.setAdapter(mPagerAdapter);
+
+ mPageIndicator.setViewPager(mViewPager);
+ mPageIndicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset,
+ int positionOffsetPixels) {
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "onPageScrolled() called with " + "position = ["
+ + position + "], positionOffset = [" + positionOffset
+ + "], positionOffsetPixels = [" + positionOffsetPixels + "]");
+ }
+
+ if (mEditing) {
+ float targetTranslationX = 0;
+
+ // targetTranslationX = where it's supposed to be - diff
+ int homeLocation = mViewPager.getMeasuredWidth();
+
+ // how far away from homeLocation is the scroll?
+ if (positionOffsetPixels < homeLocation
+ && position == 0) {
+ targetTranslationX = homeLocation - positionOffsetPixels;
+ }
+ mQsPanelTop.setTranslationX(targetTranslationX);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if (mDragging && position != mDraggingRecord.page
+ && !mViewPager.isFakeDragging() && !mRestoring) {
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "moving drag record to page: " + position);
+ }
+
+ // remove it from the previous page and add it here
+ final QSPage sourceP = getPage(mDraggingRecord.page);
+ final QSPage targetP = getPage(position);
+
+ sourceP.removeView(mDraggingRecord.tileView);
+ mDraggingRecord.page = position;
+ targetP.addView(mDraggingRecord.tileView);
+
+ // set coords off screen until we're ready to place it
+ mDraggingRecord.tileView.setX(-mDraggingRecord.tileView.getMeasuredWidth());
+ mDraggingRecord.tileView.setY(-mDraggingRecord.tileView.getMeasuredHeight());
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+ });
+ mViewPager.setOverScrollMode(OVER_SCROLL_NEVER);
+
+ setClipChildren(false);
+
+ mSettingsObserver = new SettingsObserver(new Handler());
+
+ mViewPager.setOnDragListener(QSDragPanel.this);
+ mQsPanelTop.setOnDragListener(QSDragPanel.this);
+ mPageIndicator.setOnDragListener(QSDragPanel.this);
+ setOnDragListener(QSDragPanel.this);
+
+ mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return mClipper.isAnimating() || mEditing;
+ }
+
+ @Override
+ public void setBrightnessMirror(BrightnessMirrorController c) {
+ super.onFinishInflate();
+ ToggleSlider brightnessSlider =
+ (ToggleSlider) mQsPanelTop.findViewById(R.id.brightness_slider);
+ ToggleSlider mirror = (ToggleSlider) c.getMirror().findViewById(R.id.brightness_slider);
+ brightnessSlider.setMirror(mirror);
+ brightnessSlider.setMirrorController(c);
+ }
+
+ protected void drawTile(TileRecord r, QSTile.State state) {
+ if (mEditing) {
+ state.visible = true;
+ }
+ final int visibility = state.visible ? VISIBLE : GONE;
+ setTileVisibility(r.tileView, visibility);
+ setTileEnabled(r.tileView, state.enabled);
+ r.tileView.onStateChanged(state);
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ // reset the page when inactive for a while
+ if (listening) {
+ removeCallbacks(mResetPage);
+ } else {
+ postDelayed(mResetPage, PAGE_RESET_DELAY);
+ }
+ for (TileRecord r : mRecords) {
+ r.tile.setListening(mListening);
+ }
+ mFooter.setListening(mListening);
+ mQsPanelTop.setListening(mListening);
+ if (mListening) {
+ refreshAllTiles();
+ }
+ if (mListening) {
+ mSettingsObserver.observe();
+ } else {
+ mSettingsObserver.unobserve();
+ }
+
+ if (isLaidOut() && listening && showBrightnessSlider()) {
+ mBrightnessController.registerCallbacks();
+ } else {
+ mBrightnessController.unregisterCallbacks();
+ }
+ }
+
+ private void persistRecords() {
+ // persist the new config.
+ List<String> newTiles = new ArrayList<>();
+ for (TileRecord record : mRecords) {
+ newTiles.add(mHost.getSpec(record.tile));
+ }
+ mHost.setTiles(newTiles);
+ }
+
+ public void setEditing(boolean editing) {
+ if (mEditing == editing) return;
+ final boolean isOnSettings = isOnSettingsPage();
+
+ mQsPanelTop.setEditing(editing, isOnSettings);
+ if (!editing) {
+ persistRecords();
+
+ refreshAllTiles();
+
+ mQsPanelTop.setTranslationX(0);
+ if (isOnSettings) {
+ mViewPager.setCurrentItem(1, true);
+ }
+ }
+ mEditing = editing;
+ mPagerAdapter.notifyDataSetChanged();
+
+ mPageIndicator.setEditing(editing);
+ mViewPager.setOffscreenPageLimit(mEditing ? getCurrentMaxPageCount() + 1 : 1);
+ mPagerAdapter.notifyDataSetChanged();
+
+ // clear the record state
+ for (TileRecord record : mRecords) {
+ setupRecord(record);
+ drawTile(record, record.tile.getState());
+ }
+
+ requestLayout();
+ }
+
+ protected void onStartDrag() {
+ mQsPanelTop.onStartDrag();
+ }
+
+ protected void onStopDrag() {
+ mDraggingRecord.tileView.setAlpha(1f);
+
+ mLastDragRecord = mDraggingRecord;
+ mDraggingRecord = null;
+ mDragging = false;
+ mRestored = false;
+
+ mLastLeftShift = -1;
+ mLastRightShift = -1;
+
+ mQsPanelTop.onStopDrag();
+ requestLayout();
+ }
+
+ protected View getDropTarget() {
+ return mQsPanelTop.getDropTarget();
+ }
+
+ public View getBrightnessView() {
+ return mQsPanelTop.getBrightnessView();
+ }
+
+ public boolean isEditing() {
+ return mEditing;
+ }
+
+ protected int getPagesForCount(int tileCount) {
+ if (tileCount == 0) {
+ return 1;
+ }
+ tileCount = Math.max(0, tileCount - getTilesPerPage(true));
+ // first page + rest of tiles
+ return 1 + (int) Math.ceil(tileCount / (double) getTilesPerPage(false));
+ }
+
+ protected int getCurrentMaxPageCount() {
+ int initialSize = mRecords.size();
+ return getPagesForCount(initialSize);
+ }
+
+ @Override
+ protected void updateDetailText() {
+ super.updateDetailText();
+ mDetailRemoveButton.setText(R.string.quick_settings_remove);
+ }
+
+ public void setTiles(final Collection<QSTile<?>> tilesCollection) {
+ final List<QSTile<?>> tiles = new ArrayList<>(tilesCollection);
+ if (DEBUG_TILES) {
+ Log.i(TAG, "setTiles() called with " + "tiles = ["
+ + tiles + "]");
+ }
+
+ int currentViewPagerPage = mViewPager.getCurrentItem();
+
+ if (mLastDragRecord != null && mRecords.indexOf(mLastDragRecord) == -1) {
+ // the last removed record might be stored in mLastDragRecord if we just shifted
+ // re-add it to the list so we'll clean it up below
+ mRecords.add(mLastDragRecord);
+ mLastDragRecord = null;
+ }
+
+ Map<QSTile<?>, DragTileRecord> recordMap = new ArrayMap<>();
+ ListIterator<TileRecord> iterator = mRecords.listIterator(mRecords.size());
+
+ int recordsRemoved = 0;
+ // cleanup current records
+ while (iterator.hasPrevious()) {
+ DragTileRecord dr = (DragTileRecord) iterator.previous();
+
+ if (dr.page >= 0) {
+ // clean up view
+ mPages.get(dr.page).removeView(dr.tileView);
+ }
+
+ if (tiles.contains(dr.tile)) {
+ if (DEBUG_TILES) {
+ Log.i(TAG, "caching tile: " + dr.tile);
+ }
+ recordMap.put(dr.tile, dr);
+ } else {
+ if (DEBUG_TILES) {
+ Log.i(TAG, "removing tile: " + dr.tile);
+ }
+
+ // remove record
+ iterator.remove();
+ recordsRemoved++;
+
+ if (dr.page >= getCurrentMaxPageCount() - 1) {
+ final int childCount = mPages.get(dr.page).getChildCount();
+
+ if (childCount == 0) {
+ final int currentIndex = mViewPager.getCurrentItem();
+ if (currentIndex > 0 && currentViewPagerPage == currentIndex) {
+ // if we are about to remove the page we are currently on, move back
+ currentViewPagerPage--;
+ }
+ final int pageIndex = dr.page + (mEditing ? 1 : 0);
+ mPagerAdapter.startUpdate(mViewPager);
+ mPagerAdapter.destroyItem(mViewPager, pageIndex, mPages.get(dr.page));
+ mPagerAdapter.finishUpdate(mViewPager);
+ mPagerAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+ dr.page = -1;
+ dr.destinationPage = -1;
+ }
+
+ // at this point recordMap should have all retained tiles, no new or old tiles
+ int delta = tiles.size() - recordMap.size() - recordsRemoved;
+ if (DEBUG_TILES) {
+ Log.i(TAG, "record map delta: " + delta);
+ }
+ mRecords.ensureCapacity(tiles.size());
+
+ mPagerAdapter.notifyDataSetChanged();
+
+ // even though we explicitly destroy old pages, without this call,
+ // the viewpager doesn't seem to want to pick up the fact that we have less pages
+ // and allows "empty" scrolls to the right where there is no page.
+ mViewPager.setAdapter(mPagerAdapter);
+
+ // add new tiles
+ for (int i = 0; i < tiles.size(); i++) {
+ QSTile<?> tile = tiles.get(i);
+ final int tileDestPage = getPagesForCount(i + 1) - 1;
+
+ if (DEBUG_TILES) {
+ Log.d(TAG, "tile at : " + i + ": " + tile + " to dest page: " + tileDestPage);
+ }
+ DragTileRecord record;
+ if (!recordMap.containsKey(tile)) {
+ if (DEBUG_TILES) {
+ Log.d(TAG, "tile at: " + i + " not cached, adding it to records");
+ }
+ record = makeRecord(tile);
+ record.destinationPage = tileDestPage;
+ recordMap.put(tile, record);
+ mRecords.add(i, record);
+ mPagerAdapter.notifyDataSetChanged();
+ } else {
+ record = recordMap.get(tile);
+ if (DEBUG_TILES) {
+ Log.d(TAG, "tile at : " + i + ": cached, restoring: " + record);
+ }
+ int indexOf = mRecords.indexOf(record);
+ if (indexOf != i) {
+ if (DEBUG_TILES) {
+ Log.w(TAG, "moving index of " + record + " from "
+ + indexOf + " to " + i);
+ }
+ Collections.swap(mRecords, indexOf, i);
+
+ }
+ record.destinationPage = tileDestPage;
+ }
+ if (record.page == -1) {
+ // add the view
+ mPages.get(record.destinationPage).addView(record.tileView);
+ record.page = record.destinationPage;
+ if (DEBUG_TILES) {
+ Log.d(TAG, "added view " + record);
+ }
+ }
+ }
+
+ // restore the visible page
+ mViewPager.setCurrentItem(currentViewPagerPage, false);
+
+ if (isShowingDetail()) {
+ mDetail.bringToFront();
+ }
+ mPagerAdapter.notifyDataSetChanged();
+
+ refreshAllTiles();
+ requestLayout();
+ }
+
+ private DragTileRecord makeRecord(final QSTile<?> tile) {
+ if (DEBUG_TILES) {
+ Log.d(TAG, "+++ makeRecord() called with " + "tile = [" + tile + "]");
+ }
+ final DragTileRecord r = new DragTileRecord();
+
+
+ r.tile = tile;
+ r.page = -1;
+ r.destinationPage = -1;
+ r.tileView = tile.createTileView(mContext);
+ final QSTile.Callback callback = new QSTile.Callback() {
+ @Override
+ public void onStateChanged(QSTile.State state) {
+ if (!r.openingDetail) {
+ drawTile(r, state);
+ }
+ }
+
+ @Override
+ public void onShowDetail(boolean show) {
+ showDetail(show, r);
+ }
+
+ @Override
+ public void onToggleStateChanged(boolean state) {
+ if (mDetailRecord == r) {
+ fireToggleStateChanged(state);
+ }
+ }
+
+ @Override
+ public void onScanStateChanged(boolean state) {
+ r.scanState = state;
+ if (mDetailRecord == r) {
+ fireScanStateChanged(r.scanState);
+ }
+ }
+
+ @Override
+ public void onAnnouncementRequested(CharSequence announcement) {
+ announceForAccessibility(announcement);
+ }
+ };
+ r.tile.setCallback(callback);
+ final OnClickListener click = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!mEditing || r.tile instanceof EditTile) {
+ r.tile.click();
+ }
+ }
+ };
+ final OnClickListener clickSecondary = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!mEditing) {
+ r.tile.secondaryClick();
+ }
+ }
+ };
+ final OnLongClickListener longClick = new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ if (!mEditing) {
+ r.tile.longClick();
+ } else {
+ QSDragPanel.this.onLongClick(r.tileView);
+ }
+ return true;
+ }
+ };
+ r.tileView.init(click, clickSecondary, longClick);
+ r.tile.setListening(mListening);
+ r.tile.refreshState();
+ r.tileView.setVisibility(mEditing ? View.VISIBLE : View.GONE);
+ callback.onStateChanged(r.tile.getState());
+
+ if (DEBUG_TILES) {
+ Log.d(TAG, "--- makeRecord() called with " + "tile = [" + tile + "]");
+ }
+ return r;
+ }
+
+ private void removeDraggingRecord() {
+ // what spec is this tile?
+ String spec = mHost.getSpec(mDraggingRecord.tile);
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "removing tile: " + mDraggingRecord + " with spec: " + spec);
+ }
+ onStopDrag();
+ mHost.remove(spec);
+ }
+
+ public int getTilesPerPage(boolean firstPage) {
+ if ((!mFirstRowLarge && firstPage) || !firstPage) {
+ return QSTileHost.TILES_PER_PAGE + 1;
+ }
+ return QSTileHost.TILES_PER_PAGE;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mTmpLoc = null;
+ mDisplaySize = null;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int width = MeasureSpec.getSize(widthMeasureSpec);
+
+ mQsPanelTop.measure(exactly(width), MeasureSpec.UNSPECIFIED);
+ mViewPager.measure(exactly(width), MeasureSpec.UNSPECIFIED);
+ mPageIndicator.measure(exactly(width), atMost(mPageIndicatorHeight));
+ mFooter.getView().measure(exactly(width), MeasureSpec.UNSPECIFIED);
+
+ int h = getRowTop(getCurrentMaxRow() + 1) + mPanelPaddingBottom;
+
+ if (mFooter.hasFooter()) {
+ h += mFooter.getView().getMeasuredHeight();
+ }
+ mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED);
+ if (mDetail.getMeasuredHeight() < h) {
+ mDetail.measure(exactly(width), exactly(h));
+ }
+
+ // Check if the detail view would be overflowing below the physical height of the device
+ // and cutting the content off. If it is, reduce the detail height to fit.
+ if (isShowingDetail()) {
+ if (mDisplaySize == null) {
+ mDisplaySize = new Point();
+ getDisplay().getSize(mDisplaySize);
+ }
+ if (mTmpLoc == null) {
+ mTmpLoc = new int[2];
+ mDetail.getLocationOnScreen(mTmpLoc);
+ }
+
+ final int containerTop = mTmpLoc[1];
+ final int detailBottom = containerTop + mDetail.getMeasuredHeight();
+ if (detailBottom >= mDisplaySize.y) {
+ // panel is hanging below the screen
+ final int detailMinHeight = mDisplaySize.y - containerTop;
+ mDetail.measure(exactly(width), exactly(detailMinHeight));
+ }
+ setMeasuredDimension(width, mDetail.getMeasuredHeight());
+ mGridHeight = mDetail.getMeasuredHeight();
+ } else {
+ setMeasuredDimension(width, h);
+ mGridHeight = h;
+ }
+
+ for (TileRecord record : mRecords) {
+ setupRecord(record);
+ }
+ }
+
+ private void setupRecord(TileRecord record) {
+ record.tileView.setEditing(mEditing);
+ record.tileView.setOnDragListener(mEditing ? this : null);
+ }
+
+ public static int exactly(int size) {
+ return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+ }
+
+ public static int atMost(int size) {
+ return MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+ }
+
+ @Override
+ protected void handleShowDetailTile(TileRecord r, boolean show) {
+ if (r instanceof DragTileRecord) {
+ if ((mDetailRecord != null) == show && mDetailRecord == r) return;
+
+ if (show) {
+ r.detailAdapter = r.tile.getDetailAdapter();
+ if (r.detailAdapter == null) return;
+ }
+ r.tile.setDetailListening(show);
+ int x = (int) ((DragTileRecord) r).destination.x + r.tileView.getWidth() / 2;
+ int y = mViewPager.getTop() + (int) ((DragTileRecord) r).destination.y + r.tileView.getHeight() / 2;
+ handleShowDetailImpl(r, show, x, y);
+ } else {
+ super.handleShowDetailTile(r, show);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int w = getWidth();
+
+ mQsPanelTop.layout(0, 0, w, mQsPanelTop.getMeasuredHeight());
+
+ int viewPagerBottom = mQsPanelTop.getMeasuredHeight() + mViewPager.getMeasuredHeight();
+ // view pager laid out from top of brightness view to bottom to page through settings
+ mViewPager.layout(0, 0, w, viewPagerBottom);
+
+ // layout page indicator inside viewpager inset
+ mPageIndicator.layout(0, b - mPageIndicatorHeight, w, b);
+
+ mDetail.layout(0, 0, w, mDetail.getMeasuredHeight());
+
+ if (mFooter.hasFooter()) {
+ View footer = mFooter.getView();
+ footer.layout(0, getMeasuredHeight() - footer.getMeasuredHeight(),
+ footer.getMeasuredWidth(), getMeasuredHeight());
+ }
+
+ if (!isShowingDetail() && !isClosingDetail()) {
+ mQsPanelTop.bringToFront();
+ }
+ }
+
+ protected int getRowTop(int row) {
+ int baseHeight = mQsPanelTop.getMeasuredHeight();
+ if (row <= 0) return baseHeight;
+ return baseHeight + mLargeCellHeight - mDualTileUnderlap + (row - 1) * mCellHeight;
+ }
+
+ public int getColumnCount() {
+ return mColumns;
+ }
+
+ public int getColumnCount(int page, int row, boolean smart) {
+ int cols = 0;
+ for (Record record : mRecords) {
+ if (record instanceof DragTileRecord) {
+ DragTileRecord dr = (DragTileRecord) record;
+ if (dr.tileView.getVisibility() == GONE) continue;
+ if (dr.destinationPage != page) continue;
+ if (dr.row == row) cols++;
+ }
+ }
+
+ if (smart && isEditing() && (isDragging() || mRestoring) && !isDragRecordAttached()) {
+ // if shifting tiles back, and one moved from previous page
+
+ // if it's the very last row on the last page, we should add an extra column to account
+ // for where teh dragging lastRecord would go
+ DragTileRecord lastRecord = (DragTileRecord) mRecords.get(mRecords.size() - 1);
+ if (lastRecord.destinationPage == page && lastRecord.row == row
+ && cols < getColumnCount()) {
+ cols++;
+ if (DEBUG_DRAG) {
+ boolean draggingRecordBefore = isBefore(mDraggingRecord, lastRecord);
+ Log.w(TAG, "adding another col, cols: " + cols + ", last: " + lastRecord
+ + ", drag: " + mDraggingRecord
+ + ", and dragging record before last: " + draggingRecordBefore);
+ }
+ }
+ }
+ return cols;
+ }
+
+ public int getColumnCount(int page, int row) {
+ return getColumnCount(page, row, true);
+ }
+
+ public int getCurrentMaxRow() {
+ int max = 0;
+ for (TileRecord record : mRecords) {
+ if (record.row > max) {
+ max = record.row;
+ }
+ }
+ return max;
+ }
+
+ public int getLeft(int page, int row, int col) {
+ final boolean firstRowLarge = mFirstRowLarge && page == 0 && row == 0;
+ int cols = firstRowLarge ? 2 : mColumns;
+ return getLeft(row, col, cols, firstRowLarge);
+ }
+
+ public int getLeft(int page, int row, int col, int cols) {
+ final boolean firstRowLarge = mFirstRowLarge && page == 0 && row == 0;
+ return getLeft(row, col, cols, firstRowLarge);
+ }
+
+ public int getLeft(int row, int col, int cols, boolean firstRowLarge) {
+ final int cw = row == 0 && firstRowLarge ? mLargeCellWidth : mCellWidth;
+ final int extra = (getWidth() - cw * cols) / (cols + 1);
+ int left = col * cw + (col + 1) * extra;
+ return left;
+ }
+
+ public QSPage getCurrentPage() {
+ return mPages.get(mViewPager.getCurrentItem());
+ }
+
+ public QSPage getPage(int pos) {
+ if (pos >= mPages.size()) {
+ return null;
+ }
+ return mPages.get(pos);
+ }
+
+ private TileRecord getRecord(View v) {
+ for (TileRecord record : mRecords) {
+ if (record.tileView == v) {
+ return record;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean onDrag(View v, DragEvent event) {
+ final DragTileRecord targetTile = (DragTileRecord) getRecord(v);
+ boolean originatingTileEvent = mDraggingRecord != null && v == mDraggingRecord.tileView;
+
+ final int dragRecordIndex = mRecords.indexOf(mDraggingRecord);
+ boolean dragRecordAttached = dragRecordIndex != -1;
+ switch (event.getAction()) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "ACTION_DRAG_STARTED on view: " + v);
+ }
+
+ if (originatingTileEvent) {
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "ACTION_DRAG_STARTED on target view.");
+ }
+ mRestored = false;
+ mQsPanelTop.setDropIcon(R.drawable.ic_qs_tile_delete_disable, R.color.qs_tile_trash_normal_tint);
+ }
+
+ break;
+
+ case DragEvent.ACTION_DRAG_ENTERED:
+ if (DEBUG_DRAG) {
+ if (targetTile != null) {
+ Log.v(TAG, "ACTION_DRAG_ENTERED on view with tile: " + targetTile);
+ } else {
+ Log.v(TAG, "ACTION_DRAG_ENTERED on view: " + v);
+ }
+ }
+ mLocationHits = 0;
+ mMovedByLocation = false;
+
+ if (v == mQsPanelTop) {
+ int icon, color;
+ if (mDraggingRecord.tile instanceof EditTile) {
+ // use a different warning, user can't erase this one
+ icon = R.drawable.ic_qs_tile_delete_disable_avd;
+ color = R.color.qs_tile_trash_delete_tint_warning;
+ } else {
+ icon = R.drawable.ic_qs_tile_delete_disable;
+ color = R.color.qs_tile_trash_delete_tint;
+ }
+
+ mQsPanelTop.setDropIcon(icon, color);
+ }
+
+ if (!originatingTileEvent && v != getDropTarget() && targetTile != null) {
+ if (DEBUG_DRAG) {
+ Log.e(TAG, "entered tile " + targetTile);
+ }
+ if (mCurrentlyAnimating.isEmpty()
+ && !mViewPager.isFakeDragging()
+ && !dragRecordAttached) {
+ mMovedByLocation = true;
+ shiftTiles(targetTile, true);
+ } else {
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "ignoring action enter for animating tiles and fake drags");
+ }
+ }
+ }
+
+ break;
+ case DragEvent.ACTION_DRAG_ENDED:
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "ACTION_DRAG_ENDED on view: " + v + "(tile: "
+ + targetTile + "), result: " + event.getResult());
+ }
+ if (originatingTileEvent && !event.getResult()) {
+ // view pager probably ate the event
+ restoreDraggingTilePosition(v);
+ }
+
+ break;
+
+ case DragEvent.ACTION_DROP:
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "ACTION_DROP, event loc: " + event.getX() + ", " + event.getY()
+ + " + with tile: " + targetTile + " and view: " + v);
+ }
+ mLastTouchLocationX = event.getX();
+ mLastTouchLocationY = event.getY();
+
+ if (isDropTargetEvent(event, v)) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "dropping on delete target!!");
+ }
+ if (mDraggingRecord.tile instanceof EditTile) {
+ mQsPanelTop.toast(R.string.quick_settings_cannot_delete_edit_tile);
+ restoreDraggingTilePosition(v);
+ break;
+ } else {
+ mRestored = true;
+ removeDraggingRecord();
+ }
+ } else {
+ restoreDraggingTilePosition(v);
+ }
+ break;
+
+ case DragEvent.ACTION_DRAG_EXITED:
+ if (DEBUG_DRAG) {
+ if (targetTile != null) {
+ Log.v(TAG, "ACTION_DRAG_EXITED on view with tile: " + targetTile);
+ } else {
+ Log.v(TAG, "ACTION_DRAG_EXITED on view: " + v);
+ }
+ }
+
+ if (v == mQsPanelTop) {
+ mQsPanelTop.setDropIcon(R.drawable.ic_qs_tile_delete_disable, R.color.qs_tile_trash_normal_tint);
+ }
+
+ if (originatingTileEvent
+ && mCurrentlyAnimating.isEmpty()
+ && !mViewPager.isFakeDragging()
+ && dragRecordAttached
+ && mLastLeftShift == -1) {
+
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "target: " + targetTile + ", hit mLastRightShift: "
+ + mLastRightShift + ", mLastLeftShift: "
+ + mLastLeftShift + ", dragRecordIndex: "
+ + dragRecordIndex);
+ }
+
+ // move tiles back
+ shiftTiles(mDraggingRecord, false);
+ break;
+ }
+ // fall through so exit events can trigger a left shift
+ case DragEvent.ACTION_DRAG_LOCATION:
+ mLastTouchLocationX = event.getX();
+ mLastTouchLocationY = event.getY();
+
+ // do nothing if we're animating tiles
+ if (mCurrentlyAnimating.isEmpty() && !mViewPager.isFakeDragging()) {
+ if (v == mViewPager) {
+ // do we need to change pages?
+ int x = (int) event.getX();
+ int width = mViewPager.getWidth();
+ int scrollPadding = (int) (width * QSViewPager.SCROLL_PERCENT);
+ if (x < scrollPadding) {
+ if (mViewPager.canScrollHorizontally(-1)) {
+ mViewPager.animatePagerTransition(false);
+ return true;
+ }
+ } else if (x > width - scrollPadding) {
+ if (mViewPager.canScrollHorizontally(1)) {
+ mViewPager.animatePagerTransition(true);
+ return true;
+ }
+ }
+ }
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "location hit:// target: " + targetTile
+ + ", hit mLastRightShift: " + mLastRightShift
+ + ", mLastLeftShift: " + mLastLeftShift
+ + ", dragRecordIndex: " + dragRecordIndex
+ + ", originatingTileEvent: " + originatingTileEvent
+ + ", mLocationHits: " + mLocationHits
+ + ", mMovedByLocation: " + mMovedByLocation);
+ }
+
+ if (v != getDropTarget() && targetTile != null && !dragRecordAttached) {
+ // dragging around on another tile
+ if (mLocationHits++ == 30) {
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "shifting right due to location hits.");
+ }
+ // add dragging tile to current page
+ shiftTiles(targetTile, true);
+ mMovedByLocation = true;
+ } else {
+ mLocationHits++;
+ }
+ } else if (mLastRightShift != -1 // right has shifted recently
+ && mLastLeftShift == -1 // -1 means its attached
+ && dragRecordIndex == mLastRightShift
+ && !originatingTileEvent
+ && !mMovedByLocation /* helps avoid continuous shifting */) {
+ // check if the location is on another tile/view
+ // that is not the last drag index, shift back left to revert back and
+ // potentially get ready for shifting right
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "conditions met to reverse!!!! shifting left. <<<<<<<");
+ }
+ shiftTiles((DragTileRecord) mRecords.get(mLastRightShift), false);
+ mMovedByLocation = true;
+ }
+
+ } else {
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "ignoring location event because things are animating, size: "
+ + mCurrentlyAnimating.size());
+ }
+ }
+ break;
+
+ default:
+ Log.w(TAG, "unhandled event");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isDropTargetEvent(DragEvent event, View v) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "isDropTargetEvent() called with " + "event = [" + event + "], v = [" + v + "]");
+ }
+ if (v == getDropTarget() || v == mQsPanelTop) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "isDropTargetEvent() returns true by view");
+ }
+ return true;
+ }
+
+ if (v == mViewPager && mLastTouchLocationY <= getRowTop(0)) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "isDropTargetEvent() returns true by loc");
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ private void restoreDraggingTilePosition(View v) {
+ if (mRestored) {
+ return;
+ }
+ mRestored = true;
+ mRestoring = true;
+ mCurrentlyAnimating.add(mDraggingRecord);
+
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "restoreDraggingTilePosition() called with "
+ + "v = [" + (v.getTag() != null ? v.getTag() : v) + "]");
+ }
+ final boolean dragRecordDetached = mRecords.indexOf(mDraggingRecord) == -1;
+
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "mLastLeftShift: " + mLastLeftShift
+ + ", detached: " + dragRecordDetached + ", drag record: " + mDraggingRecord);
+ }
+
+ final QSPage originalPage = getPage(mDraggingRecord.page);
+ originalPage.removeView(mDraggingRecord.tileView);
+ addTransientView(mDraggingRecord.tileView, 0);
+ mDraggingRecord.tileView.setTransitionVisibility(View.VISIBLE);
+
+ // need to move center of the dragging view to the coords of the event.
+ final float touchEventBoxLeft = v.getX()
+ + (mLastTouchLocationX - (mDraggingRecord.tileView.getWidth() / 2));
+ final float touchEventBoxTop = v.getY()
+ + (mLastTouchLocationY - (mDraggingRecord.tileView.getHeight() / 2));
+
+ mDraggingRecord.tileView.setX(touchEventBoxLeft);
+ mDraggingRecord.tileView.setY(touchEventBoxTop);
+
+ if (dragRecordDetached) {
+ setToLastDestination(mDraggingRecord);
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "setting drag record view to coords: x:" + touchEventBoxLeft
+ + ", y:" + touchEventBoxTop);
+ Log.d(TAG, "animating drag record to: " + mDraggingRecord + ", loc: "
+ + mDraggingRecord.destination);
+ }
+ } else {
+ mDraggingRecord.destination.x = getLeft(mDraggingRecord.destinationPage,
+ mDraggingRecord.row, mDraggingRecord.col,
+ getColumnCount(mDraggingRecord.destinationPage, mDraggingRecord.row));
+
+ mDraggingRecord.destination.y = getRowTop(mDraggingRecord.row);
+ }
+
+ // setup x destination to animate to
+ float destinationX = mDraggingRecord.destination.x;
+
+ // see if we should animate this to the left or right off the page
+ // the +1's are to account for the edit page
+ if (mDraggingRecord.destinationPage > mViewPager.getCurrentItem() - 1) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "adding width to animate out >>>>>");
+ }
+ destinationX += getWidth();
+ } else if (mDraggingRecord.destinationPage < mViewPager.getCurrentItem() - 1) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "removing width to animate out <<<<<");
+ }
+ destinationX -= getWidth();
+ }
+
+ // setup y
+ float destinationY = mDraggingRecord.destination.y + mViewPager.getTop();
+
+ mDraggingRecord.tileView.animate()
+ .withLayer()
+ .x(destinationX)
+ .y(destinationY) // part of the viewpager now
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mDraggingRecord.tileView.setAlpha(1);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mViewPager.requestDisallowInterceptTouchEvent(false);
+
+ removeTransientView(mDraggingRecord.tileView);
+
+ final QSPage targetP = getPage(mDraggingRecord.destinationPage);
+
+ if (DEBUG_DRAG) {
+ if (dragRecordDetached) {
+ Log.i(TAG, "drag record was detached");
+ } else {
+ Log.i(TAG, "drag record was attached");
+ }
+ }
+ mDraggingRecord.page = mDraggingRecord.destinationPage;
+ targetP.addView(mDraggingRecord.tileView);
+
+ mDraggingRecord.tileView.setX(mDraggingRecord.destination.x);
+ // reset this to be in the coords of the page, not viewpager anymore
+ mDraggingRecord.tileView.setY(mDraggingRecord.destination.y);
+
+ mCurrentlyAnimating.remove(mDraggingRecord);
+
+ mRestoring = false;
+
+ if (dragRecordDetached) {
+ mRecords.add(mDraggingRecord);
+ mPagerAdapter.notifyDataSetChanged();
+ }
+ onStopDrag();
+ }
+ });
+ }
+
+ private void setToNextDestination(DragTileRecord tile) {
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "+++setToNextDestination() called with " + "tile = [" + tile + "], at: "
+ + tile.destination);
+ }
+ tile.col++;
+ int maxCols = getColumnCount();
+
+ if (tile.col >= maxCols) {
+ tile.col = 0;
+ tile.row++;
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "reached max column count, shifting to next row: " + tile.row);
+ }
+ }
+
+ // clamp this value to the max count we want.
+ int maxRows = Math.min(MAX_ROW_COUNT - 1 /* we are 0 based */, getCurrentMaxRow());
+
+ if (tile.row > maxRows) {
+ tile.destinationPage = tile.destinationPage + 1;
+ tile.row = 0;
+ tile.col = 0;
+
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "tile's destination page moved to: " + tile.destinationPage);
+ }
+ }
+ int columnCount = Math.max(1, getColumnCount(tile.destinationPage, tile.row, false));
+ if (columnCount < maxCols) {
+ // if columncount gives us 1 and we're at col 2
+ columnCount = Math.max((tile.col + 1), columnCount);
+ }
+ if (DEBUG_DRAG) {
+ Log.w(TAG, "columCount at: " + columnCount);
+ }
+
+ boolean firstRowLarge = mFirstRowLarge && tile.row == 0 && tile.destinationPage == 0;
+
+ tile.destination.x = getLeft(tile.row, tile.col, columnCount, firstRowLarge);
+ tile.destination.y = getRowTop(tile.row);
+
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "---setToNextDestination() called with " + "tile = [" + tile + "], now at: "
+ + tile.destination);
+ }
+ }
+
+ private boolean isBefore(DragTileRecord r1, DragTileRecord r2) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "isBefore() called with " + "r1 = [" + r1 + "], r2 = [" + r2 + "]");
+ }
+ boolean isBefore = r1.destinationPage <= r2.destinationPage;
+ if (r1.destinationPage == r2.destinationPage) {
+ isBefore = r1.row <= r2.row;
+ if (r1.row == r2.row) {
+ isBefore = r1.col <= r2.col;
+ }
+ }
+
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "r1 isBefore r2: " + isBefore);
+ }
+ return isBefore;
+ }
+
+ private void setToLastDestination(DragTileRecord record) {
+ DragTileRecord last = (DragTileRecord) mRecords.get(mRecords.size() - 1);
+ if (DEBUG_DRAG) {
+ Log.d(TAG, "setToLastDestination() called with record = ["
+ + record + "], and last record is: " + last);
+ }
+
+ if (isBefore(record, last)) {
+ // if the record is before the last record in the records list, set it to the
+ // last location, then spoof it one space forward
+ record.destinationPage = last.destinationPage;
+ record.row = last.row;
+ record.col = last.col;
+ record.destination.x = last.destination.x;
+ record.destination.y = last.destination.y;
+ setToNextDestination(record);
+ }
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ final DragTileRecord record = (DragTileRecord) getRecord(v);
+ if (record == null) {
+ // TODO couldn't find a matching tag?
+ Log.e(TAG, "got a null record on touch down.");
+ return false;
+ }
+
+ mDraggingRecord = record;
+
+ mDraggingRecord.tileView.setAlpha(0);
+ mDraggingRecord.tileView.setDual(false, false);
+ TileShadow mTileShadow = new TileShadow(mDraggingRecord.tileView);
+
+ v.startDrag(null, mTileShadow, null, 0);
+
+ mViewPager.requestDisallowInterceptTouchEvent(true);
+
+ onStartDrag();
+ mDragging = true;
+ return true;
+ }
+
+ private void shiftTiles(DragTileRecord startingTile, boolean forward) {
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "shiftTiles() called with " + "startingTile = [" + startingTile
+ + "], forward = [" + forward + "]");
+ }
+
+ if (forward) {
+ // startingTile and all after will need to be shifted one to the right
+ // dragging tile needs room
+
+ final int destP = startingTile.destinationPage;
+ final int rowF = startingTile.row;
+ final int colF = startingTile.col;
+ PointF loc = new PointF(startingTile.destination.x, startingTile.destination.y);
+
+ // the index of the original position of the statingTile before it moved
+ int startingIndex = mRecords.indexOf(startingTile);
+ mLastRightShift = startingIndex;
+ mLastLeftShift = -1;
+
+ shiftAllTilesRight(startingIndex);
+ mRecords.add(startingIndex, mDraggingRecord);
+
+ mPagerAdapter.notifyDataSetChanged();
+
+ mDraggingRecord.col = colF;
+ mDraggingRecord.row = rowF;
+ mDraggingRecord.destination = loc;
+ mDraggingRecord.destinationPage = destP;
+
+ mDraggingRecord.tileView.setX(mDraggingRecord.destination.x);
+ mDraggingRecord.tileView.setY(mDraggingRecord.destination.y);
+
+ } else {
+ // it is also probably the dragging tile
+ final int startingIndex = mRecords.indexOf(startingTile);
+ mLastLeftShift = startingIndex;
+ mLastRightShift = -1;
+
+ final int draggingIndex = mRecords.indexOf(mDraggingRecord);
+
+ if (startingIndex != draggingIndex) {
+ if (DEBUG_DRAG) {
+ Log.e(TAG, "startinIndex: " + startingIndex + ", draggingIndex: "
+ + draggingIndex + ", and they differ!!!!");
+ }
+ }
+
+ // startingTile should be the "empty" tile that things should start shifting into
+ shiftAllTilesLeft(startingIndex);
+
+ // remove the dragging record
+ if (mRecords.remove(mDraggingRecord)) {
+ mPagerAdapter.notifyDataSetChanged();
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "removed dragging record after moving tiles back");
+ }
+ }
+
+ // set coords off screen until we're ready to place it
+ mDraggingRecord.tileView.setX(-mDraggingRecord.tileView.getMeasuredWidth());
+ mDraggingRecord.tileView.setY(-mDraggingRecord.tileView.getMeasuredHeight());
+ }
+
+ mViewPager.getAdapter().notifyDataSetChanged();
+ }
+
+ private void shiftAllTilesRight(int startingIndex) {
+ int desiredColumnCount = -1;
+ for (int j = startingIndex; j < mRecords.size() - 1; j++) {
+ final DragTileRecord ti = (DragTileRecord) mRecords.get(j);
+ final DragTileRecord tnext = (DragTileRecord) mRecords.get(j + 1);
+
+ mCurrentlyAnimating.add(ti);
+ if (tnext.row != ti.row || desiredColumnCount == -1) {
+ desiredColumnCount = getColumnCount(tnext.destinationPage, tnext.row);
+ //Log.w(TAG, "updated desiredColumnCount: " + desiredColumnCount);
+ }
+
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "moving " + ti + " to page " + tnext.destinationPage + ", at coords: "
+ + tnext.row + ", col: " + tnext.col + ", dest: " + tnext.destination);
+ }
+
+ ti.row = tnext.row;
+ ti.col = tnext.col;
+ ti.destination.x = getLeft(tnext.destinationPage, ti.row, ti.col, desiredColumnCount);
+ ti.destination.y = getRowTop(ti.row);
+
+ if (ti.destinationPage != tnext.destinationPage) {
+ ti.destinationPage = tnext.destinationPage;
+
+ final QSPage tilePageSource = getPage(ti.page);
+ final QSPage tilePageTarget = getPage(ti.destinationPage);
+ tilePageSource.removeView(ti.tileView);
+
+ tilePageSource.addTransientView(ti.tileView, 0);
+ ti.tileView.animate()
+ .withLayer()
+ .x(ti.destination.x + getWidth())
+ .y(ti.destination.y)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ tilePageSource.removeTransientView(ti.tileView);
+ ti.page = tilePageTarget.getPageIndex();
+ tilePageTarget.addView(ti.tileView);
+ ti.tileView.setX(ti.destination.x);
+ ti.tileView.setY(ti.destination.y);
+
+ mCurrentlyAnimating.remove(ti);
+ requestLayout();
+ }
+ });
+
+ } else {
+ ti.tileView.animate()
+ .withLayer()
+ .x(ti.destination.x)
+ .y(ti.destination.y)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCurrentlyAnimating.remove(ti);
+ final boolean dual = getPage(ti.destinationPage).dualRecord(ti);
+ if (ti.tileView.setDual(dual, ti.tile.hasDualTargetsDetails())) {
+ if (DEBUG_DRAG) {
+ Log.w(TAG, ti + " changed dual state to : "
+ + ti.tileView.isDual());
+ }
+ }
+ requestLayout();
+ }
+ });
+ }
+ }
+
+ // need to do last tile manually
+ final DragTileRecord last = (DragTileRecord) mRecords.get(mRecords.size() - 1);
+ mCurrentlyAnimating.add(last);
+
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "last tile shifting to the right: " + last);
+ }
+ setToNextDestination(last);
+ if (last.page != last.destinationPage) {
+ final QSPage tilePageSource = getPage(last.page);
+ final QSPage tilePageTarget = getPage(last.destinationPage);
+ tilePageSource.removeView(last.tileView);
+ tilePageSource.addTransientView(last.tileView, 0);
+
+ last.tileView.animate()
+ .withLayer()
+ .x(last.destination.x + getWidth())
+ .y(last.destination.y)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ tilePageSource.removeTransientView(last.tileView);
+ last.page = tilePageTarget.getPageIndex();
+ tilePageTarget.addView(last.tileView);
+ last.tileView.setX(last.destination.x);
+ last.tileView.setY(last.destination.y);
+
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "page shift finished: " + last);
+ }
+
+ mCurrentlyAnimating.remove(last);
+ requestLayout();
+ }
+ });
+ } else {
+ last.tileView.animate()
+ .withLayer()
+ .x(last.destination.x)
+ .y(last.destination.y)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (DEBUG_DRAG) {
+ Log.i(TAG, "shift finished: " + last);
+ }
+
+ mCurrentlyAnimating.remove(last);
+ requestLayout();
+ }
+ });
+ }
+ }
+
+ private void shiftAllTilesLeft(int startingIndex) {
+ DragTileRecord startingTile = (DragTileRecord) mRecords.get(startingIndex);
+
+ final PointF lastLocation = new PointF(startingTile.destination.x,
+ startingTile.destination.y);
+ PointF reallyTempLoc = new PointF();
+ int lastRow = startingTile.row, lastCol = startingTile.col, tempRow,
+ tempCol, lastPage = startingTile.destinationPage, tempPage;
+
+ int desiredColCount = getColumnCount(startingTile.destinationPage, startingTile.row);
+ for (int j = startingIndex + 1; j < mRecords.size(); j++) {
+ final DragTileRecord ti = (DragTileRecord) mRecords.get(j);
+
+ mCurrentlyAnimating.add(ti);
+
+ if (DEBUG_DRAG) {
+ Log.v(TAG, "moving " + ti + " to " + lastPage + ", at coords: "
+ + lastRow + ", col: " + lastCol);
+ Log.i(TAG, "and will have desiredColCount: " + desiredColCount);
+ }
+
+ final int columnCountF = desiredColCount;
+
+ if (ti.row != lastRow) {
+ desiredColCount = getColumnCount(ti.destinationPage, ti.row);
+ if (DEBUG_DRAG) {
+ Log.e(TAG, "updating desired colum count to: " + desiredColCount);
+ }
+ }
+
+ // save current tile's loc
+ reallyTempLoc.x = ti.destination.x;
+ reallyTempLoc.y = ti.destination.y;
+
+ tempRow = ti.row;
+ tempCol = ti.col;
+ tempPage = ti.destinationPage;
+
+ ti.row = lastRow;
+ ti.col = lastCol;
+
+ ti.destination.x = getLeft(lastRow, lastCol, columnCountF,
+ lastPage == 0 && lastRow == 0 && mFirstRowLarge);
+ ti.destination.y = getRowTop(lastRow);
+
+ final boolean dual = getPage(ti.destinationPage).dualRecord(ti);
+
+ if (ti.destinationPage != lastPage) {
+ ti.destinationPage = lastPage;
+
+ ti.tileView.setX(reallyTempLoc.x + getWidth());
+ ti.tileView.setY(reallyTempLoc.y);
+
+ final QSPage originalPage = getPage(ti.page);
+ final QSPage page = getPage(lastPage);
+
+ originalPage.removeView(ti.tileView);
+
+ ti.tileView.animate()
+ .withLayer()
+ .x(ti.destination.x)
+ .y(ti.destination.y)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ page.addTransientView(ti.tileView, 0);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ page.removeTransientView(ti.tileView);
+ ti.page = page.getPageIndex();
+ page.addView(ti.tileView);
+
+ mCurrentlyAnimating.remove(ti);
+ requestLayout();
+ }
+ });
+ } else {
+ ti.tileView.animate()
+ .withLayer()
+ .x(ti.destination.x)
+ .y(ti.destination.y)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCurrentlyAnimating.remove(ti);
+ if (ti.tileView.setDual(dual, ti.tile.hasDualTargetsDetails())) {
+ if (DEBUG_DRAG) {
+ Log.w(TAG, ti + " changed dual state to : "
+ + ti.tileView.isDual());
+ }
+ }
+ requestLayout();
+ }
+ });
+ }
+
+ // update previous location
+ lastLocation.x = reallyTempLoc.x;
+ lastLocation.y = reallyTempLoc.y;
+
+ lastRow = tempRow;
+ lastCol = tempCol;
+ lastPage = tempPage;
+ }
+ }
+
+ @Override
+ protected void handleShowDetailImpl(Record r, boolean show, int x, int y) {
+ super.handleShowDetailImpl(r, show, x, y);
+ if (show) {
+ final StatusBarPanelCustomTile customTile = r.detailAdapter.getCustomTile();
+ mDetailRemoveButton.setVisibility(customTile != null &&
+ !(customTile.getPackage().equals(mContext.getPackageName())
+ || customTile.getUid() == android.os.Process.SYSTEM_UID)
+ ? VISIBLE : GONE);
+ mDetailRemoveButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHost.removeCustomTile(customTile);
+ closeDetail();
+ }
+ });
+ }
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ FontSizeUtils.updateFontSize(mDetailRemoveButton, R.dimen.qs_detail_button_text_size);
+ }
+
+ @Override
+ public void setExpanded(boolean expanded) {
+ super.setExpanded(expanded);
+ if (!expanded) {
+ if (mEditing) {
+ mHost.setEditing(false);
+ }
+ }
+ }
+
+ public void updateResources() {
+ final Resources res = mContext.getResources();
+ final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
+ mCellHeight = res.getDimensionPixelSize(R.dimen.qs_tile_height);
+ mCellWidth = (int) (mCellHeight * TILE_ASPECT);
+ mLargeCellHeight = res.getDimensionPixelSize(R.dimen.qs_dual_tile_height);
+ mLargeCellWidth = (int) (mLargeCellHeight * TILE_ASPECT);
+ mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom);
+ mDualTileUnderlap = res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical);
+ mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top);
+ mPageIndicatorHeight = res.getDimensionPixelSize(R.dimen.qs_panel_page_indicator_height);
+ if (mColumns != columns) {
+ mColumns = columns;
+ if (isLaidOut()) postInvalidate();
+ }
+ if (isLaidOut()) {
+ for (TileRecord r : mRecords) {
+ r.tile.clearState();
+ }
+ if (mListening) {
+ refreshAllTiles();
+ }
+ updateDetailText();
+ }
+ }
+
+ public boolean isAnimating(TileRecord t) {
+ return mCurrentlyAnimating.contains(t);
+ }
+
+ public void cleanup() {
+ if (mSettingsObserver != null) {
+ mSettingsObserver.unobserve();
+ }
+ }
+
+ public static class TilesListAdapter extends BaseExpandableListAdapter
+ implements QSTile.DetailAdapter {
+
+ public static final String PACKAGE_ANDROID = "android";
+
+ Context mContext;
+ QSTileHost mHost;
+ QSDragPanel mPanel;
+
+ ArrayMap<String, List<String>> mPackageTileMap = new ArrayMap<>();
+
+ public TilesListAdapter(Context context, QSDragPanel panel) {
+ mContext = context;
+ mHost = panel.getHost();
+ mPanel = panel;
+
+ List<String> currentTileSpec = mHost.getTileSpecs();
+ final Collection<String> tiles = QSUtils.getAvailableTiles(mContext);
+ tiles.removeAll(currentTileSpec);
+
+ // we'll always have a system tiles category
+ mPackageTileMap.put(PACKAGE_ANDROID, new ArrayList<String>());
+
+ final Iterator<String> i = tiles.iterator();
+ while (i.hasNext()) {
+ final String spec = i.next();
+ if (QSUtils.isStaticQsTile(spec) || QSUtils.isDynamicQsTile(spec)) {
+ List<String> packageList = mPackageTileMap.get(PACKAGE_ANDROID);
+ packageList.add(spec);
+ } else {
+ String tilePackage = getCustomTilePackage(spec);
+ List<String> packageList = mPackageTileMap.get(tilePackage);
+ if (packageList == null) {
+ mPackageTileMap.put(tilePackage, packageList = new ArrayList<>());
+ }
+ packageList.add(spec);
+ }
+ }
+
+ final List<String> systemTiles = mPackageTileMap.get(PACKAGE_ANDROID);
+ Collections.sort(systemTiles);
+ }
+
+ private String getCustomTilePackage(String spec) {
+ StatusBarPanelCustomTile sbc = mHost.getCustomTileData().get(spec).sbc;
+ return sbc.getPackage();
+ }
+
+ @Override
+ public int getGroupCount() {
+ return mPackageTileMap.keySet().size();
+ }
+
+ @Override
+ public int getChildrenCount(int groupPosition) {
+ return mPackageTileMap.valueAt(groupPosition).size();
+ }
+
+ @Override
+ public String getGroup(int groupPosition) {
+ return mPackageTileMap.keyAt(groupPosition);
+ }
+
+ @Override
+ public String getChild(int groupPosition, int childPosition) {
+ return mPackageTileMap.valueAt(groupPosition).get(childPosition);
+ }
+
+ @Override
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ @Override
+ public long getChildId(int groupPosition, int childPosition) {
+ return mPackageTileMap.valueAt(groupPosition).get(childPosition).hashCode();
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+ ViewGroup parent) {
+ LinearLayout row = (LinearLayout) convertView;
+ if (row == null) {
+ row = (LinearLayout) LayoutInflater.from(mContext)
+ .inflate(R.layout.qs_tile_category_row, parent, false);
+ }
+ TextView title = (TextView) row.findViewById(android.R.id.title);
+
+ ImageView systemOrAppIcon = (ImageView) row.findViewById(android.R.id.icon);
+ ImageView expansionIndicator = (ImageView) row.findViewById(android.R.id.icon2);
+
+ expansionIndicator.setImageResource(isExpanded ? R.drawable.ic_qs_tile_contract
+ : R.drawable.ic_qs_tile_expand);
+ // hide indicator when there's only 1 group
+ final boolean singleGroupMode = getGroupCount() == 1;
+ expansionIndicator.setVisibility(singleGroupMode ? View.GONE : View.VISIBLE);
+
+ String group = getGroup(groupPosition);
+ if (group.equals(PACKAGE_ANDROID)) {
+ group = mContext.getText(R.string.quick_settings_tiles_category_system).toString();
+ // special icon
+ systemOrAppIcon.setImageResource(R.drawable.ic_qs_tile_category_system);
+ } else {
+ systemOrAppIcon.setImageResource(R.drawable.ic_qs_tile_category_other);
+ }
+ title.setText(group);
+
+ if (isExpanded) {
+ expansionIndicator.setColorFilter(
+ mContext.getColor(
+ R.color.qs_detailed_expansion_indicator_color), PorterDuff.Mode.SRC_ATOP);
+ systemOrAppIcon.setColorFilter(
+ mContext.getColor(R.color.qs_detailed_icon_tint_color), PorterDuff.Mode.SRC_ATOP);
+ title.setTextColor(mContext.getColor(R.color.qs_detailed_title_text_color));
+ } else {
+ title.setTextColor(mContext.getColor(R.color.qs_detailed_default_text_color));
+ systemOrAppIcon.setColorFilter(null);
+ expansionIndicator.setColorFilter(null);
+ }
+ return row;
+ }
+
+ @Override
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+ View convertView, ViewGroup parent) {
+ LinearLayout child = (LinearLayout) convertView;
+ if (child == null) {
+ child = (LinearLayout) LayoutInflater.from(mContext)
+ .inflate(R.layout.qs_tile_child_row, parent, false);
+ }
+ String spec = getChild(groupPosition, childPosition);
+
+ TextView title = (TextView) child.findViewById(android.R.id.title);
+ title.setText(getQSTileLabel(spec));
+
+ ImageView icon = (ImageView) child.findViewById(android.R.id.icon);
+ icon.setImageDrawable(getQSTileIcon(spec));
+
+ return child;
+ }
+
+ private String getQSTileLabel(String spec) {
+ if (QSUtils.isStaticQsTile(spec)) {
+ int resource = QSTileHost.getLabelResource(spec);
+ return mContext.getText(resource).toString();
+ } else if (QSUtils.isDynamicQsTile(spec)) {
+ return QSUtils.getDynamicQSTileLabel(mContext,
+ UserHandle.myUserId(), spec);
+ } else {
+ return getPackageLabel(getCustomTilePackage(spec));
+ }
+ }
+
+ private Drawable getQSTileIcon(String spec) {
+ if (QSUtils.isDynamicQsTile(spec)) {
+ return QSTile.ResourceIcon.get(
+ QSUtils.getDynamicQSTileResIconId(mContext, UserHandle.myUserId(), spec))
+ .getDrawable(mContext);
+ } else if (QSUtils.isStaticQsTile(spec)) {
+ return QSTile.ResourceIcon.get(QSTileHost.getIconResource(spec))
+ .getDrawable(mContext);
+ } else {
+ QSTile<?> tile = mHost.getTile(spec);
+ if (tile != null) {
+ QSTile.State state = tile.getState();
+ if (state != null && state.icon != null) {
+ return state.icon.getDrawable(mContext);
+ }
+ }
+ return getPackageDrawable(getCustomTilePackage(spec));
+ }
+ }
+
+ private String getPackageLabel(String packageName) {
+ try {
+ return mContext.getPackageManager().getApplicationLabel(
+ mContext.getPackageManager().getApplicationInfo(packageName, 0)).toString();
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private Drawable getPackageDrawable(String packageName) {
+ try {
+ return mContext.getPackageManager().getApplicationIcon(packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_tiles_add_tiles;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ ExpandableListView lv = (ExpandableListView) convertView;
+ if (lv == null) {
+ lv = new ExpandableListView(parent.getContext());
+ lv.setOnTouchListener(new OnTouchListener() {
+ // Setting on Touch Listener for handling the touch inside ScrollView
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ // Disallow the touch request for parent scroll on touch of child view
+ v.getParent().requestDisallowInterceptTouchEvent(true);
+ return false;
+ }
+ });
+ }
+ lv.setAdapter(this);
+ lv.expandGroup(mPackageTileMap.indexOfKey(PACKAGE_ANDROID));
+ lv.setGroupIndicator(null);
+ lv.setChildIndicator(null);
+ lv.setChildDivider(new ColorDrawable(Color.TRANSPARENT));
+ lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
+ @Override
+ public boolean onChildClick(ExpandableListView parent, View v,
+ int groupPosition, int childPosition, long id) {
+ String spec = getChild(groupPosition, childPosition);
+ mPanel.add(spec);
+ mPanel.closeDetail();
+ return true;
+ }
+ });
+ lv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
+ @Override
+ public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition,
+ long id) {
+ if (getGroupCount() == 1) {
+ // disable contracting/expanding group when there's only 1
+ return true;
+ }
+ return false;
+ }
+ });
+ return lv;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return null;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.DONT_LOG;
+ }
+
+ private boolean isValid(String action) {
+ for (int i = 0; i < action.length(); i++) {
+ char c = action.charAt(i);
+ if (!Character.isAlphabetic(c) && !Character.isDigit(c) && c != '.') {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ public void add(String tile) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_ADD, tile);
+ List<String> tiles = new ArrayList<>(mHost.getTileSpecs());
+ tiles.add(tile);
+ mHost.setTiles(tiles);
+ }
+
+ public boolean isDragging() {
+ return mDragging;
+ }
+
+ public boolean isDragRecordAttached() {
+ return mRecords.indexOf(mDraggingRecord) >= 0;
+ }
+
+ public boolean isOnSettingsPage() {
+ return mEditing && mViewPager.getCurrentItem() == 0;
+ }
+
+ public void goToSettingsPage() {
+ if (mEditing) {
+ mViewPager.setCurrentItem(0, true);
+ }
+ }
+
+ class SettingsObserver extends UserContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.QS_USE_MAIN_TILES), false, this, UserHandle.USER_ALL);
+ update();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ int currentUserId = ActivityManager.getCurrentUser();
+ boolean firstRowLarge = CMSettings.Secure.getIntForUser(resolver,
+ CMSettings.Secure.QS_USE_MAIN_TILES, 1, currentUserId) == 1;
+ if (firstRowLarge != mFirstRowLarge) {
+ mFirstRowLarge = firstRowLarge;
+ setTiles(mHost.getTiles());
+ mPagerAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+
+ public static final class DragTileRecord extends TileRecord {
+ public int page;
+ public int destinationPage;
+ public PointF destination = new PointF();
+
+ @Override
+ public String toString() {
+ String label = tile instanceof QsTuner.DraggableTile ? tile.toString() :
+ tile.getClass().getSimpleName();
+
+ String p = "at page: " + page;
+ if (destinationPage != page) {
+ p += "{-> " + destinationPage + "} ";
+ }
+
+ return "[" + label + ", coords: (" + row + ", " + col + ") " + p + "]";
+ }
+ }
+
+ private static class TileShadow extends View.DragShadowBuilder {
+
+ public TileShadow(View view) {
+ super(view);
+ Drawable shadow = view.getContext().getDrawable(R.drawable.qs_tile_background_drag);
+ view.setBackground(shadow);
+ }
+
+ @Override
+ public void onDrawShadow(Canvas canvas) {
+ super.onDrawShadow(canvas);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPage.java b/packages/SystemUI/src/com/android/systemui/qs/QSPage.java
new file mode 100644
index 0000000..7871a62
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPage.java
@@ -0,0 +1,161 @@
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.systemui.R;
+
+public class QSPage extends ViewGroup {
+
+ private static final String TAG = "QSPage";
+
+ static final float TILE_ASPECT = 1.2f;
+
+ private int mCellWidth;
+ private int mCellHeight;
+ private int mLargeCellWidth;
+ private int mLargeCellHeight;
+ private int mGridHeight;
+
+ private QSDragPanel mPanel;
+
+ private int mPage;
+
+ private boolean mAdapterEditingState;
+
+ public QSPage(Context context, QSDragPanel panel, int page) {
+ super(context);
+ mPanel = panel;
+ mPage = page;
+ updateResources();
+ setClipChildren(false);
+ setClipToPadding(false);
+ setClipToOutline(false);
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ public int getPageIndex() {
+ return mPage;
+ }
+
+ public void updateResources() {
+ final Resources res = mContext.getResources();
+ final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
+ mCellHeight = res.getDimensionPixelSize(R.dimen.qs_tile_height);
+ mCellWidth = (int)(mCellHeight * TILE_ASPECT);
+ mLargeCellHeight = res.getDimensionPixelSize(R.dimen.qs_dual_tile_height);
+ mLargeCellWidth = (int)(mLargeCellHeight * TILE_ASPECT);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int width = MeasureSpec.getSize(widthMeasureSpec);
+ if (mPanel.mCurrentlyAnimating.isEmpty() && !mPanel.isDragging()) {
+ int r = -1;
+ int c = -1;
+ int rows = 0;
+ for (QSPanel.TileRecord ts : mPanel.mRecords) {
+ QSDragPanel.DragTileRecord record = (QSDragPanel.DragTileRecord) ts;
+ if (record.page != mPage) continue;
+ if (record.tileView.getVisibility() == GONE) continue;
+
+ if (mPage == 0 && r == 0 && c == 1 && mPanel.mFirstRowLarge) {
+ r = 1;
+ c = 0;
+ } else if (r == -1 || c == (mPanel.getColumnCount() - 1)) {
+ r++;
+ c = 0;
+ } else {
+ c++;
+ }
+ record.row = r;
+ record.col = c;
+ rows = r + 1;
+ }
+ mGridHeight = mPanel.getRowTop(rows);
+ }
+
+ View previousView = mPanel.getBrightnessView();
+ for (QSPanel.TileRecord ts : mPanel.mRecords) {
+ QSDragPanel.DragTileRecord record = (QSDragPanel.DragTileRecord) ts;
+ if (record.page != mPage) continue;
+ if (record.page != record.destinationPage) continue;
+
+ final boolean dual = dualRecord(record);
+ if (record.tileView.setDual(dual, record.tile.hasDualTargetsDetails())) {
+ record.tileView.handleStateChanged(record.tile.getState());
+ }
+ if (record.tileView.getVisibility() == GONE) continue;
+ final int cw = dual ? mLargeCellWidth : mCellWidth;
+ final int ch = dual ? mLargeCellHeight : mCellHeight;
+ record.tileView.measure(exactly(cw), exactly(ch));
+ previousView = record.tileView.updateAccessibilityOrder(previousView);
+ }
+ setMeasuredDimension(width, mGridHeight);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int w = getWidth();
+ boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ for (QSPanel.TileRecord ts : mPanel.mRecords) {
+ QSDragPanel.DragTileRecord record = (QSDragPanel.DragTileRecord) ts;
+ if (record.page != mPage) continue;
+ if (record.page != record.destinationPage) continue;
+ if (record.tileView.getVisibility() == GONE) continue;
+
+ final int cols = mPanel.getColumnCount(mPage, record.row);
+
+ int left = mPanel.getLeft(record.row, record.col, cols, dualRecord(record));
+ final int top = mPanel.getRowTop(record.row);
+ int right;
+ int tileWith = record.tileView.getMeasuredWidth();
+ if (isRtl) {
+ right = w - left;
+ left = right - tileWith;
+ } else {
+ right = left + tileWith;
+ }
+ if (mPanel.isAnimating(record)) {
+ record.tileView.layout(record.tileView.getLeft(), record.tileView.getTop(),
+ record.tileView.getRight(), record.tileView.getBottom());
+ continue;
+ }
+ if (false) {
+ Log.v(TAG + "-" + mPage, "laying out " + record + ", top: " + top + ", left: " + left);
+ Log.d(TAG, record + " wiping translations: "
+ + record.tileView.getTranslationX()
+ + ", " + record.tileView.getTranslationY());
+ }
+ record.tileView.setTranslationX(0);
+ record.tileView.setTranslationY(0);
+
+ record.destination.x = record.tileView.getX();
+ record.destination.y = record.tileView.getY();
+
+ record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
+ }
+ }
+
+ public boolean getAdapterEditingState() {
+ return mAdapterEditingState;
+ }
+
+ public void setAdapterEditingState(boolean editing) {
+ this.mAdapterEditingState = editing;
+ }
+
+ public boolean dualRecord(QSPanel.TileRecord record) {
+ return mPanel.mFirstRowLarge && record.row == 0 && mPage == 0;
+ }
+
+ private static int exactly(int size) {
+ return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 94d5170..60dc787 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -25,6 +25,8 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -45,40 +47,42 @@ import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import java.util.ArrayList;
import java.util.Collection;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import cyanogenmod.providers.CMSettings;
+
/** View that represents the quick settings tile panel. **/
public class QSPanel extends ViewGroup {
- private static final float TILE_ASPECT = 1.2f;
-
- private final Context mContext;
- protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
- private final View mDetail;
- private final ViewGroup mDetailContent;
- private final TextView mDetailSettingsButton;
- private final TextView mDetailDoneButton;
- protected final View mBrightnessView;
- private final QSDetailClipper mClipper;
+ protected static final float TILE_ASPECT = 1.2f;
+
+ protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+ protected View mDetail;
+ protected ViewGroup mDetailContent;
+ protected TextView mDetailSettingsButton;
+ protected TextView mDetailDoneButton;
+ protected View mBrightnessView;
+ protected QSDetailClipper mClipper;
private final H mHandler = new H();
- private int mColumns;
- private int mCellWidth;
- private int mCellHeight;
- private int mLargeCellWidth;
- private int mLargeCellHeight;
- private int mPanelPaddingBottom;
- private int mDualTileUnderlap;
- private int mBrightnessPaddingTop;
- private int mGridHeight;
+ protected int mColumns;
+ protected int mCellWidth;
+ protected int mCellHeight;
+ protected int mLargeCellWidth;
+ protected int mLargeCellHeight;
+ protected int mPanelPaddingBottom;
+ protected int mDualTileUnderlap;
+ protected int mBrightnessPaddingTop;
+ protected int mGridHeight;
private boolean mExpanded;
- private boolean mListening;
+ protected boolean mListening;
private boolean mClosingDetail;
- private Record mDetailRecord;
+ protected Record mDetailRecord;
private Callback mCallback;
- private BrightnessController mBrightnessController;
- private QSTileHost mHost;
+ protected BrightnessController mBrightnessController;
+ protected QSTileHost mHost;
- private QSFooter mFooter;
- private boolean mGridContentVisible = true;
+ protected QSFooter mFooter;
+ protected boolean mGridContentVisible = true;
public QSPanel(Context context) {
this(context, null);
@@ -87,17 +91,23 @@ public class QSPanel extends ViewGroup {
public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
+ setupViews();
+ }
- mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false);
+ /**
+ * THIS IS OVERRIDDEN in QSDragPanel
+ */
+ protected void setupViews() {
+ mDetail = LayoutInflater.from(mContext).inflate(R.layout.qs_detail, this, false);
mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
updateDetailText();
mDetail.setVisibility(GONE);
mDetail.setClickable(true);
- mBrightnessView = LayoutInflater.from(context).inflate(
+ mBrightnessView = LayoutInflater.from(mContext).inflate(
R.layout.quick_settings_brightness_dialog, this, false);
- mFooter = new QSFooter(this, context);
+ mFooter = new QSFooter(this, mContext);
addView(mDetail);
addView(mBrightnessView);
addView(mFooter.getView());
@@ -118,7 +128,26 @@ public class QSPanel extends ViewGroup {
});
}
- private void updateDetailText() {
+ /**
+ * Enable/disable brightness slider.
+ */
+ protected boolean showBrightnessSlider() {
+ boolean brightnessSliderEnabled = CMSettings.System.getIntForUser(
+ mContext.getContentResolver(), CMSettings.System.QS_SHOW_BRIGHTNESS_SLIDER,
+ 1, UserHandle.USER_CURRENT) == 1;
+ ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
+ if (brightnessSliderEnabled) {
+ mBrightnessView.setVisibility(VISIBLE);
+ brightnessSlider.setVisibility(VISIBLE);
+ } else {
+ mBrightnessView.setVisibility(GONE);
+ brightnessSlider.setVisibility(GONE);
+ }
+ updateResources();
+ return brightnessSliderEnabled;
+ }
+
+ protected void updateDetailText() {
mDetailDoneButton.setText(R.string.quick_settings_done);
mDetailSettingsButton.setText(R.string.quick_settings_more_settings);
}
@@ -206,7 +235,7 @@ public class QSPanel extends ViewGroup {
if (mListening) {
refreshAllTiles();
}
- if (listening) {
+ if (listening && showBrightnessSlider()) {
mBrightnessController.registerCallbacks();
} else {
mBrightnessController.unregisterCallbacks();
@@ -236,11 +265,11 @@ public class QSPanel extends ViewGroup {
showDetail(show, r);
}
- private void showDetail(boolean show, Record r) {
+ protected void showDetail(boolean show, Record r) {
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
}
- private void setTileVisibility(View v, int visibility) {
+ protected void setTileVisibility(View v, int visibility) {
mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visibility, 0, v).sendToTarget();
}
@@ -252,6 +281,15 @@ public class QSPanel extends ViewGroup {
v.setVisibility(visibility);
}
+ protected void setTileEnabled(View v, boolean enabled) {
+ mHandler.obtainMessage(H.SET_TILE_ENABLED, enabled ? 1 : 0, 0, v).sendToTarget();
+ }
+
+ private void handleSetTileEnabled(View v, boolean enabled) {
+ if (enabled == v.isEnabled()) return;
+ v.setEnabled(enabled);
+ }
+
public void setTiles(Collection<QSTile<?>> tiles) {
for (TileRecord record : mRecords) {
removeView(record.tileView);
@@ -265,7 +303,7 @@ public class QSPanel extends ViewGroup {
}
}
- private void drawTile(TileRecord r, QSTile.State state) {
+ protected void drawTile(TileRecord r, QSTile.State state) {
final int visibility = state.visible ? VISIBLE : GONE;
setTileVisibility(r.tileView, visibility);
r.tileView.onStateChanged(state);
@@ -365,7 +403,7 @@ public class QSPanel extends ViewGroup {
}
}
- private void handleShowDetailTile(TileRecord r, boolean show) {
+ protected void handleShowDetailTile(TileRecord r, boolean show) {
if ((mDetailRecord != null) == show && mDetailRecord == r) return;
if (show) {
@@ -378,7 +416,7 @@ public class QSPanel extends ViewGroup {
handleShowDetailImpl(r, show, x, y);
}
- private void handleShowDetailImpl(Record r, boolean show, int x, int y) {
+ protected void handleShowDetailImpl(Record r, boolean show, int x, int y) {
boolean visibleDiff = (mDetailRecord != null) != show;
if (!visibleDiff && mDetailRecord == r) return; // already in right state
DetailAdapter detailAdapter = null;
@@ -425,7 +463,7 @@ public class QSPanel extends ViewGroup {
}
}
- private void setGridContentVisibility(boolean visible) {
+ protected void setGridContentVisibility(boolean visible) {
int newVis = visible ? VISIBLE : INVISIBLE;
for (int i = 0; i < mRecords.size(); i++) {
TileRecord tileRecord = mRecords.get(i);
@@ -433,7 +471,7 @@ public class QSPanel extends ViewGroup {
tileRecord.tileView.setVisibility(newVis);
}
}
- mBrightnessView.setVisibility(newVis);
+ mBrightnessView.setVisibility(showBrightnessSlider() ? newVis : GONE);
if (mGridContentVisible != visible) {
MetricsLogger.visibility(mContext, MetricsLogger.QS_PANEL, newVis);
}
@@ -458,15 +496,12 @@ public class QSPanel extends ViewGroup {
int r = -1;
int c = -1;
int rows = 0;
- boolean rowIsDual = false;
for (TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
// wrap to next column if we've reached the max # of columns
- // also don't allow dual + single tiles on the same row
- if (r == -1 || c == (mColumns - 1) || rowIsDual != record.tile.supportsDualTargets()) {
+ if (r == -1 || c == (mColumns - 1)) {
r++;
c = 0;
- rowIsDual = record.tile.supportsDualTargets();
} else {
c++;
}
@@ -477,7 +512,8 @@ public class QSPanel extends ViewGroup {
View previousView = mBrightnessView;
for (TileRecord record : mRecords) {
- if (record.tileView.setDual(record.tile.supportsDualTargets())) {
+ final boolean dualTarget = record.tile.hasDualTargetsDetails();
+ if (record.tileView.setDual(dualTarget, dualTarget)) {
record.tileView.handleStateChanged(record.tile.getState());
}
if (record.tileView.getVisibility() == GONE) continue;
@@ -535,7 +571,7 @@ public class QSPanel extends ViewGroup {
}
}
- private int getRowTop(int row) {
+ protected int getRowTop(int row) {
if (row <= 0) return mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop;
return mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop
+ mLargeCellHeight - mDualTileUnderlap + (row - 1) * mCellHeight;
@@ -556,13 +592,13 @@ public class QSPanel extends ViewGroup {
}
}
- private void fireToggleStateChanged(boolean state) {
+ protected void fireToggleStateChanged(boolean state) {
if (mCallback != null) {
mCallback.onToggleStateChanged(state);
}
}
- private void fireScanStateChanged(boolean state) {
+ protected void fireScanStateChanged(boolean state) {
if (mCallback != null) {
mCallback.onScanStateChanged(state);
}
@@ -579,24 +615,27 @@ public class QSPanel extends ViewGroup {
private class H extends Handler {
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
+ private static final int SET_TILE_ENABLED = 3;
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_DETAIL) {
handleShowDetail((Record)msg.obj, msg.arg1 != 0);
} else if (msg.what == SET_TILE_VISIBILITY) {
handleSetTileVisibility((View)msg.obj, msg.arg1);
+ } else if (msg.what == SET_TILE_ENABLED) {
+ handleSetTileEnabled((View)msg.obj, msg.arg1 == 1);
}
}
}
- private static class Record {
+ protected static class Record {
View detailView;
DetailAdapter detailAdapter;
int x;
int y;
}
- protected static final class TileRecord extends Record {
+ protected static class TileRecord extends Record {
public QSTile<?> tile;
public QSTileView tileView;
public int row;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java
new file mode 100644
index 0000000..5f57be1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.settings.ToggleSlider;
+
+import cyanogenmod.providers.CMSettings;
+
+public class QSPanelTopView extends FrameLayout {
+
+ private static final String TAG = "QSPanelTopView";
+
+ public static final int TOAST_DURATION = 2000;
+
+ protected View mEditTileInstructionView;
+ protected View mDropTarget;
+ protected View mBrightnessView;
+ protected TextView mToastView;
+ protected View mAddTarget;
+
+ private boolean mEditing = false;
+ private boolean mDisplayingInstructions = false;
+ private boolean mDisplayingTrash = false;
+ private boolean mDisplayingToast = false;
+ public boolean mHasBrightnessSliderToDisplay = true;
+
+ private AnimatorSet mAnimator;
+ private ImageView mDropTargetIcon;
+
+ private SettingsObserver mSettingsObserver;
+ private boolean mListening;
+ private boolean mSkipAnimations;
+
+ public QSPanelTopView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public QSPanelTopView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public QSPanelTopView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setFocusable(true);
+ mSettingsObserver = new SettingsObserver(new Handler());
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return mEditing;
+ }
+
+ public View getDropTarget() {
+ return mDropTarget;
+ }
+
+ public ImageView getDropTargetIcon() {
+ return mDropTargetIcon;
+ }
+
+ public View getBrightnessView() {
+ return mBrightnessView;
+ }
+
+ public View getAddTarget() {
+ return mAddTarget;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mDropTarget = findViewById(R.id.delete_container);
+ mDropTargetIcon = (ImageView) findViewById(R.id.delete_target);
+ mEditTileInstructionView = findViewById(R.id.edit_container);
+ mBrightnessView = findViewById(R.id.brightness_container);
+ mToastView = (TextView) findViewById(R.id.qs_toast);
+ mAddTarget = findViewById(R.id.add_target);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int width = MeasureSpec.getSize(widthMeasureSpec);
+ mBrightnessView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED);
+ mEditTileInstructionView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED);
+ mToastView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED);
+
+ // if we are showing a brightness slider, always fit to that, otherwise only
+ // declare a height when editing.
+ int dh = mHasBrightnessSliderToDisplay ? mBrightnessView.getMeasuredHeight()
+ : mEditing ? mEditTileInstructionView.getMeasuredHeight() : 0;
+
+ mDropTarget.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh));
+ mEditTileInstructionView.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh));
+ mToastView.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh));
+
+ setMeasuredDimension(width, dh);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ boolean animateToState = !isLaidOut();
+ super.onLayout(changed, left, top, right, bottom);
+ if (animateToState) {
+ goToState();
+ }
+ }
+
+ public void setEditing(boolean editing, boolean skipAnim) {
+ mEditing = editing;
+ if (editing) {
+ mDisplayingInstructions = true;
+ mDisplayingTrash = false;
+ } else {
+ mDisplayingInstructions = false;
+ mDisplayingTrash = false;
+ }
+ if (skipAnim) {
+ goToState();
+ } else {
+ animateToState();
+ }
+ }
+
+ public void onStopDrag() {
+ mDisplayingTrash = false;
+ animateToState();
+ }
+
+ public void onStartDrag() {
+ mDisplayingTrash = true;
+ animateToState();
+ }
+
+ public void setDropIcon(int resourceId, int colorResourceId) {
+ mDropTargetIcon.setImageResource(resourceId);
+ final Drawable drawable = mDropTargetIcon.getDrawable();
+
+ DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_ATOP);
+ DrawableCompat.setTint(drawable, mContext.getColor(colorResourceId));
+
+ if (drawable instanceof Animatable) {
+ ((Animatable) drawable).start();
+ }
+ }
+
+ public void toast(int textStrResId) {
+ mDisplayingToast = true;
+ mToastView.setText(textStrResId);
+ animateToState();
+ }
+
+ private Runnable mAnimateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ mAnimator = new AnimatorSet();
+
+ final boolean showToast = mDisplayingToast;
+ final boolean showTrash = mDisplayingTrash && !mDisplayingToast;
+ final boolean showBrightness = !mEditing && !mDisplayingToast;
+ final boolean showInstructions = mEditing
+ && mDisplayingInstructions
+ && !mDisplayingTrash
+ && !mDisplayingToast;
+
+ /*Log.d(TAG, "animating to state: "
+ + " showBrightness: " + showBrightness
+ + " showInstructions: " + showInstructions
+ + " showTrash: " + showTrash
+ + " showToast: " + showToast
+ );*/
+
+ final Animator brightnessAnimator = showBrightnessSlider(showBrightness);
+ final Animator instructionAnimator = showInstructions(showInstructions);
+ final Animator trashAnimator = showTrash(showTrash);
+ final Animator toastAnimator = showToast(showToast);
+
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // if the view is already visible, keep it visible on animation start
+ // to animate it out, otherwise set it as invisible (to not affect view height)
+ mEditTileInstructionView.setVisibility(
+ getVisibilityForAnimation(mEditTileInstructionView, showInstructions));
+ mDropTarget.setVisibility(
+ getVisibilityForAnimation(mDropTarget, showTrash));
+ mToastView.setVisibility(
+ getVisibilityForAnimation(mToastView, showToast));
+ if (mHasBrightnessSliderToDisplay) {
+ mBrightnessView.setVisibility(
+ getVisibilityForAnimation(mBrightnessView, showBrightness));
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mToastView.setVisibility(showToast ? View.VISIBLE : View.GONE);
+ mEditTileInstructionView.setVisibility(showInstructions
+ ? View.VISIBLE : View.GONE);
+ mDropTarget.setVisibility(showTrash ? View.VISIBLE : View.GONE);
+ if (mHasBrightnessSliderToDisplay) {
+ mBrightnessView.setVisibility(showBrightness ? View.VISIBLE : View.GONE);
+ }
+
+ mAnimator = null;
+
+ requestLayout();
+
+ if (showToast) {
+ mToastView.bringToFront();
+ mToastView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mDisplayingToast = false;
+ animateToState();
+ }
+ }, TOAST_DURATION);
+ }
+ }
+ });
+
+ mAnimator.setDuration(mSkipAnimations ? 0 : 500);
+ mAnimator.setInterpolator(new FastOutSlowInInterpolator());
+ mAnimator.setStartDelay(mSkipAnimations ? 0 : 100);
+ mAnimator.playTogether(instructionAnimator, trashAnimator,
+ brightnessAnimator, toastAnimator);
+ mAnimator.start();
+ }
+ };
+
+ private int getVisibilityForAnimation(View view, boolean show) {
+ if (show || view.getVisibility() != View.GONE) {
+ return View.VISIBLE;
+ }
+ return View.INVISIBLE;
+ }
+
+ private void animateToState() {
+ mSkipAnimations = false;
+ post(mAnimateRunnable);
+ }
+
+ private void goToState() {
+ mSkipAnimations = true;
+ post(mAnimateRunnable);
+ }
+
+ private Animator animateView(View v, boolean show) {
+ return ObjectAnimator.ofFloat(v, "translationY", show ? 0 : -getMeasuredHeight());
+ }
+
+ private Animator showBrightnessSlider(boolean show) {
+ return animateView(mBrightnessView, show);
+ }
+
+ private Animator showInstructions(boolean show) {
+ return animateView(mEditTileInstructionView, show);
+ }
+
+ private Animator showTrash(boolean show) {
+ return animateView(mDropTarget, show);
+ }
+
+ private Animator showToast(boolean show) {
+ return animateView(mToastView, show);
+ }
+
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (mListening) {
+ mSettingsObserver.observe();
+ } else {
+ mSettingsObserver.unobserve();
+ }
+
+ }
+
+ class SettingsObserver extends UserContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.QS_SHOW_BRIGHTNESS_SLIDER), false, this, UserHandle.USER_ALL);
+ update();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ int currentUserId = ActivityManager.getCurrentUser();
+ boolean showSlider = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.QS_SHOW_BRIGHTNESS_SLIDER, 1, currentUserId) == 1;
+ if (showSlider != mHasBrightnessSliderToDisplay) {
+ if (mAnimator != null) {
+ mAnimator.cancel(); // cancel everything we're animating
+ mAnimator = null;
+ }
+ mHasBrightnessSliderToDisplay = showSlider;
+ if (mBrightnessView != null) {
+ mBrightnessView.setVisibility(showSlider ? View.VISIBLE : View.GONE);
+
+ // as per showBrightnessSlider() in QSPanel.java, we look it up on-the-go
+ ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
+ if (brightnessSlider != null) {
+ brightnessSlider.setVisibility(showSlider ? View.VISIBLE : View.GONE);
+ }
+
+ }
+ getParent().requestLayout();
+ animateToState();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java
new file mode 100644
index 0000000..7766ca4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs;
+
+import android.annotation.Nullable;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+
+public class QSSettings extends ScrollView {
+
+ private QSTileHost mHost;
+
+ private boolean mAdapterEditingState;
+
+ public QSSettings(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ setFillViewport(true);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ findViewById(R.id.reset_tiles).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ initiateTileReset();
+ }
+ });
+ }
+
+ private void initiateTileReset() {
+ final AlertDialog d = new AlertDialog.Builder(mContext)
+ .setMessage(R.string.qs_tiles_reset_confirmation)
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(com.android.internal.R.string.reset,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mHost.initiateReset();
+ }
+ }).create();
+ SystemUIDialog.makeSystemUIDialog(d);
+ d.show();
+ }
+
+ public void setHost(QSTileHost host) {
+ mHost = host;
+ }
+
+ public boolean getAdapterEditingState() {
+ return mAdapterEditingState;
+ }
+
+ public void setAdapterEditingState(boolean editing) {
+ this.mAdapterEditingState = editing;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index e4a37fb..2d62724 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -20,7 +20,9 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Animatable;
+import android.graphics.Bitmap;
import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
@@ -30,6 +32,7 @@ import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.RemoteViews;
import com.android.systemui.qs.QSTile.State;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
@@ -41,6 +44,7 @@ import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.util.Collection;
import java.util.Objects;
@@ -85,7 +89,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
mHandler = new H(host.getLooper());
}
- public boolean supportsDualTargets() {
+ public boolean hasDualTargetsDetails() {
return false;
}
@@ -106,6 +110,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
Boolean getToggleState();
View createDetailView(Context context, View convertView, ViewGroup parent);
Intent getSettingsIntent();
+ StatusBarPanelCustomTile getCustomTile();
void setToggleState(boolean state);
int getMetricsCategory();
}
@@ -320,10 +325,12 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
public interface Host {
+ void removeCustomTile(StatusBarPanelCustomTile customTile);
void startActivityDismissingKeyguard(Intent intent);
void startActivityDismissingKeyguard(PendingIntent intent);
void warn(String message, Throwable t);
void collapsePanels();
+ RemoteViews.OnClickHandler getOnClickHandler();
Looper getLooper();
Context getContext();
Collection<QSTile<?>> getTiles();
@@ -337,9 +344,17 @@ public abstract class QSTile<TState extends State> implements Listenable {
CastController getCastController();
FlashlightController getFlashlightController();
KeyguardMonitor getKeyguardMonitor();
+ boolean isEditing();
+ void setEditing(boolean editing);
+ void resetTiles();
+ void goToSettingsPage();
public interface Callback {
void onTilesChanged();
+ void setEditing(boolean editing);
+ boolean isEditing();
+ void goToSettingsPage();
+ void resetTiles();
}
}
@@ -352,6 +367,42 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
}
+ protected class ExternalIcon extends AnimationIcon {
+ private Context mPackageContext;
+ private String mPkg;
+ private int mResId;
+
+ public ExternalIcon(String pkg, int resId) {
+ super(resId);
+ mPkg = pkg;
+ mResId = resId;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ // Get the drawable from the package context
+ Drawable d = null;
+ try {
+ d = super.getDrawable(getPackageContext());
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + mPkg + " id=" + mResId, t);
+ }
+ return d;
+ }
+
+ private Context getPackageContext() {
+ if (mPackageContext == null) {
+ try {
+ mPackageContext = mContext.createPackageContext(mPkg, 0);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error creating package context" + mPkg, t);
+ return null;
+ }
+ }
+ return mPackageContext;
+ }
+ }
+
public static class ResourceIcon extends Icon {
private static final SparseArray<Icon> ICONS = new SparseArray<Icon>();
@@ -390,6 +441,21 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
}
+ protected class ExternalBitmapIcon extends Icon {
+ private Bitmap mBitmap;
+
+ public ExternalBitmapIcon(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ // This is gross
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), mBitmap);
+ return bitmapDrawable;
+ }
+ }
+
protected class AnimationIcon extends ResourceIcon {
private boolean mAllowAnimation;
@@ -404,13 +470,14 @@ public abstract class QSTile<TState extends State> implements Listenable {
@Override
public Drawable getDrawable(Context context) {
// workaround: get a clean state for every new AVD
- final AnimatedVectorDrawable d = (AnimatedVectorDrawable) context.getDrawable(mResId)
- .getConstantState().newDrawable();
- d.start();
- if (mAllowAnimation) {
- mAllowAnimation = false;
- } else {
- d.stop(); // skip directly to end state
+ final Drawable d = super.getDrawable(context).getConstantState().newDrawable();
+ if (d instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable)d).start();
+ if (mAllowAnimation) {
+ mAllowAnimation = false;
+ } else {
+ ((AnimatedVectorDrawable)d).stop(); // skip directly to end state
+ }
}
return d;
}
@@ -431,6 +498,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
public static class State {
public boolean visible;
+ public boolean enabled = true;
public Icon icon;
public String label;
public String contentDescription;
@@ -441,6 +509,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
if (other == null) throw new IllegalArgumentException();
if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
final boolean changed = other.visible != visible
+ || !Objects.equals(other.enabled, enabled)
|| !Objects.equals(other.icon, icon)
|| !Objects.equals(other.label, label)
|| !Objects.equals(other.contentDescription, contentDescription)
@@ -448,6 +517,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
|| !Objects.equals(other.dualLabelContentDescription,
dualLabelContentDescription);
other.visible = visible;
+ other.enabled = enabled;
other.icon = icon;
other.label = label;
other.contentDescription = contentDescription;
@@ -464,6 +534,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
protected StringBuilder toStringBuilder() {
final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
sb.append("visible=").append(visible);
+ sb.append(",enabled=").append(enabled);
sb.append(",icon=").append(icon);
sb.append(",label=").append(label);
sb.append(",contentDescription=").append(contentDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 6d26a3b..7c63782 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +17,13 @@
package com.android.systemui.qs;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
@@ -27,6 +31,7 @@ import android.graphics.drawable.RippleDrawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.util.Log;
import android.util.MathUtils;
import android.util.TypedValue;
import android.view.Gravity;
@@ -48,6 +53,8 @@ public class QSTileView extends ViewGroup {
private static final Typeface CONDENSED = Typeface.create("sans-serif-condensed",
Typeface.NORMAL);
+ private static final String TAG = "QSTileView";
+
protected final Context mContext;
private final View mIcon;
private final View mDivider;
@@ -62,6 +69,7 @@ public class QSTileView extends ViewGroup {
private TextView mLabel;
private QSDualTileLabel mDualLabel;
private boolean mDual;
+ private boolean mDualDetails;
private OnClickListener mClickPrimary;
private OnClickListener mClickSecondary;
private OnLongClickListener mLongClick;
@@ -124,31 +132,34 @@ public class QSTileView extends ViewGroup {
private void recreateLabel() {
CharSequence labelText = null;
CharSequence labelDescription = null;
- if (mLabel != null) {
+ if (mLabel != null && mLabel.isAttachedToWindow()) {
labelText = mLabel.getText();
removeView(mLabel);
- mLabel = null;
}
- if (mDualLabel != null) {
+ if (mDualLabel != null && mDualLabel.isAttachedToWindow()) {
labelText = mDualLabel.getText();
- labelDescription = mLabel.getContentDescription();
+ labelDescription = mDualLabel.getContentDescription();
removeView(mDualLabel);
- mDualLabel = null;
}
final Resources res = mContext.getResources();
if (mDual) {
- mDualLabel = new QSDualTileLabel(mContext);
- mDualLabel.setId(View.generateViewId());
- mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect);
- mDualLabel.setFirstLineCaret(mContext.getDrawable(R.drawable.qs_dual_tile_caret));
- mDualLabel.setTextColor(mContext.getColor(R.color.qs_tile_text));
- mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx);
- mDualLabel.setTypeface(CONDENSED);
- mDualLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- res.getDimensionPixelSize(R.dimen.qs_tile_text_size));
- mDualLabel.setClickable(true);
- mDualLabel.setOnClickListener(mClickSecondary);
- mDualLabel.setFocusable(true);
+ if (mDualLabel == null) {
+ mDualLabel = new QSDualTileLabel(mContext);
+ mDualLabel.setId(View.generateViewId());
+ mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect);
+ if (mDualDetails) {
+ mDualLabel.setFirstLineCaret(mContext.getDrawable(R.drawable.qs_dual_tile_caret));
+ }
+ mDualLabel.setTextColor(mContext.getColor(R.color.qs_tile_text));
+ mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx);
+ mDualLabel.setTypeface(CONDENSED);
+ mDualLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ res.getDimensionPixelSize(R.dimen.qs_tile_text_size));
+ mDualLabel.setClickable(true);
+ mDualLabel.setFocusable(true);
+ mDualLabel.setOnClickListener(mDualDetails ? mClickSecondary : mClickPrimary);
+ mDualLabel.setOnLongClickListener(mLongClick);
+ }
if (labelText != null) {
mDualLabel.setText(labelText);
}
@@ -158,15 +169,18 @@ public class QSTileView extends ViewGroup {
addView(mDualLabel);
mDualLabel.setAccessibilityTraversalAfter(mTopBackgroundView.getId());
} else {
- mLabel = new TextView(mContext);
- mLabel.setTextColor(mContext.getColor(R.color.qs_tile_text));
- mLabel.setGravity(Gravity.CENTER_HORIZONTAL);
- mLabel.setMinLines(2);
- mLabel.setPadding(0, 0, 0, 0);
- mLabel.setTypeface(CONDENSED);
- mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- res.getDimensionPixelSize(R.dimen.qs_tile_text_size));
- mLabel.setClickable(false);
+ if (mLabel == null) {
+ mLabel = new TextView(mContext);
+ mLabel.setTextColor(mContext.getColor(R.color.qs_tile_text));
+ mLabel.setGravity(Gravity.CENTER_HORIZONTAL);
+ mLabel.setMinLines(2);
+ mLabel.setPadding(0, 0, 0, 0);
+ mLabel.setTypeface(CONDENSED);
+ mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ res.getDimensionPixelSize(R.dimen.qs_tile_text_size));
+ mLabel.setClickable(false);
+ mLabel.setFocusable(false);
+ }
if (labelText != null) {
mLabel.setText(labelText);
}
@@ -174,39 +188,59 @@ public class QSTileView extends ViewGroup {
}
}
- public boolean setDual(boolean dual) {
+ public boolean isDual() {
+ return mDual;
+ }
+
+ public boolean setDual(boolean dual, boolean hasDetails) {
final boolean changed = dual != mDual;
mDual = dual;
+ mDualDetails = hasDetails;
if (changed) {
recreateLabel();
}
- if (mTileBackground instanceof RippleDrawable) {
- setRipple((RippleDrawable) mTileBackground);
- }
+
if (dual) {
mTopBackgroundView.setOnClickListener(mClickPrimary);
+ mTopBackgroundView.setOnLongClickListener(mLongClick);
setOnClickListener(null);
- setClickable(false);
+ setOnLongClickListener(null);
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
- mTopBackgroundView.setBackground(mTileBackground);
} else {
mTopBackgroundView.setOnClickListener(null);
- mTopBackgroundView.setClickable(false);
+ mTopBackgroundView.setOnLongClickListener(null);
setOnClickListener(mClickPrimary);
setOnLongClickListener(mLongClick);
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- setBackground(mTileBackground);
}
+ setTileBackground();
+ mTopBackgroundView.setClickable(dual);
mTopBackgroundView.setFocusable(dual);
+ setClickable(!dual);
setFocusable(!dual);
mDivider.setVisibility(dual ? VISIBLE : GONE);
+ mTopBackgroundView.setVisibility(dual ? VISIBLE : GONE);
+
+ if (changed) {
+ getParent().requestLayout();
+ }
postInvalidate();
return changed;
}
+ protected void setTileBackground() {
+ if (mTileBackground instanceof RippleDrawable) {
+ setRipple((RippleDrawable) mTileBackground);
+ } else {
+ setRipple(null);
+ }
+ mTopBackgroundView.setBackground(mDual ? mTileBackground : null);
+ setBackground(!mDual ? mTileBackground : null);
+ }
+
private void setRipple(RippleDrawable tileBackground) {
mRipple = tileBackground;
- if (getWidth() != 0) {
+ if (getWidth() != 0 && mRipple != null) {
updateRippleSize(getWidth(), getHeight());
}
}
@@ -225,7 +259,7 @@ public class QSTileView extends ViewGroup {
return icon;
}
- private Drawable newTileBackground() {
+ public Drawable newTileBackground() {
final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
final TypedArray ta = mContext.obtainStyledAttributes(attrs);
final Drawable d = ta.getDrawable(0);
@@ -285,7 +319,7 @@ public class QSTileView extends ViewGroup {
private void updateRippleSize(int width, int height) {
// center the touch feedback on the center of the icon, and dial it down a bit
final int cx = width / 2;
- final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() / 2 : height / 2;
+ final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() : height / 2;
final int rad = (int)(mIcon.getHeight() * 1.25f);
mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad);
}
@@ -302,9 +336,20 @@ public class QSTileView extends ViewGroup {
mDualLabel.setText(state.label);
mDualLabel.setContentDescription(state.dualLabelContentDescription);
mTopBackgroundView.setContentDescription(state.contentDescription);
+ if (!Objects.equals(state.enabled, mDualLabel.isEnabled())) {
+ mTopBackgroundView.setEnabled(state.enabled);
+ mDualLabel.setEnabled(state.enabled);
+ mDualLabel.setTextColor(mContext.getResources().getColor(state.enabled ?
+ R.color.qs_tile_text : R.color.qs_tile_text_disabled));
+ }
} else {
mLabel.setText(state.label);
setContentDescription(state.contentDescription);
+ if (!Objects.equals(state.enabled, mLabel.isEnabled())) {
+ mLabel.setEnabled(state.enabled);
+ mLabel.setTextColor(mContext.getResources().getColor(state.enabled ?
+ R.color.qs_tile_text : R.color.qs_tile_text_disabled));
+ }
}
}
@@ -323,6 +368,14 @@ public class QSTileView extends ViewGroup {
}
}
}
+ if (!Objects.equals(state.enabled, iv.isEnabled())) {
+ iv.setEnabled(state.enabled);
+ if (state.enabled) {
+ iv.setColorFilter(null);
+ } else {
+ iv.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
+ }
+ }
}
public void onStateChanged(QSTile.State state) {
@@ -349,6 +402,37 @@ public class QSTileView extends ViewGroup {
return lastView;
}
+ public void setEditing(boolean editing) {
+ if (mDual) {
+ if (mTopBackgroundView != null) {
+ mTopBackgroundView.setFocusable(!editing);
+ mTopBackgroundView.setClickable(!editing);
+ }
+ if (mDualLabel != null) {
+ mDualLabel.setFocusable(!editing);
+ mDualLabel.setClickable(!editing);
+ }
+ setClickable(editing);
+ setFocusable(editing);
+ } else {
+ if (mLabel != null) {
+ mLabel.setFocusable(!editing);
+ }
+ if (mRipple != null) {
+ mRipple.setVisible(!editing, false);
+ }
+ }
+
+ // clean up extra label view if needed
+ if (!editing) {
+ if (mDual && mLabel != null) {
+ mLabel = null;
+ } else if (!mDual && mDualLabel != null) {
+ mDualLabel = null;
+ }
+ }
+ }
+
private class H extends Handler {
private static final int STATE_CHANGED = 1;
public H() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java b/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java
new file mode 100644
index 0000000..3dc5d27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java
@@ -0,0 +1,105 @@
+package com.android.systemui.qs;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+
+public class QSViewPager extends ViewPager {
+
+ private static final String TAG = "QSViewPager";
+
+ protected static final float SCROLL_PERCENT = .10f;
+
+ QSDragPanel mDragPanel;
+
+ public QSViewPager(Context context) {
+ super(context);
+ }
+
+ public void setDragPanel(QSDragPanel p) {
+ mDragPanel = p;
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return mDragPanel.isEditing();
+ }
+
+ @Override
+ public boolean canScrollHorizontally(int direction) {
+ if (direction < 0
+ && mDragPanel.isDragging()
+ && getCurrentItem() == 1) {
+ // can't scroll left while not editing, OR dragging on the first page
+ return false;
+ }
+ return super.canScrollHorizontally(direction);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int height = 0;
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ int h = child.getMeasuredHeight();
+ if (h > height && !(child instanceof QSSettings)) height = h;
+ }
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ public void animatePagerTransition(final boolean forward) {
+ ValueAnimator animator = ValueAnimator.ofInt(0, getWidth());
+ animator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (isFakeDragging()) {
+ endFakeDrag();
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ if (isFakeDragging()) {
+ endFakeDrag();
+ }
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ });
+
+ animator.setInterpolator(new AccelerateInterpolator());
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+
+ private int oldDragPosition = 0;
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (isFakeDragging()) {
+ int dragPosition = (Integer) animation.getAnimatedValue();
+ int dragOffset = dragPosition - oldDragPosition;
+ oldDragPosition = dragPosition;
+ fakeDragBy(dragOffset * (forward ? -1 : 1));
+ }
+ }
+ });
+ if (beginFakeDrag()) {
+ animator.setDuration(500);
+ animator.start();
+ } else {
+ Log.e(TAG, "can't start fake drag?");
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java
new file mode 100644
index 0000000..283d617
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.NetworkUtils;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+
+import java.net.InetAddress;
+
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+public class AdbOverNetworkTile extends QSTile<QSTile.BooleanState> {
+
+ private boolean mListening;
+
+ private static final Intent SETTINGS_DEVELOPMENT =
+ new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ CMSettings.Secure.putIntForUser(mContext.getContentResolver(),
+ CMSettings.Secure.ADB_PORT, getState().value ? -1 : 5555,
+ UserHandle.USER_CURRENT);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(SETTINGS_DEVELOPMENT);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.visible = isAdbEnabled();
+ if (!state.visible) {
+ return;
+ }
+ state.value = isAdbNetworkEnabled();
+ if (state.value) {
+ WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+
+ if (wifiInfo != null) {
+ // if wifiInfo is not null, set the label to "hostAddress"
+ InetAddress address = NetworkUtils.intToInetAddress(wifiInfo.getIpAddress());
+ state.label = address.getHostAddress();
+ } else {
+ // if wifiInfo is null, set the label without host address
+ state.label = mContext.getString(R.string.quick_settings_network_adb_label);
+ }
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_network_adb_on);
+ } else {
+ // Otherwise set the disabled label and icon
+ state.label = mContext.getString(R.string.quick_settings_network_adb_label);
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_network_adb_off);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_ADB_OVER_NETWORK;
+ }
+
+ private boolean isAdbEnabled() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Global.ADB_ENABLED, 0) > 0;
+ }
+
+ private boolean isAdbNetworkEnabled() {
+ return CMSettings.Secure.getInt(mContext.getContentResolver(),
+ CMSettings.Secure.ADB_PORT, 0) > 0;
+ }
+
+ public AdbOverNetworkTile(Host host) {
+ super(host);
+ }
+
+ private ContentObserver mObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ refreshState();
+ }
+ };
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening != listening) {
+ mListening = listening;
+ if (listening) {
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT),
+ false, mObserver);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Global.ADB_ENABLED),
+ false, mObserver);
+ } else {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 49f8d1c..bf28dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
+import android.provider.Settings;
import android.provider.Settings.Global;
import com.android.internal.logging.MetricsLogger;
@@ -30,6 +32,9 @@ import com.android.systemui.qs.QSTile;
/** Quick settings tile: Airplane mode **/
public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent WIRELESS_SETTINGS = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+
private final AnimationIcon mEnable =
new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation);
private final AnimationIcon mDisable =
@@ -62,6 +67,11 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
mDisable.setAllowAnimation(true);
}
+ @Override
+ public void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(WIRELESS_SETTINGS);
+ }
+
private void setEnabled(boolean enabled) {
final ConnectivityManager mgr =
(ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java
new file mode 100644
index 0000000..cc08d02
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+
+import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.R;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/** Quick settings tile: Ambient Display **/
+public class AmbientDisplayTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent DISPLAY_SETTINGS = new Intent("android.settings.DISPLAY_SETTINGS");
+
+ private final SecureSetting mSetting;
+
+ public AmbientDisplayTile(Host host) {
+ super(host);
+
+ mSetting = new SecureSetting(mContext, mHandler, Secure.DOZE_ENABLED) {
+ @Override
+ protected void handleValueChanged(int value, boolean observedChange) {
+ handleRefreshState(value);
+ }
+ };
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ setEnabled(!mState.value);
+ refreshState();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(DISPLAY_SETTINGS);
+ }
+
+ private void setEnabled(boolean enabled) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.DOZE_ENABLED,
+ enabled ? 1 : 0);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue();
+ final boolean enable = value != 0;
+ state.value = enable;
+ state.visible = true;
+ state.label = mContext.getString(R.string.quick_settings_ambient_display_label);
+ if (enable) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_ambientdisplay_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_ambient_display_on);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_ambientdisplay_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_ambient_display_off);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_AMBIENT_DISPLAY;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_ambient_display_changed_on);
+ } else {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_ambient_display_changed_off);
+ }
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ // Do nothing
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
new file mode 100644
index 0000000..37d8d73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.provider.Settings;
+
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.R;
+
+import cyanogenmod.power.PerformanceManager;
+
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/** Quick settings tile: Battery saver **/
+public class BatterySaverTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent BATTERY_SETTINGS = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+
+ private final PowerManager mPm;
+ private final PerformanceManager mPerformanceManager;
+ private boolean mListening;
+
+ public BatterySaverTile(Host host) {
+ super(host);
+ mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mPerformanceManager = PerformanceManager.getInstance(mContext);
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void handleClick() {
+ mPm.setPowerSaveMode(!mState.value);
+ refreshState();
+ }
+
+ @Override
+ public void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(BATTERY_SETTINGS);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.value = mPm.isPowerSaveMode();
+ state.visible = mPerformanceManager.getNumberOfProfiles() == 0;
+ state.label = mContext.getString(R.string.quick_settings_battery_saver_label);
+ if (state.value) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_battery_saver_on);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_battery_saver_off);
+ }
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_battery_saver_changed_on);
+ } else {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_battery_saver_changed_off);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_BATTERY_SAVER;
+ }
+
+ private ContentObserver mObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ refreshState();
+ }
+ };
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+
+ if (listening) {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE),
+ false, mObserver);
+ } else {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index abce31f..a798e4e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,17 +25,25 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ListView;
import com.android.internal.logging.MetricsLogger;
+
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
+import com.android.systemui.qs.QSDetailItemsList;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BluetoothController;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.Set;
+import java.util.List;
/** Quick settings tile: Bluetooth **/
public class BluetoothTile extends QSTile<QSTile.BooleanState> {
@@ -50,7 +59,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
@Override
- public boolean supportsDualTargets() {
+ public boolean hasDualTargetsDetails() {
return true;
}
@@ -90,6 +99,11 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(BLUETOOTH_SETTINGS);
+ }
+
+ @Override
protected void handleUpdateState(BooleanState state, Object arg) {
final boolean supported = mController.isBluetoothSupported();
final boolean enabled = mController.isBluetoothEnabled();
@@ -165,8 +179,11 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
};
- private final class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
- private QSDetailItems mItems;
+ private final class BluetoothDetailAdapter implements DetailAdapter,
+ QSDetailItems.Callback, AdapterView.OnItemClickListener {
+ private QSDetailItemsList mItemsList;
+ private QSDetailItemsList.QSDetailListAdapter mAdapter;
+ private List<Item> mBluetoothItems = new ArrayList<>();
@Override
public int getTitle() {
@@ -184,6 +201,11 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsLogger.QS_BLUETOOTH_TOGGLE, state);
mController.setBluetoothEnabled(state);
@@ -197,29 +219,34 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
- mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
- mItems.setTagSuffix("Bluetooth");
- mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
+ mItemsList = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ ListView listView = mItemsList.getListView();
+ listView.setDivider(null);
+ listView.setOnItemClickListener(this);
+ listView.setAdapter(mAdapter =
+ new QSDetailItemsList.QSDetailListAdapter(context, mBluetoothItems));
+ mItemsList.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
R.string.quick_settings_bluetooth_detail_empty_text);
- mItems.setCallback(this);
- mItems.setMinHeightInItems(0);
+
updateItems();
- setItemsVisible(mState.value);
- return mItems;
+ return mItemsList;
}
public void setItemsVisible(boolean visible) {
- if (mItems == null) return;
- mItems.setItemsVisible(visible);
+ if (mAdapter == null) return;
+ if (visible) {
+ updateItems();
+ } else {
+ mBluetoothItems.clear();
+ }
+ mAdapter.notifyDataSetChanged();
}
private void updateItems() {
- if (mItems == null) return;
- Item[] items = null;
- final Collection<CachedBluetoothDevice> devices = mController.getDevices();
+ if (mAdapter == null) return;
+ final Collection<CachedBluetoothDevice> devices = mController.getDevices();
if (devices != null) {
- items = new Item[getBondedCount(devices)];
- int i = 0;
+ mBluetoothItems.clear();
for (CachedBluetoothDevice device : devices) {
if (device.getBondState() == BluetoothDevice.BOND_NONE) continue;
final Item item = new Item();
@@ -235,10 +262,10 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
item.line2 = mContext.getString(R.string.quick_settings_connecting);
}
item.tag = device;
- items[i++] = item;
+ mBluetoothItems.add(item);
}
}
- mItems.setItems(items);
+ mAdapter.notifyDataSetChanged();
}
private int getBondedCount(Collection<CachedBluetoothDevice> devices) {
@@ -253,12 +280,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
@Override
public void onDetailItemClick(Item item) {
- if (item == null || item.tag == null) return;
- final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
- if (device != null && device.getMaxConnectionState()
- == BluetoothProfile.STATE_DISCONNECTED) {
- mController.connect(device);
- }
+ // noop
}
@Override
@@ -269,5 +291,16 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
mController.disconnect(device);
}
}
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Item item = (Item) parent.getItemAtPosition(position);
+ if (item == null || item.tag == null) return;
+ final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
+ if (device != null && device.getMaxConnectionState()
+ == BluetoothProfile.STATE_DISCONNECTED) {
+ mController.connect(device);
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java
new file mode 100644
index 0000000..fb6ec42
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.CountDownTimer;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.Settings;
+
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.R;
+
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/** Quick settings tile: Caffeine **/
+public class CaffeineTile extends QSTile<QSTile.BooleanState> {
+
+ private final PowerManager.WakeLock mWakeLock;
+ private int mSecondsRemaining;
+ private int mDuration;
+ private static int[] DURATIONS = new int[] {
+ 5 * 60, // 5 min
+ 10 * 60, // 10 min
+ 30 * 60, // 30 min
+ -1, // infinity
+ };
+ private CountDownTimer mCountdownTimer = null;
+ public long mLastClickTime = -1;
+ private final Receiver mReceiver = new Receiver();
+ private boolean mListening;
+
+ public CaffeineTile(Host host) {
+ super(host);
+ mWakeLock = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE)).newWakeLock(
+ PowerManager.FULL_WAKE_LOCK, "CaffeineTile");
+ mReceiver.init();
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ stopCountDown();
+ mReceiver.destroy();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ }
+
+ @Override
+ public void handleClick() {
+ // If last user clicks < 5 seconds
+ // we cycle different duration
+ // otherwise toggle on/off
+ if (mWakeLock.isHeld() && (mLastClickTime != -1) &&
+ (SystemClock.elapsedRealtime() - mLastClickTime < 5000)) {
+ // cycle duration
+ mDuration++;
+ if (mDuration >= DURATIONS.length) {
+ // all durations cycled, turn if off
+ mDuration = -1;
+ stopCountDown();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ } else {
+ // change duration
+ startCountDown(DURATIONS[mDuration]);
+ if (!mWakeLock.isHeld()) {
+ mWakeLock.acquire();
+ }
+ }
+ } else {
+ // toggle
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ stopCountDown();
+ } else {
+ mWakeLock.acquire();
+ mDuration = 0;
+ startCountDown(DURATIONS[mDuration]);
+ }
+ }
+ mLastClickTime = SystemClock.elapsedRealtime();
+ refreshState();
+ }
+
+ private void startCountDown(long duration) {
+ stopCountDown();
+ mSecondsRemaining = (int)duration;
+ if (duration == -1) {
+ // infinity timing, no need to start timer
+ return;
+ }
+ mCountdownTimer = new CountDownTimer(duration * 1000, 1000) {
+
+ @Override
+ public void onTick(long millisUntilFinished) {
+ mSecondsRemaining = (int) (millisUntilFinished / 1000);
+ refreshState();
+ }
+
+ @Override
+ public void onFinish() {
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ refreshState();
+ }
+
+ }.start();
+ }
+
+ private void stopCountDown() {
+ if (mCountdownTimer != null) {
+ mCountdownTimer.cancel();
+ mCountdownTimer = null;
+ }
+ }
+
+ private String formatValueWithRemainingTime() {
+ if (mSecondsRemaining == -1) {
+ return "\u221E"; // infinity
+ }
+ return String.format("%02d:%02d",
+ mSecondsRemaining / 60 % 60, mSecondsRemaining % 60);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.value = mWakeLock.isHeld();
+ state.visible = true;
+ if (state.value) {
+ state.label = formatValueWithRemainingTime();
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_caffeine_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_caffeine_on);
+ } else {
+ state.label = mContext.getString(R.string.quick_settings_caffeine_label);
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_caffeine_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_caffeine_off);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_CAFFEINE;
+ }
+
+ private final class Receiver extends BroadcastReceiver {
+ public void init() {
+ // Register for Intent broadcasts for...
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ mContext.registerReceiver(this, filter, null, mHandler);
+ }
+
+ public void destroy() {
+ mContext.unregisterReceiver(this);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ // disable caffeine if user force off (power button)
+ stopCountDown();
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ refreshState();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 61695b2..f83bbf4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +33,7 @@ import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.util.LinkedHashMap;
import java.util.Set;
@@ -91,6 +93,16 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ protected void handleSecondaryClick() {
+ handleClick();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(CAST_SETTINGS);
+ }
+
+ @Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.visible = !mKeyguard.isSecure() || !mKeyguard.isShowing()
|| mKeyguard.canSkipBouncer();
@@ -129,6 +141,11 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
return null;
}
+ @Override
+ public boolean hasDualTargetsDetails() {
+ return true;
+ }
+
private String getDeviceName(CastDevice device) {
return device.name != null ? device.name
: mContext.getString(R.string.quick_settings_cast_device_default_name);
@@ -167,6 +184,11 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public void setToggleState(boolean state) {
// noop
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index f3ad9d8..038fa5e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +17,13 @@
package com.android.systemui.qs.tiles;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.UserHandle;
+import android.telephony.TelephonyManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -35,15 +39,23 @@ import com.android.systemui.statusbar.policy.NetworkController.MobileDataControl
import com.android.systemui.statusbar.policy.NetworkController.MobileDataController.DataUsageInfo;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
+import cyanogenmod.app.StatusBarPanelCustomTile;
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTile<QSTile.SignalState> {
- private static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
+
+ private static final Intent DATA_USAGE_SETTINGS = new Intent().setComponent(new ComponentName(
"com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
+ private static final Intent MOBILE_NETWORK_SETTINGS = new Intent(Intent.ACTION_MAIN)
+ .setComponent(new ComponentName("com.android.phone",
+ "com.android.phone.MobileNetworkSettings"));
+ private static final Intent MOBILE_NETWORK_SETTINGS_MSIM
+ = new Intent("com.android.settings.sim.SIM_SUB_INFO_SETTINGS");
private final NetworkController mController;
private final MobileDataController mDataController;
private final CellularDetailAdapter mDetailAdapter;
+ private final TelephonyManager mTelephonyManager;
private final CellSignalCallback mSignalCallback = new CellSignalCallback();
@@ -52,6 +64,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
mController = host.getNetworkController();
mDataController = mController.getMobileDataController();
mDetailAdapter = new CellularDetailAdapter();
+ mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
}
@Override
@@ -79,18 +92,40 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
}
@Override
+ protected void handleUserSwitch(int newUserId) {
+ if (newUserId != UserHandle.USER_OWNER) {
+ refreshState();
+ }
+ }
+
+ @Override
protected void handleClick() {
MetricsLogger.action(mContext, getMetricsCategory());
if (mDataController.isMobileDataSupported()) {
showDetail(true);
} else {
- mHost.startActivityDismissingKeyguard(CELLULAR_SETTINGS);
+ mHost.startActivityDismissingKeyguard(DATA_USAGE_SETTINGS);
+ }
+ }
+
+ @Override
+ protected void handleSecondaryClick() {
+ handleClick();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ if (mTelephonyManager.getDefault().getPhoneCount() > 1) {
+ mHost.startActivityDismissingKeyguard(MOBILE_NETWORK_SETTINGS_MSIM);
+ } else {
+ mHost.startActivityDismissingKeyguard(MOBILE_NETWORK_SETTINGS);
}
}
@Override
protected void handleUpdateState(SignalState state, Object arg) {
- state.visible = mController.hasMobileDataFeature();
+ state.visible = mController.hasMobileDataFeature()
+ && (ActivityManager.getCurrentUser() == UserHandle.USER_OWNER);
if (!state.visible) return;
CallbackInfo cb = (CallbackInfo) arg;
if (cb == null) {
@@ -112,7 +147,9 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
state.label = cb.enabled
? removeTrailingPeriod(cb.enabledDesc)
- : r.getString(R.string.quick_settings_rssi_emergency_only);
+ : mDataController.isMobileDataSupported() ?
+ r.getString(R.string.data_sim_not_configured) :
+ r.getString(R.string.quick_settings_rssi_emergency_only);
final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0)
? cb.signalContentDescription
@@ -131,6 +168,11 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
return MetricsLogger.QS_CELLULAR;
}
+ @Override
+ public boolean hasDualTargetsDetails() {
+ return true;
+ }
+
// Remove the period from the network name
public static String removeTrailingPeriod(String string) {
if (string == null) return null;
@@ -168,7 +210,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
@Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
- String description, boolean isWide, int subId) {
+ String description, boolean isWide, boolean showSeparateRoaming, int subId) {
if (qsIcon == null) {
// Not data sim, don't display.
return;
@@ -192,10 +234,14 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
// Make sure signal gets cleared out when no sims.
mInfo.mobileSignalIconId = 0;
mInfo.dataTypeIconId = 0;
- // Show a No SIMs description to avoid emergency calls message.
+ // Show a No SIMs description if we're incapable of supporting mobile data
+ // to avoid showing an emergency mode description. If we're still capable of
+ // supporting mobile data, notify the user that the data sim is not configured
+ // only relevant in MSIM scenario: CYNGNOS-2211
mInfo.enabled = true;
- mInfo.enabledDesc = mContext.getString(
- R.string.keyguard_missing_sim_message_short);
+ mInfo.enabledDesc = mDataController.isMobileDataSupported() ?
+ mContext.getString(R.string.data_sim_not_configured)
+ : mContext.getString(R.string.keyguard_missing_sim_message_short);
mInfo.signalContentDescription = mInfo.enabledDesc;
}
refreshState(mInfo);
@@ -214,6 +260,10 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
};
private final class CellularDetailAdapter implements DetailAdapter {
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
@Override
public int getTitle() {
@@ -229,7 +279,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
@Override
public Intent getSettingsIntent() {
- return CELLULAR_SETTINGS;
+ return DATA_USAGE_SETTINGS;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index c6fc6ff..04cc5dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +17,8 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
+import android.provider.Settings;
import android.provider.Settings.Secure;
import com.android.internal.logging.MetricsLogger;
@@ -28,6 +31,9 @@ import com.android.systemui.qs.UsageTracker;
/** Quick settings tile: Invert colors **/
public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
+ private static final Intent ACCESSIBILITY_SETTINGS = new Intent(
+ Settings.ACTION_ACCESSIBILITY_SETTINGS);
+
private final AnimationIcon mEnable
= new AnimationIcon(R.drawable.ic_invert_colors_enable_animation);
private final AnimationIcon mDisable
@@ -95,15 +101,18 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleLongClick() {
- if (mState.value) return; // don't allow usage reset if inversion is active
- final String title = mContext.getString(R.string.quick_settings_reset_confirmation_title,
- mState.label);
- mUsageTracker.showResetConfirmation(title, new Runnable() {
- @Override
- public void run() {
- refreshState();
- }
- });
+ if (mState.value) {
+ mHost.startActivityDismissingKeyguard(ACCESSIBILITY_SETTINGS);
+ } else {
+ final String title = mContext.getString(
+ R.string.quick_settings_reset_confirmation_title, mState.label);
+ mUsageTracker.showResetConfirmation(title, new Runnable() {
+ @Override
+ public void run() {
+ refreshState();
+ }
+ });
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java
new file mode 100644
index 0000000..f19e466
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSTileView;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+public class CompassTile extends QSTile<QSTile.BooleanState> implements SensorEventListener {
+ private final static float ALPHA = 0.97f;
+
+ private boolean mActive = false;
+
+ private SensorManager mSensorManager;
+ private Sensor mAccelerationSensor;
+ private Sensor mGeomagneticFieldSensor;
+
+ private float[] mAcceleration;
+ private float[] mGeomagnetic;
+
+ private ImageView mImage;
+ private boolean mListeningSensors;
+
+ public CompassTile(Host host) {
+ super(host);
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ mAccelerationSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ mGeomagneticFieldSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ setListeningSensors(false);
+ mSensorManager = null;
+ mImage = null;
+ }
+
+ @Override
+ public QSTileView createTileView(Context context) {
+ QSTileView tileView = super.createTileView(context);
+ mImage = (ImageView) tileView.findViewById(android.R.id.icon);
+ return tileView;
+ }
+
+ @Override
+ protected void handleClick() {
+ mActive = !mActive;
+ refreshState();
+ setListeningSensors(mActive);
+ }
+
+ private void setListeningSensors(boolean listening) {
+ if (listening == mListeningSensors) return;
+ mListeningSensors = listening;
+ if (mListeningSensors) {
+ mSensorManager.registerListener(
+ this, mAccelerationSensor, SensorManager.SENSOR_DELAY_GAME);
+ mSensorManager.registerListener(
+ this, mGeomagneticFieldSensor, SensorManager.SENSOR_DELAY_GAME);
+ } else {
+ mSensorManager.unregisterListener(this);
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ Float degrees = arg == null ? 0 :(float) arg;
+
+ state.visible = true;
+ state.value = mActive;
+
+ if (state.value) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_compass_on);
+ if (arg != null) {
+ state.label = formatValueWithCardinalDirection(degrees);
+
+ float target = 360 - degrees;
+ float relative = target - mImage.getRotation();
+ if (relative > 180) relative -= 360;
+
+ mImage.setRotation(mImage.getRotation() + relative / 2);
+
+ } else {
+ state.label = mContext.getString(R.string.quick_settings_compass_init);
+ mImage.setRotation(0);
+ }
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_compass_off);
+ state.label = mContext.getString(R.string.quick_settings_compass_label);
+ mImage.setRotation(0);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_COMPASS;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (!listening) {
+ setListeningSensors(false);
+ mActive = false;
+ }
+ }
+
+ private String formatValueWithCardinalDirection(float degree) {
+ int cardinalDirectionIndex = (int) (Math.floor(((degree - 22.5) % 360) / 45) + 1) % 8;
+ String[] cardinalDirections = mContext.getResources().getStringArray(
+ R.array.cardinal_directions);
+
+ return mContext.getString(R.string.quick_settings_compass_value, degree,
+ cardinalDirections[cardinalDirectionIndex]);
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ float[] values;
+ if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+ if (mAcceleration == null) {
+ mAcceleration = event.values.clone();
+ }
+
+ values = mAcceleration;
+ } else {
+ // Magnetic field sensor
+ if (mGeomagnetic == null) {
+ mGeomagnetic = event.values.clone();
+ }
+
+ values = mGeomagnetic;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ values[i] = ALPHA * values[i] + (1 - ALPHA) * event.values[i];
+ }
+
+ if (!mActive || !mListeningSensors || mAcceleration == null || mGeomagnetic == null) {
+ // Nothing to do at this moment
+ return;
+ }
+
+ float R[] = new float[9];
+ float I[] = new float[9];
+ if (!SensorManager.getRotationMatrix(R, I, mAcceleration, mGeomagnetic)) {
+ // Rotation matrix couldn't be calculated
+ return;
+ }
+
+ // Get the current orientation
+ float[] orientation = new float[3];
+ SensorManager.getOrientation(R, orientation);
+
+ // Convert azimuth to degrees
+ Float newDegree = Float.valueOf((float) Math.toDegrees(orientation[0]));
+ newDegree = (newDegree + 360) % 360;
+
+ refreshState(newDegree);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // noop
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java
new file mode 100644
index 0000000..d09ca92
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.ThemeConfig;
+import android.net.Uri;
+import android.os.Process;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+
+import com.android.systemui.qs.QSDetailItemsGrid;
+import com.android.systemui.qs.QSDetailItemsList;
+import cyanogenmod.app.CustomTile;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+import java.util.Arrays;
+
+public class CustomQSTile extends QSTile<QSTile.State> {
+
+ private CustomTile.ExpandedStyle mExpandedStyle;
+ private PendingIntent mOnClick;
+ private PendingIntent mOnLongClick;
+ private Uri mOnClickUri;
+ private int mCurrentUserId;
+ private StatusBarPanelCustomTile mTile;
+ private CustomQSDetailAdapter mDetailAdapter;
+ private boolean mCollapsePanel;
+
+ public CustomQSTile(Host host, StatusBarPanelCustomTile tile) {
+ super(host);
+ mTile = tile;
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ }
+
+ @Override
+ protected State newTileState() {
+ return new State();
+ }
+
+ @Override
+ protected void handleUserSwitch(int newUserId) {
+ super.handleUserSwitch(newUserId);
+ mCurrentUserId = newUserId;
+ }
+
+ public void update(StatusBarPanelCustomTile customTile) {
+ refreshState(customTile);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ if (mOnLongClick != null) {
+ if (mOnLongClick.isActivity()) {
+ getHost().collapsePanels();
+ }
+ try {
+ mOnLongClick.send();
+ } catch (Throwable e) {
+ Log.w(TAG, "Error sending long click intent", e);
+ }
+ } else if (mExpandedStyle == null) {
+ showDetail(true);
+ }
+ }
+
+ @Override
+ protected void handleClick() {
+ try {
+ if (mExpandedStyle != null &&
+ mExpandedStyle.getStyle() != CustomTile.ExpandedStyle.NO_STYLE) {
+ showDetail(true);
+ return;
+ }
+ if (mCollapsePanel) {
+ mHost.collapsePanels();
+ }
+ if (mOnClick != null) {
+ mOnClick.send();
+ } else if (mOnClickUri != null) {
+ mHost.collapsePanels();
+ final Intent intent = new Intent().setData(mOnClickUri);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
+ }
+ } catch (Throwable t) {
+ Log.w(TAG, "Error sending click intent", t);
+ }
+ }
+
+ public StatusBarPanelCustomTile getTile() {
+ return mTile;
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ if (arg instanceof StatusBarPanelCustomTile) {
+ mTile = (StatusBarPanelCustomTile) arg;
+ }
+ final CustomTile customTile = mTile.getCustomTile();
+ state.contentDescription = customTile.contentDescription;
+ state.label = customTile.label;
+ state.visible = true;
+ final int iconId = customTile.icon;
+ if (iconId != 0 && (customTile.remoteIcon == null)) {
+ final String iconPackage = mTile.getResPkg();
+ if (!TextUtils.isEmpty(iconPackage)) {
+ state.icon = new ExternalIcon(iconPackage, iconId);
+ }
+ } else {
+ state.icon = new ExternalBitmapIcon(customTile.remoteIcon);
+ }
+ mOnClick = customTile.onClick;
+ mOnLongClick = customTile.onLongClick;
+ mOnClickUri = customTile.onClickUri;
+ mExpandedStyle = customTile.expandedStyle;
+ mCollapsePanel = customTile.collapsePanel;
+ mDetailAdapter = new CustomQSDetailAdapter();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_CUSTOM_QS;
+ }
+
+ private boolean isDynamicTile() {
+ return mTile.getPackage().equals(mContext.getPackageName())
+ || mTile.getUid() == Process.SYSTEM_UID;
+ }
+
+ private class CustomQSDetailAdapter implements DetailAdapter, AdapterView.OnItemClickListener,
+ QSDetailItemsGrid.QSDetailItemsGridAdapter.OnPseudoGriditemClickListener {
+ private QSDetailItemsList.QSCustomDetailListAdapter mListAdapter;
+ private QSDetailItemsGrid.QSDetailItemsGridAdapter mGridAdapter;
+
+ public int getTitle() {
+ if (isDynamicTile()) {
+ return mContext.getResources().getIdentifier(
+ String.format("dynamic_qs_tile_%s_label", mTile.getTag()),
+ "string", mContext.getPackageName());
+ }
+ return R.string.quick_settings_custom_tile_detail_title;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+
+ @Override
+ public Intent getSettingsIntent() {
+ return mTile.getCustomTile().onSettingsClick;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return mTile;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_CUSTOM_QS_DETAIL;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ View rootView = null;
+ if (mExpandedStyle == null) {
+ rootView = (LinearLayout) LayoutInflater.from(context)
+ .inflate(R.layout.qs_custom_detail, parent, false);
+ ImageView imageView = (ImageView)
+ rootView.findViewById(R.id.custom_qs_tile_icon);
+ TextView customTileTitle = (TextView)
+ rootView.findViewById(R.id.custom_qs_tile_title);
+ TextView customTilePkg = (TextView) rootView
+ .findViewById(R.id.custom_qs_tile_package);
+ TextView customTileContentDesc = (TextView) rootView
+ .findViewById(R.id.custom_qs_tile_content_description);
+ // icon is cached in state, fetch it
+ imageView.setImageDrawable(getState().icon.getDrawable(mContext));
+ customTileTitle.setText(mTile.getCustomTile().label);
+ if (isDynamicTile()) {
+ customTilePkg.setText(R.string.quick_settings_dynamic_tile_detail_title);
+ } else {
+ customTilePkg.setText(mTile.getPackage());
+ customTileContentDesc.setText(mTile.getCustomTile().contentDescription);
+ }
+ } else {
+ switch (mExpandedStyle.getStyle()) {
+ case CustomTile.ExpandedStyle.GRID_STYLE:
+ rootView = QSDetailItemsGrid.inflate(context, parent, false);
+ mGridAdapter = ((QSDetailItemsGrid) rootView)
+ .createAndSetAdapter(mTile.getPackage(),
+ mExpandedStyle.getExpandedItems());
+ mGridAdapter.setOnPseudoGridItemClickListener(this);
+ break;
+ case CustomTile.ExpandedStyle.REMOTE_STYLE:
+ rootView = (LinearLayout) LayoutInflater.from(context)
+ .inflate(R.layout.qs_custom_detail_remote, parent, false);
+ RemoteViews remoteViews = mExpandedStyle.getContentViews();
+ if (remoteViews != null) {
+ View localView = mTile.getCustomTile().expandedStyle.getContentViews()
+ .apply(context, (ViewGroup) rootView,
+ mHost.getOnClickHandler(), getThemePackageName());
+ ((LinearLayout) rootView).addView(localView);
+ } else {
+ Log.d(TAG, "Unable to add null remoteview for " + mTile.getOpPkg());
+ }
+ break;
+ case CustomTile.ExpandedStyle.LIST_STYLE:
+ default:
+ rootView = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ ListView listView = ((QSDetailItemsList) rootView).getListView();
+ listView.setDivider(null);
+ listView.setOnItemClickListener(this);
+ listView.setAdapter(mListAdapter =
+ new QSDetailItemsList.QSCustomDetailListAdapter(mTile.getPackage(),
+ context, Arrays.asList(mExpandedStyle.getExpandedItems())));
+ break;
+ }
+ }
+ return rootView;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
+ CustomTile.ExpandedItem item = mListAdapter.getItem(position);
+ sendEvent(item.onClickPendingIntent);
+ }
+
+ @Override
+ public void onPsuedoGridItemClick(View view, CustomTile.ExpandedItem item) {
+ sendEvent(item.onClickPendingIntent);
+ }
+
+ private void sendEvent(PendingIntent intent) {
+ try {
+ if (intent.isActivity()) {
+ mHost.collapsePanels();
+ }
+ intent.send();
+ } catch (PendingIntent.CanceledException e) {
+ //
+ }
+ }
+
+ private String getThemePackageName() {
+ final Configuration config = mContext.getResources().getConfiguration();
+ final ThemeConfig themeConfig = config != null ? config.themeConfig : null;
+ return themeConfig != null ? themeConfig.getOverlayForStatusBar() : null;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 781ab1c..0d43f8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +38,7 @@ import com.android.systemui.SysUIToast;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
+import cyanogenmod.app.StatusBarPanelCustomTile;
/** Quick settings tile: Do not disturb **/
public class DndTile extends QSTile<QSTile.BooleanState> {
@@ -121,6 +123,16 @@ public class DndTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ protected void handleSecondaryClick() {
+ handleClick();
+ }
+
+ @Override
+ public void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(ZEN_SETTINGS);
+ }
+
+ @Override
protected void handleUpdateState(BooleanState state, Object arg) {
final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
final boolean newValue = zen != Global.ZEN_MODE_OFF;
@@ -129,7 +141,7 @@ public class DndTile extends QSTile<QSTile.BooleanState> {
state.visible = isVisible(mContext);
switch (zen) {
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
- state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on_priority);
state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd_priority_on);
@@ -188,6 +200,11 @@ public class DndTile extends QSTile<QSTile.BooleanState> {
}
}
+ @Override
+ public boolean hasDualTargetsDetails() {
+ return true;
+ }
+
private final OnSharedPreferenceChangeListener mPrefListener
= new OnSharedPreferenceChangeListener() {
@Override
@@ -233,6 +250,11 @@ public class DndTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsLogger.QS_DND_TOGGLE, state);
if (!state) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java
new file mode 100644
index 0000000..7173786
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+public class EditTile extends QSTile<QSTile.BooleanState> implements KeyguardMonitor.Callback {
+
+ private boolean mListening;
+
+ public EditTile(Host host) {
+ super(host);
+ refreshState();
+ }
+
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ getHost().setEditing(!mState.value);
+ refreshState(!mState.value);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ getHost().goToSettingsPage();
+ refreshState(true);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ final boolean showing = getHost().getKeyguardMonitor().isShowing();
+ final boolean secure = getHost().getKeyguardMonitor().isSecure();
+ state.visible = !showing || !secure;
+ state.enabled = !showing;
+ state.label = mContext.getString(R.string.quick_settings_edit_label);
+
+ if (arg instanceof Boolean) {
+ state.value = (boolean) arg;
+ } else {
+ state.value = getHost().isEditing();
+ }
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_edit_tiles);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_EDIT;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ // TODO
+ return null;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (mListening) {
+ mHost.getKeyguardMonitor().addCallback(this);
+ } else {
+ mHost.getKeyguardMonitor().removeCallback(this);
+ }
+ refreshState();
+ }
+
+ @Override
+ public void onKeyguardChanged() {
+ refreshState();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java
new file mode 100644
index 0000000..d30bd91
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+
+import com.android.systemui.qs.GlobalSetting;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.R;
+
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/** Quick settings tile: Heads up **/
+public class HeadsUpTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent NOTIFICATION_SETTINGS =
+ new Intent("android.settings.NOTIFICATION_MANAGER");
+
+ private final GlobalSetting mSetting;
+
+ public HeadsUpTile(Host host) {
+ super(host);
+
+ mSetting = new GlobalSetting(mContext, mHandler, Global.HEADS_UP_NOTIFICATIONS_ENABLED) {
+ @Override
+ protected void handleValueChanged(int value) {
+ handleRefreshState(value);
+ }
+ };
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ setEnabled(!mState.value);
+ refreshState();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(NOTIFICATION_SETTINGS);
+ }
+
+ private void setEnabled(boolean enabled) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+ enabled ? 1 : 0);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue();
+ final boolean headsUp = value != 0;
+ state.value = headsUp;
+ state.visible = true;
+ state.label = mContext.getString(R.string.quick_settings_heads_up_label);
+ if (headsUp) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_heads_up_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_heads_up_on);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_heads_up_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_heads_up_off);
+ }
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_heads_up_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_heads_up_changed_off);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_HEADS_UP;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ // Do nothing
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 7b83e6a..25a7fb7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,18 +18,30 @@
package com.android.systemui.qs.tiles;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiDevice;
+import android.provider.Settings;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.UsageTracker;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.HotspotController;
+import java.util.List;
+
/** Quick settings tile: Hotspot **/
public class HotspotTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
+ "com.android.settings", "com.android.settings.TetherSettings"));
+
private final AnimationIcon mEnable =
new AnimationIcon(R.drawable.ic_hotspot_enable_animation);
private final AnimationIcon mDisable =
@@ -36,12 +49,16 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
private final HotspotController mController;
private final Callback mCallback = new Callback();
private final UsageTracker mUsageTracker;
+ private final ConnectivityManager mConnectivityManager;
+ private boolean mListening;
+ private int mNumConnectedClients = 0;
public HotspotTile(Host host) {
super(host);
mController = host.getHotspotController();
mUsageTracker = newUsageTracker(host.getContext());
mUsageTracker.setListening(true);
+ mConnectivityManager = host.getContext().getSystemService(ConnectivityManager.class);
}
@Override
@@ -57,15 +74,31 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
@Override
public void setListening(boolean listening) {
+ if (mListening == listening) return;
if (listening) {
mController.addCallback(mCallback);
+ mContext.registerReceiver(mTetherConnectStateChangedReceiver,
+ new IntentFilter(ConnectivityManager.TETHER_CONNECT_STATE_CHANGED));
} else {
mController.removeCallback(mCallback);
+ mContext.unregisterReceiver(mTetherConnectStateChangedReceiver);
}
+ mListening = listening;
}
@Override
protected void handleClick() {
+ boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
+ if (airplaneMode) {
+ SystemUIDialog d = new SystemUIDialog(mContext);
+ d.setTitle(R.string.quick_settings_hotspot_label);
+ d.setMessage(R.string.hotspot_apm_message);
+ d.setPositiveButton(com.android.internal.R.string.ok, null);
+ d.setShowForAllUsers(true);
+ d.show();
+ return;
+ }
final boolean isEnabled = (Boolean) mState.value;
MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled);
mController.setHotspotEnabled(!isEnabled);
@@ -75,27 +108,36 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleLongClick() {
- if (mState.value) return; // don't allow usage reset if hotspot is active
- final String title = mContext.getString(R.string.quick_settings_reset_confirmation_title,
- mState.label);
- mUsageTracker.showResetConfirmation(title, new Runnable() {
- @Override
- public void run() {
- refreshState();
- }
- });
+ if (mState.value) {
+ mHost.startActivityDismissingKeyguard(TETHER_SETTINGS);
+ } else {
+ final String title = mContext.getString(
+ R.string.quick_settings_reset_confirmation_title, mState.label);
+ mUsageTracker.showResetConfirmation(title, new Runnable() {
+ @Override
+ public void run() {
+ refreshState();
+ }
+ });
+ }
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed();
- state.label = mContext.getString(R.string.quick_settings_hotspot_label);
if (arg instanceof Boolean) {
state.value = (boolean) arg;
} else {
state.value = mController.isHotspotEnabled();
}
+ if (state.visible && state.value) {
+ state.label = mContext.getResources().getQuantityString(
+ R.plurals.wifi_hotspot_connected_clients_label, mNumConnectedClients,
+ mNumConnectedClients);
+ } else {
+ state.label = mContext.getString(R.string.quick_settings_hotspot_label);
+ }
state.icon = state.visible && state.value ? mEnable : mDisable;
}
@@ -118,6 +160,15 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
R.integer.days_to_show_hotspot_tile);
}
+ private BroadcastReceiver mTetherConnectStateChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final List<WifiDevice> clients = mConnectivityManager.getTetherConnectedSta();
+ mNumConnectedClients = clients != null ? clients.size() : 0;
+ refreshState();
+ }
+ };
+
private final class Callback implements HotspotController.Callback {
@Override
public void onHotspotChanged(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java
new file mode 100644
index 0000000..f59c876
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.UserHandle;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+
+import cyanogenmod.hardware.CMHardwareManager;
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/** Quick settings tile: LiveDisplay mode switcher **/
+public class LiveDisplayTile extends QSTile<LiveDisplayTile.LiveDisplayState> {
+
+ private static final Intent LIVEDISPLAY_SETTINGS =
+ new Intent("android.settings.LIVEDISPLAY_SETTINGS");
+
+ private final LiveDisplayObserver mObserver;
+ private String[] mEntries;
+ private String[] mDescriptionEntries;
+ private String[] mAnnouncementEntries;
+ private String[] mValues;
+ private final int[] mEntryIconRes;
+
+ private boolean mListening;
+
+ private static final int MODE_OUTDOOR = 3;
+ private static final int MODE_DAY = 4;
+
+ private static final int OFF_TEMPERATURE = 6500;
+
+ private int mDayTemperature;
+
+ private final boolean mOutdoorModeAvailable;
+ private final int mDefaultDayTemperature;
+
+ public LiveDisplayTile(Host host) {
+ super(host);
+
+ Resources res = mContext.getResources();
+ TypedArray typedArray = res.obtainTypedArray(R.array.live_display_drawables);
+ mEntryIconRes = new int[typedArray.length()];
+ for (int i = 0; i < mEntryIconRes.length; i++) {
+ mEntryIconRes[i] = typedArray.getResourceId(i, 0);
+ }
+ typedArray.recycle();
+
+ updateEntries();
+
+ mOutdoorModeAvailable =
+ CMHardwareManager.getInstance(mContext)
+ .isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT);
+
+ mDefaultDayTemperature = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_dayColorTemperature);
+ loadDayTemperature();
+
+ mObserver = new LiveDisplayObserver(mHandler);
+ mObserver.startObserving();
+ }
+
+ private void updateEntries() {
+ Resources res = mContext.getResources();
+ mEntries = res.getStringArray(com.android.internal.R.array.live_display_entries);
+ mDescriptionEntries = res.getStringArray(R.array.live_display_description);
+ mAnnouncementEntries = res.getStringArray(R.array.live_display_announcement);
+ mValues = res.getStringArray(com.android.internal.R.array.live_display_values);
+ }
+
+ @Override
+ protected LiveDisplayState newTileState() {
+ return new LiveDisplayState();
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening)
+ return;
+ mListening = listening;
+ if (listening) {
+ mObserver.startObserving();
+ } else {
+ mObserver.endObserving();
+ }
+ }
+
+ @Override
+ protected void handleClick() {
+ changeToNextMode();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(LIVEDISPLAY_SETTINGS);
+ }
+
+ @Override
+ protected void handleUpdateState(LiveDisplayState state, Object arg) {
+ updateEntries();
+ state.visible = true;
+ state.mode = arg == null ? getCurrentModeIndex() : (Integer) arg;
+ state.label = mEntries[state.mode];
+ state.icon = ResourceIcon.get(mEntryIconRes[state.mode]);
+ state.contentDescription = mDescriptionEntries[state.mode];
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_LIVE_DISPLAY;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ return mAnnouncementEntries[getCurrentModeIndex()];
+ }
+
+ private int getCurrentModeIndex() {
+ return ArrayUtils.indexOf(mValues,
+ String.valueOf(CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_TEMPERATURE_MODE,
+ 0, UserHandle.USER_CURRENT)));
+ }
+
+ private void changeToNextMode() {
+ int next = getCurrentModeIndex() + 1;
+
+ if (next >= mValues.length) {
+ next = 0;
+ }
+
+ while (true) {
+ // Skip outdoor mode if it's unsupported, and skip the day setting
+ // if it's the same as the off setting
+ if ((!mOutdoorModeAvailable &&
+ Integer.valueOf(mValues[next]) == MODE_OUTDOOR) ||
+ (mDayTemperature == OFF_TEMPERATURE &&
+ Integer.valueOf(mValues[next]) == MODE_DAY)) {
+ next++;
+ if (next >= mValues.length) {
+ next = 0;
+ }
+ } else {
+ break;
+ }
+ }
+
+ CMSettings.System.putIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_TEMPERATURE_MODE,
+ Integer.valueOf(mValues[next]), UserHandle.USER_CURRENT);
+ }
+
+ private void loadDayTemperature() {
+ mDayTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_TEMPERATURE_DAY,
+ mDefaultDayTemperature,
+ UserHandle.USER_CURRENT);
+ }
+
+ private class LiveDisplayObserver extends ContentObserver {
+ public LiveDisplayObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ loadDayTemperature();
+ refreshState(getCurrentModeIndex());
+ }
+
+ public void startObserving() {
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_MODE),
+ false, this, UserHandle.USER_ALL);
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY),
+ false, this, UserHandle.USER_ALL);
+ }
+
+ public void endObserving() {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+
+ public static class LiveDisplayState extends QSTile.State {
+ public int mode;
+
+ @Override
+ public boolean copyTo(State other) {
+ final LiveDisplayState o = (LiveDisplayState) other;
+ final boolean changed = mode != o.mode;
+ return super.copyTo(other) || changed;
+ }
+
+ @Override
+ protected StringBuilder toStringBuilder() {
+ final StringBuilder rt = super.toStringBuilder();
+ rt.insert(rt.length() - 1, ",mode=" + mode);
+ return rt;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index e6fade4..3598bba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,32 +17,69 @@
package com.android.systemui.qs.tiles;
+import com.android.internal.logging.MetricsConstants;
import com.android.internal.logging.MetricsLogger;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckedTextView;
+import android.widget.ListView;
+
import com.android.systemui.R;
+import com.android.systemui.qs.QSDetailItems;
+import com.android.systemui.qs.QSDetailItemsList;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
/** Quick settings tile: Location **/
public class LocationTile extends QSTile<QSTile.BooleanState> {
+ private static final Intent LOCATION_SETTINGS_INTENT
+ = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ public static final Integer[] LOCATION_SETTINGS = new Integer[]{
+ Settings.Secure.LOCATION_MODE_BATTERY_SAVING,
+ Settings.Secure.LOCATION_MODE_SENSORS_ONLY,
+ Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
+ };
+
private final AnimationIcon mEnable =
new AnimationIcon(R.drawable.ic_signal_location_enable_animation);
private final AnimationIcon mDisable =
new AnimationIcon(R.drawable.ic_signal_location_disable_animation);
private final LocationController mController;
+ private final LocationDetailAdapter mDetailAdapter;
private final KeyguardMonitor mKeyguard;
private final Callback mCallback = new Callback();
+ private final List<Integer> mLocationList = new ArrayList<Integer>();
public LocationTile(Host host) {
super(host);
mController = host.getLocationController();
+ mDetailAdapter = new LocationDetailAdapter();
mKeyguard = host.getKeyguardMonitor();
}
@Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
protected BooleanState newTileState() {
return new BooleanState();
}
@@ -59,32 +97,74 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleClick() {
- final boolean wasEnabled = (Boolean) mState.value;
- MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled);
- mController.setLocationEnabled(!wasEnabled);
+ if(mController.isAdvancedSettingsEnabled()) {
+ showDetail(true);
+ } else {
+ boolean wasEnabled = mController.isLocationEnabled();
+ mController.setLocationEnabled(!wasEnabled);
+ MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled);
+ refreshState();
+ }
+
mEnable.setAllowAnimation(true);
mDisable.setAllowAnimation(true);
}
@Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(LOCATION_SETTINGS_INTENT);
+ }
+
+ @Override
protected void handleUpdateState(BooleanState state, Object arg) {
- final boolean locationEnabled = mController.isLocationEnabled();
+ final int currentState = mController.getLocationCurrentState();
// Work around for bug 15916487: don't show location tile on top of lock screen. After the
// bug is fixed, this should be reverted to only hiding it on secure lock screens:
// state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
state.visible = !mKeyguard.isShowing();
- state.value = locationEnabled;
- if (locationEnabled) {
- state.icon = mEnable;
- state.label = mContext.getString(R.string.quick_settings_location_label);
- state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_location_on);
- } else {
- state.icon = mDisable;
- state.label = mContext.getString(R.string.quick_settings_location_label);
- state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_location_off);
+ state.label = mContext.getString(getStateLabelRes(currentState));
+
+ switch (currentState) {
+ case Settings.Secure.LOCATION_MODE_OFF:
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_location_off);
+ state.icon = mDisable;
+ break;
+ case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_location_battery_saving);
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_location_battery_saving);
+ break;
+ case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_location_gps_only);
+ state.icon = mEnable;
+ break;
+ case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_location_high_accuracy);
+ state.icon = mEnable;
+ break;
+ default:
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_location_on);
+ state.icon = mEnable;
+ }
+ }
+
+ private int getStateLabelRes(int currentState) {
+ switch (currentState) {
+ case Settings.Secure.LOCATION_MODE_OFF:
+ return R.string.quick_settings_location_off_label;
+ case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
+ return R.string.quick_settings_location_battery_saving_label;
+ case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
+ return R.string.quick_settings_location_gps_only_label;
+ case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
+ return R.string.quick_settings_location_high_accuracy_label;
+ default:
+ return R.string.quick_settings_location_label;
}
}
@@ -95,10 +175,22 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
@Override
protected String composeChangeAnnouncement() {
- if (mState.value) {
- return mContext.getString(R.string.accessibility_quick_settings_location_changed_on);
- } else {
- return mContext.getString(R.string.accessibility_quick_settings_location_changed_off);
+ switch (mController.getLocationCurrentState()) {
+ case Settings.Secure.LOCATION_MODE_OFF:
+ return mContext.getString(
+ R.string.accessibility_quick_settings_location_changed_off);
+ case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
+ return mContext.getString(
+ R.string.accessibility_quick_settings_location_changed_battery_saving);
+ case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
+ return mContext.getString(
+ R.string.accessibility_quick_settings_location_changed_gps_only);
+ case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
+ return mContext.getString(
+ R.string.accessibility_quick_settings_location_changed_high_accuracy);
+ default:
+ return mContext.getString(
+ R.string.accessibility_quick_settings_location_changed_on);
}
}
@@ -114,4 +206,90 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
refreshState();
}
};
+
+ private class AdvancedLocationAdapter extends ArrayAdapter<Integer> {
+ public AdvancedLocationAdapter(Context context) {
+ super(context, android.R.layout.simple_list_item_single_choice, mLocationList);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ CheckedTextView label = (CheckedTextView) inflater.inflate(
+ android.R.layout.simple_list_item_single_choice, parent, false);
+ label.setText(getStateLabelRes(getItem(position)));
+ return label;
+ }
+ }
+
+ private class LocationDetailAdapter implements DetailAdapter, AdapterView.OnItemClickListener {
+
+ private AdvancedLocationAdapter mAdapter;
+ private QSDetailItemsList mDetails;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_location_detail_title;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ boolean state = mController.getLocationCurrentState()
+ != Settings.Secure.LOCATION_MODE_OFF;
+ rebuildLocationList(state);
+ return state;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return LOCATION_SETTINGS_INTENT;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ mController.setLocationEnabled(state);
+ rebuildLocationList(state);
+ fireToggleStateChanged(state);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.QS_LOCATION;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ mDetails = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ mDetails.setEmptyState(R.drawable.ic_qs_location_off,
+ R.string.accessibility_quick_settings_location_off);
+ mAdapter = new LocationTile.AdvancedLocationAdapter(context);
+ mDetails.setAdapter(mAdapter);
+
+ final ListView list = mDetails.getListView();
+ list.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+ list.setOnItemClickListener(this);
+
+ return mDetails;
+ }
+
+ private void rebuildLocationList(boolean populate) {
+ mLocationList.clear();
+ if (populate) {
+ mLocationList.addAll(Arrays.asList(LOCATION_SETTINGS));
+ mDetails.getListView().setItemChecked(mAdapter.getPosition(
+ mController.getLocationCurrentState()), true);
+ }
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ mController.setLocationMode((Integer) parent.getItemAtPosition(position));
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java
new file mode 100644
index 0000000..a147d30
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015-2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Intent;
+import android.os.UserHandle;
+import com.android.systemui.R;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
+import cyanogenmod.app.Profile;
+import cyanogenmod.app.ProfileManager;
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+public class LockscreenToggleTile extends QSTile<QSTile.BooleanState>
+ implements KeyguardMonitor.Callback {
+
+ private static final Intent LOCK_SCREEN_SETTINGS =
+ new Intent("android.settings.LOCK_SCREEN_SETTINGS");
+
+ private KeyguardMonitor mKeyguard;
+ private boolean mListening;
+
+ private KeyguardViewMediator.LockscreenEnabledSettingsObserver mSettingsObserver;
+
+ public LockscreenToggleTile(Host host) {
+ super(host);
+
+ mKeyguard = host.getKeyguardMonitor();
+
+ mSettingsObserver = new KeyguardViewMediator.LockscreenEnabledSettingsObserver(mContext,
+ mUiHandler) {
+
+ @Override
+ public void update() {
+ refreshState();
+ }
+ };
+
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) {
+ return;
+ }
+ mListening = listening;
+ if (listening) {
+ mSettingsObserver.observe();
+ mKeyguard.addCallback(this);
+ refreshState();
+ } else {
+ mSettingsObserver.unobserve();
+ mKeyguard.removeCallback(this);
+ }
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ final boolean newState = !getState().value;
+ setPersistedState(newState);
+ refreshState(newState);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(LOCK_SCREEN_SETTINGS);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ KeyguardViewMediator mediator = ((SystemUIApplication)
+ mContext.getApplicationContext()).getComponent(KeyguardViewMediator.class);
+
+ if (mediator == null) {
+ state.visible = false;
+ state.value = false;
+ state.enabled = false;
+ } else {
+ final boolean lockscreenEnforced = mediator.lockscreenEnforcedByDevicePolicy();
+ final boolean lockscreenEnabled = lockscreenEnforced ||
+ arg != null ? (Boolean) arg : mediator.getKeyguardEnabledInternal();
+
+ state.visible = mediator.isKeyguardBound();
+
+ if (mediator.isProfileDisablingKeyguard()) {
+ state.value = false;
+ state.enabled = false;
+ state.label = mContext.getString(
+ R.string.quick_settings_lockscreen_label_locked_by_profile);
+ } else if (lockscreenEnforced) {
+ state.value = true;
+ state.enabled = false;
+ state.label = mContext.getString(
+ R.string.quick_settings_lockscreen_label_enforced);
+ } else {
+ state.value = lockscreenEnabled;
+ state.enabled = !mKeyguard.isShowing() || !mKeyguard.isSecure();
+
+ state.label = mContext.getString(R.string.quick_settings_lockscreen_label);
+ }
+ // update icon
+ if (lockscreenEnabled) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_lock_screen_on);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_lock_screen_off);
+ }
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_LOCKSCREEN_TOGGLE;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_lock_screen_changed_on);
+ } else {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_lock_screen_changed_off);
+ }
+ }
+
+ @Override
+ public void onKeyguardChanged() {
+ refreshState();
+ }
+
+ private void setPersistedState(boolean enabled) {
+ CMSettings.Secure.putIntForUser(mContext.getContentResolver(),
+ CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED,
+ enabled ? 1 : 0, UserHandle.USER_CURRENT);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
new file mode 100644
index 0000000..1bfbb8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+public class NfcTile extends QSTile<QSTile.BooleanState> {
+ private NfcAdapter mNfcAdapter;
+ private boolean mListening;
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ refreshState();
+ }
+ };
+
+ public NfcTile(Host host) {
+ super(host);
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ toggleState();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(new Intent("android.settings.NFC_SETTINGS"));
+ }
+
+ protected void toggleState() {
+ int state = getNfcState();
+ switch (state) {
+ case NfcAdapter.STATE_TURNING_ON:
+ case NfcAdapter.STATE_ON:
+ mNfcAdapter.disable();
+ break;
+ case NfcAdapter.STATE_TURNING_OFF:
+ case NfcAdapter.STATE_OFF:
+ mNfcAdapter.enable();
+ break;
+ }
+ }
+
+ private boolean isEnabled() {
+ int state = getNfcState();
+ switch (state) {
+ case NfcAdapter.STATE_TURNING_ON:
+ case NfcAdapter.STATE_ON:
+ return true;
+ case NfcAdapter.STATE_TURNING_OFF:
+ case NfcAdapter.STATE_OFF:
+ default:
+ return false;
+ }
+ }
+
+ private int getNfcState() {
+ return mNfcAdapter.getAdapterState();
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ if (mNfcAdapter == null) {
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
+ }
+ state.visible = mNfcAdapter != null;
+ state.value = mNfcAdapter != null && isEnabled();
+ state.icon = ResourceIcon.get(state.value ?
+ R.drawable.ic_qs_nfc_on : R.drawable.ic_qs_nfc_off);
+ state.label = mContext.getString(R.string.quick_settings_nfc_label);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_NFC;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (listening) {
+ if (mNfcAdapter == null) {
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
+ refreshState();
+ }
+ mContext.registerReceiver(mReceiver,
+ new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED));
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java
new file mode 100644
index 0000000..e6e6bb4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSDetailItemsList;
+import com.android.systemui.qs.QSTile;
+
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+import org.cyanogenmod.internal.util.QSUtils;
+
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import cyanogenmod.power.PerformanceManager;
+import cyanogenmod.providers.CMSettings;
+
+public class PerfProfileTile extends QSTile<PerfProfileTile.ProfileState> {
+
+ private static final Intent BATTERY_SETTINGS = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+
+ private final String[] mEntries;
+ private final String[] mDescriptionEntries;
+ private final String[] mAnnouncementEntries;
+ private final int[] mPerfProfileValues;
+ private final Icon mIcon;
+
+ private final PowerManager mPm;
+ private final PerformanceManager mPerformanceManager;
+ private boolean mListening;
+
+ private PerformanceProfileObserver mObserver;
+
+ public PerfProfileTile(Host host) {
+ super(host);
+ mObserver = new PerformanceProfileObserver(mHandler);
+ mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mPerformanceManager = PerformanceManager.getInstance(mContext);
+
+ Resources res = mContext.getResources();
+
+ mPerfProfileValues = res.getIntArray(org.cyanogenmod.platform.internal.R.array.perf_profile_values);
+
+ mEntries = res.getStringArray(org.cyanogenmod.platform.internal.R.array.perf_profile_entries);
+ mDescriptionEntries = res.getStringArray(R.array.perf_profile_description);
+ mAnnouncementEntries = res.getStringArray(R.array.perf_profile_announcement);
+
+ mIcon = ResourceIcon.get(R.drawable.ic_qs_perf_profile);
+ }
+
+ @Override
+ protected ProfileState newTileState() {
+ return new ProfileState();
+ }
+
+ @Override
+ protected void handleClick() {
+ showDetail(true);
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return new PerfProfileDetailAdapter();
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(BATTERY_SETTINGS);
+ }
+
+ @Override
+ protected void handleUpdateState(ProfileState state, Object arg) {
+ state.visible = mPerformanceManager.getNumberOfProfiles() > 0;
+ state.profile = arg == null ? getCurrentProfileIndex() : (Integer) arg;
+ state.label = mEntries[state.profile];
+ state.icon = mIcon;
+ state.contentDescription = mDescriptionEntries[state.profile];
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_PERF_PROFILE;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ return mAnnouncementEntries[getCurrentProfileIndex()];
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (listening) {
+ mObserver.startObserving();
+ } else {
+ mObserver.endObserving();
+ }
+ }
+
+ private class PerformanceProfileObserver extends ContentObserver {
+ public PerformanceProfileObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ refreshState(getCurrentProfileIndex());
+ }
+
+ public void startObserving() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(CMSettings.Secure.PERFORMANCE_PROFILE),
+ false, this);
+ }
+
+ public void endObserving() {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+
+ private int getCurrentProfileIndex() {
+ int index = 0;
+ int perfProfile = mPerformanceManager.getPowerProfile();
+
+ int count = mPerfProfileValues.length;
+ for (int i = 0; i < count; i++) {
+ if (mPerfProfileValues[i] == perfProfile) {
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+ }
+
+ private void changeToProfile(int profileIndex) {
+ mPerformanceManager.setPowerProfile(mPerfProfileValues[profileIndex]); // content observer will notify
+ }
+
+ public static class ProfileState extends QSTile.State {
+ public int profile;
+
+ @Override
+ public boolean copyTo(State other) {
+ final ProfileState o = (ProfileState) other;
+ final boolean changed = profile != o.profile;
+ return super.copyTo(other) || changed;
+ }
+
+ @Override
+ protected StringBuilder toStringBuilder() {
+ final StringBuilder rt = super.toStringBuilder();
+ rt.insert(rt.length() - 1, ",profile=" + profile);
+ return rt;
+ }
+ }
+
+ private class PerfProfileDetailAdapter implements DetailAdapter,
+ AdapterView.OnItemClickListener {
+ private QSDetailItemsList mItems;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_performance_profile_detail_title;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return BATTERY_SETTINGS;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_PERF_PROFILE_DETAIL;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ mItems = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ ArrayAdapter adapter = new ArrayAdapter<String>(mContext,
+ android.R.layout.simple_list_item_single_choice, mEntries);
+ ListView listView = mItems.getListView();
+ listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(this);
+ listView.setDivider(null);
+ listView.setItemChecked(getCurrentProfileIndex(), true);
+ return mItems;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ changeToProfile(position);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java
new file mode 100644
index 0000000..6f65f6c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckedTextView;
+import android.widget.ListView;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSDetailItemsList;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
+import cyanogenmod.app.Profile;
+import cyanogenmod.app.ProfileManager;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class ProfilesTile extends QSTile<QSTile.State> implements KeyguardMonitor.Callback {
+
+ private static final Intent PROFILES_SETTINGS =
+ new Intent("android.settings.PROFILES_SETTINGS");
+
+ private boolean mListening;
+ private ProfilesObserver mObserver;
+ private ProfileManager mProfileManager;
+ private QSDetailItemsList mDetails;
+ private ProfileAdapter mAdapter;
+ private KeyguardMonitor mKeyguardMonitor;
+
+ public ProfilesTile(Host host) {
+ super(host);
+ mProfileManager = ProfileManager.getInstance(mContext);
+ mObserver = new ProfilesObserver(mHandler);
+ mKeyguardMonitor = host.getKeyguardMonitor();
+ mKeyguardMonitor.addCallback(this);
+ }
+
+ @Override
+ protected void handleDestroy() {
+ mKeyguardMonitor.removeCallback(this);
+ }
+
+ @Override
+ protected State newTileState() {
+ return new State();
+ }
+
+ @Override
+ protected void handleClick() {
+ showDetail(true);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(PROFILES_SETTINGS);
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ state.visible = true;
+
+
+
+ state.enabled = !mKeyguardMonitor.isShowing() || !mKeyguardMonitor.isSecure();
+ if (profilesEnabled()) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_profiles_on);
+ state.label = mProfileManager.getActiveProfile().getName();
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_profiles, state.label);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_profiles_off);
+ state.label = mContext.getString(R.string.quick_settings_profiles_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_profiles_off);
+ }
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (profilesEnabled()) {
+ return mContext.getString(R.string.accessibility_quick_settings_profiles_changed,
+ mState.label);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_profiles_changed_off);
+ }
+ }
+
+ private boolean profilesEnabled() {
+ return CMSettings.System.getInt(mContext.getContentResolver(),
+ CMSettings.System.SYSTEM_PROFILES_ENABLED, 1) == 1;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_PROFILES;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (listening) {
+ mObserver.startObserving();
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_SELECTED);
+ filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_UPDATED);
+ mContext.registerReceiver(mReceiver, filter);
+ refreshState();
+ } else {
+ mObserver.endObserving();
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return new ProfileDetailAdapter();
+ }
+
+ @Override
+ public void onKeyguardChanged() {
+ refreshState();
+ }
+
+ private class ProfileAdapter extends ArrayAdapter<Profile> {
+ public ProfileAdapter(Context context, List<Profile> profiles) {
+ super(context, android.R.layout.simple_list_item_single_choice, profiles);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ CheckedTextView label = (CheckedTextView) inflater.inflate(
+ android.R.layout.simple_list_item_single_choice, parent, false);
+
+ Profile p = getItem(position);
+ label.setText(p.getName());
+
+ return label;
+ }
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ProfileManager.INTENT_ACTION_PROFILE_SELECTED.equals(intent.getAction())
+ || ProfileManager.INTENT_ACTION_PROFILE_UPDATED.equals(intent.getAction())) {
+ refreshState();
+ }
+ }
+ };
+
+ public class ProfileDetailAdapter implements DetailAdapter, AdapterView.OnItemClickListener {
+
+ private List<Profile> mProfilesList;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_profiles;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ boolean enabled = profilesEnabled();
+ rebuildProfilesList(enabled);
+ return enabled;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_PROFILES_DETAIL;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ mDetails = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ mProfilesList = new ArrayList<>();
+ mDetails.setAdapter(mAdapter = new ProfileAdapter(context, mProfilesList));
+
+ final ListView list = mDetails.getListView();
+ list.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+ list.setOnItemClickListener(this);
+
+ mDetails.setEmptyState(R.drawable.ic_qs_profiles_off,
+ R.string.quick_settings_profiles_off);
+
+ return mDetails;
+ }
+
+ private void rebuildProfilesList(boolean populate) {
+ mProfilesList.clear();
+ if (populate) {
+ int selected = -1;
+
+ final Profile[] profiles = mProfileManager.getProfiles();
+ final Profile activeProfile = mProfileManager.getActiveProfile();
+ final UUID activeUuid = activeProfile != null ? activeProfile.getUuid() : null;
+
+ for (int i = 0; i < profiles.length; i++) {
+ mProfilesList.add(profiles[i]);
+ if (activeUuid != null && activeUuid.equals(profiles[i].getUuid())) {
+ selected = i;
+ }
+ }
+ mDetails.getListView().setItemChecked(selected, true);
+ }
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return PROFILES_SETTINGS;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ CMSettings.System.putInt(mContext.getContentResolver(),
+ CMSettings.System.SYSTEM_PROFILES_ENABLED, state ? 1 : 0);
+ fireToggleStateChanged(state);
+ rebuildProfilesList(state);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Profile selected = (Profile) parent.getItemAtPosition(position);
+ mProfileManager.setActiveProfile(selected.getUuid());
+ }
+ }
+
+ private class ProfilesObserver extends ContentObserver {
+ public ProfilesObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ refreshState();
+ }
+
+ public void startObserving() {
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.SYSTEM_PROFILES_ENABLED),
+ false, this);
+ }
+
+ public void endObserving() {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 1a26a4d..f074d9d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +17,7 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
import android.content.res.Configuration;
import com.android.internal.logging.MetricsLogger;
@@ -26,6 +28,10 @@ import com.android.systemui.statusbar.policy.RotationLockController.RotationLock
/** Quick settings tile: Rotation **/
public class RotationLockTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent DISPLAY_ROTATION_SETTINGS =
+ new Intent("android.settings.DISPLAY_ROTATION_SETTINGS");
+
private final AnimationIcon mPortraitToAuto
= new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation);
private final AnimationIcon mAutoToPortrait
@@ -67,6 +73,11 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
}
@Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(DISPLAY_ROTATION_SETTINGS);
+ }
+
+ @Override
protected void handleUpdateState(BooleanState state, Object arg) {
if (mController == null) return;
final boolean rotationLocked = arg != null ? ((UserBoolean) arg).value
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java
new file mode 100644
index 0000000..e933787
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.provider.Settings;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSDetailItemsList;
+import com.android.systemui.qs.QSTile;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class ScreenTimeoutTile extends QSTile<ScreenTimeoutTile.TimeoutState> {
+
+ private static final Intent SETTINGS_INTENT = new Intent(Settings.ACTION_DISPLAY_SETTINGS);
+ private static final String TIMEOUT_ENTRIES_NAME = "screen_timeout_entries";
+ private static final String TIMEOUT_VALUES_NAME = "screen_timeout_values";
+ private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+
+ private final AnimationIcon mShort =
+ new AnimationIcon(R.drawable.ic_qs_screen_timeout_short_avd);
+ private final AnimationIcon mShortReverse =
+ new AnimationIcon(R.drawable.ic_qs_screen_timeout_short_reverse_avd);
+ private final AnimationIcon mMedium =
+ new AnimationIcon(R.drawable.ic_qs_screen_timeout_med_avd);
+ private final AnimationIcon mMediumReverse =
+ new AnimationIcon(R.drawable.ic_qs_screen_timeout_med_reverse_avd);
+ private final AnimationIcon mLong =
+ new AnimationIcon(R.drawable.ic_qs_screen_timeout_long_avd);
+ private final AnimationIcon mLongReverse =
+ new AnimationIcon(R.drawable.ic_qs_screen_timeout_long_reverse_avd);
+
+ private String[] mEntries, mValues;
+
+ public ScreenTimeoutTile(Host host) {
+ super(host);
+ populateList();
+ }
+
+ private void populateList() {
+ try {
+ Context context = mContext.createPackageContext(SETTINGS_PACKAGE_NAME, 0);
+ Resources mSettingsResources = context.getResources();
+ int id = mSettingsResources.getIdentifier(TIMEOUT_ENTRIES_NAME,
+ "array", SETTINGS_PACKAGE_NAME);
+ if (id <= 0) {
+ return;
+ }
+ mEntries = mSettingsResources.getStringArray(id);
+ id = mSettingsResources.getIdentifier(TIMEOUT_VALUES_NAME,
+ "array", SETTINGS_PACKAGE_NAME);
+ if (id <= 0) {
+ return;
+ }
+ mValues = mSettingsResources.getStringArray(id);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private int getScreenTimeout() {
+ return Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_OFF_TIMEOUT, 0);
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return new ScreenTimeoutDetailAdapter();
+ }
+
+ private ContentObserver mObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ refreshState();
+ }
+ };
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.SCREEN_OFF_TIMEOUT),
+ false, mObserver);
+ } else {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
+ }
+
+ @Override
+ protected TimeoutState newTileState() {
+ return new TimeoutState();
+ }
+
+ @Override
+ protected void handleClick() {
+ if (mEntries.length > 0) {
+ showDetail(true);
+ }
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(SETTINGS_INTENT);
+ }
+
+ private String makeTimeoutSummaryString(int timeout) {
+ Resources res = mContext.getResources();
+ int resId;
+
+ /* ms -> seconds */
+ timeout /= 1000;
+
+ if (timeout >= 60 && timeout % 60 == 0) {
+ /* seconds -> minutes */
+ timeout /= 60;
+ if (timeout >= 60 && timeout % 60 == 0) {
+ /* minutes -> hours */
+ timeout /= 60;
+ resId = com.android.internal.R.plurals.duration_hours;
+ } else {
+ resId = com.android.internal.R.plurals.duration_minutes;
+ }
+ } else {
+ resId = com.android.internal.R.plurals.duration_seconds;
+ }
+
+ return res.getQuantityString(resId, timeout, timeout);
+ }
+
+ public static final class TimeoutState extends QSTile.State {
+ int previousTimeout;
+ }
+
+ private enum Bucket {
+ SMALL(0, 30000),
+ MEDIUM(60000,300000),
+ LARGE(600000, 1800000);
+ private final int start;
+ private final int stop;
+
+ Bucket(int start, int stop) {
+ this.start = start;
+ this.stop = stop;
+ }
+
+ public static Bucket getBucket(int value) {
+ for (Bucket item : Bucket.values()) {
+ if (value >= item.start && value <= item.stop) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ }
+ @Override
+ protected void handleUpdateState(final TimeoutState state, Object arg) {
+ int newTimeout = getScreenTimeout();
+
+ AnimationIcon d = null;
+ Bucket nextBucket = Bucket.getBucket(newTimeout);
+ Bucket previousBucket = Bucket.getBucket(state.previousTimeout);
+
+ if (state.previousTimeout < 60000) {
+ // Default
+ d = mMediumReverse;
+ if (nextBucket == Bucket.MEDIUM) {
+ // Medium
+ d = mShort;
+ } else if (nextBucket == Bucket.LARGE) {
+ // Large
+ d = mShortReverse;
+ }
+ } else if (state.previousTimeout < 600000) {
+ // Default
+ d = mShort;
+ if (nextBucket == Bucket.SMALL) {
+ // Small
+ d = mMediumReverse;
+ } else if (nextBucket == Bucket.LARGE) {
+ // Large
+ d = mMedium;
+ }
+ } else {
+ d = mMedium;
+ if (nextBucket == Bucket.MEDIUM) {
+ // Small
+ d = mLongReverse;
+ } else if (nextBucket == Bucket.SMALL) {
+ // Large
+ d = mLong;
+ }
+ }
+
+ if (state.icon == null || previousBucket != nextBucket) {
+ if (arg instanceof Boolean && (Boolean) arg) {
+ d.setAllowAnimation(true);
+ }
+ state.icon = d;
+ }
+
+ state.visible = true;
+ state.label = makeTimeoutSummaryString(newTimeout);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_screen_timeout, state.label);
+ state.previousTimeout = newTimeout;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_SCREEN_TIME_OUT;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ return mContext.getString(R.string.accessibility_quick_settings_screen_timeout_changed,
+ mState.label);
+ }
+
+ private class RadioAdapter extends ArrayAdapter<String> {
+
+ public RadioAdapter(Context context, int resource, String[] objects) {
+ super(context, resource, objects);
+ }
+
+ public RadioAdapter(Context context, int resource,
+ int textViewResourceId, String[] objects) {
+ super(context, resource, textViewResourceId, objects);
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ view = super.getView(position, view, parent);
+
+ view.setMinimumHeight(mContext.getResources() .getDimensionPixelSize(
+ R.dimen.qs_detail_item_height));
+
+ return view;
+ }
+
+ }
+ private class ScreenTimeoutDetailAdapter implements DetailAdapter,
+ AdapterView.OnItemClickListener {
+ private QSDetailItemsList mItems;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_screen_timeout_detail_title;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return SETTINGS_INTENT;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_SCREEN_TIME_OUT_DETAIL;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ mItems = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ ListView listView = mItems.getListView();
+ listView.setOnItemClickListener(this);
+ listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ listView.setDivider(null);
+ RadioAdapter adapter = new RadioAdapter(context,
+ android.R.layout.simple_list_item_single_choice, mEntries);
+ int indexOfSelection = Arrays.asList(mValues).indexOf(String.valueOf(getScreenTimeout()));
+ mItems.setAdapter(adapter);
+ listView.setItemChecked(indexOfSelection, true);
+ mItems.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mUiHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ refreshState(true);
+ }
+ }, 100);
+
+ }
+ });
+ return mItems;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ int selectedTimeout = Integer.valueOf(mValues[position]);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_OFF_TIMEOUT, selectedTimeout);
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java
new file mode 100644
index 0000000..7ffebc7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.SyncStatusObserver;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/** Quick settings tile: Sync **/
+public class SyncTile extends QSTile<QSTile.BooleanState> {
+
+ private Object mSyncObserverHandle = null;
+ private boolean mListening;
+
+ public SyncTile(Host host) {
+ super(host);
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void handleClick() {
+ ContentResolver.setMasterSyncAutomatically(!mState.value);
+ refreshState();
+ }
+
+ @Override
+ public void handleLongClick() {
+ Intent intent = new Intent("android.settings.SYNC_SETTINGS");
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ mHost.startActivityDismissingKeyguard(intent);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.value = ContentResolver.getMasterSyncAutomatically();
+ state.visible = true;
+ state.label = mContext.getString(R.string.quick_settings_sync_label);
+ if (state.value) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_sync_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_sync_on);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_sync_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_sync_off);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_SYNC;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_sync_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_sync_changed_off);
+ }
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+
+ if (listening) {
+ mSyncObserverHandle = ContentResolver.addStatusChangeListener(
+ ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, mSyncObserver);
+ } else {
+ ContentResolver.removeStatusChangeListener(mSyncObserverHandle);
+ mSyncObserverHandle = null;
+ }
+ }
+
+ private SyncStatusObserver mSyncObserver = new SyncStatusObserver() {
+ public void onStatusChanged(int which) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ refreshState();
+ }
+ });
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java
new file mode 100644
index 0000000..1274195
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbManager;
+import android.provider.Settings;
+import android.net.ConnectivityManager;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+/**
+ * USB Tether quick settings tile
+ */
+public class UsbTetherTile extends QSTile<QSTile.BooleanState> {
+ private static final Intent WIRELESS_SETTINGS = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+
+ private final ConnectivityManager mConnectivityManager;
+
+ private boolean mListening;
+
+ private boolean mUsbTethered = false;
+ private boolean mUsbConnected = false;
+
+ public UsbTetherTile(Host host) {
+ super(host);
+ mConnectivityManager = (ConnectivityManager) mContext
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening)
+ return;
+ mListening = listening;
+ if (listening) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(UsbManager.ACTION_USB_STATE);
+ mContext.registerReceiver(mReceiver, filter);
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ @Override
+ protected void handleClick() {
+ mConnectivityManager.setUsbTethering(!mUsbTethered);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(WIRELESS_SETTINGS);
+ }
+
+ private void updateState() {
+ String[] tetheredIfaces = mConnectivityManager.getTetheredIfaces();
+ String[] usbRegexs = mConnectivityManager.getTetherableUsbRegexs();
+
+ mUsbTethered = false;
+ for (String s : tetheredIfaces) {
+ for (String regex : usbRegexs) {
+ if (s.matches(regex)) {
+ mUsbTethered = true;
+ return;
+ }
+ }
+ }
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+ if (mUsbConnected && mConnectivityManager.isTetheringSupported()) {
+ updateState();
+ } else {
+ mUsbTethered = false;
+ }
+ refreshState();
+ }
+ };
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.visible = mUsbConnected && mConnectivityManager.isTetheringSupported();
+ state.value = mUsbTethered;
+ state.label = mContext.getString(R.string.quick_settings_usb_tether_label);
+ state.icon = mUsbTethered ? ResourceIcon.get(R.drawable.ic_qs_usb_tether_on)
+ : ResourceIcon.get(R.drawable.ic_qs_usb_tether_off);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_USB_TETHER;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java
new file mode 100644
index 0000000..ae29f16
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.provider.Settings;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
+public class VolumeTile extends QSTile<QSTile.BooleanState> {
+
+ private static final Intent SOUND_SETTINGS = new Intent("android.settings.SOUND_SETTINGS");
+
+ public VolumeTile(Host host) {
+ super(host);
+ }
+
+ @Override
+ protected void handleClick() {
+ AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ am.adjustVolume(AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
+ }
+
+ @Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(SOUND_SETTINGS);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.visible = true;
+ state.label = mContext.getString(R.string.quick_settings_volume_panel_label);
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_volume_panel); // TODO needs own icon
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.TILE_VOLUME;
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ // Do nothing
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index e654efd..abc9acd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,16 +20,20 @@ package com.android.systemui.qs.tiles;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ListView;
import com.android.internal.logging.MetricsLogger;
import com.android.settingslib.wifi.AccessPoint;
+
import com.android.systemui.R;
-import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
+import com.android.systemui.qs.QSDetailItemsList;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
@@ -37,6 +42,9 @@ import com.android.systemui.statusbar.policy.NetworkController.AccessPointContro
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
+import java.util.ArrayList;
import java.util.List;
/** Quick settings tile: Wifi **/
@@ -58,7 +66,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
}
@Override
- public boolean supportsDualTargets() {
+ public boolean hasDualTargetsDetails() {
return true;
}
@@ -116,19 +124,36 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
}
@Override
+ protected void handleLongClick() {
+ mHost.startActivityDismissingKeyguard(WIFI_SETTINGS);
+ }
+
+ @Override
protected void handleUpdateState(SignalState state, Object arg) {
state.visible = true;
if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
- CallbackInfo cb = (CallbackInfo) arg;
- if (cb == null) {
+ final CallbackInfo cb;
+ if (arg == null) {
cb = mSignalCallback.mInfo;
+ } else {
+ cb = (CallbackInfo) arg;
}
boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
boolean enabledChanging = state.enabled != cb.enabled;
if (enabledChanging) {
- mDetailAdapter.setItemsVisible(cb.enabled);
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ // on main thread, bypass the handler
+ mDetailAdapter.setItemsVisible(cb.enabled);
+ } else {
+ mUiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mDetailAdapter.setItemsVisible(cb.enabled);
+ }
+ });
+ }
fireToggleStateChanged(cb.enabled);
}
state.enabled = cb.enabled;
@@ -235,10 +260,12 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
};
private final class WifiDetailAdapter implements DetailAdapter,
- NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
+ AccessPointController.AccessPointCallback, AdapterView.OnItemClickListener {
- private QSDetailItems mItems;
- private AccessPoint[] mAccessPoints;
+ private QSDetailItemsList mItemsList;
+ private List<AccessPoint> mAccessPoints;
+ private List<Item> mDisplayedAccessPoints = new ArrayList<>();
+ private QSDetailItemsList.QSDetailListAdapter mAdapter;
@Override
public int getTitle() {
@@ -250,6 +277,11 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public Boolean getToggleState() {
return mState.enabled;
}
@@ -273,19 +305,21 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
mAccessPoints = null;
mWifiController.scanForAccessPoints();
fireScanStateChanged(true);
- mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
- mItems.setTagSuffix("Wifi");
- mItems.setCallback(this);
- mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
+ mItemsList = QSDetailItemsList.convertOrInflate(context, convertView, parent);
+ ListView listView = mItemsList.getListView();
+ listView.setDivider(null);
+ listView.setOnItemClickListener(this);
+ listView.setAdapter(mAdapter =
+ new QSDetailItemsList.QSDetailListAdapter(context, mDisplayedAccessPoints));
+ mItemsList.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
R.string.quick_settings_wifi_detail_empty_text);
updateItems();
- setItemsVisible(mState.enabled);
- return mItems;
+ return mItemsList;
}
@Override
public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
- mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
+ mAccessPoints = accessPoints;
updateItems();
if (accessPoints != null && accessPoints.size() > 0) {
fireScanStateChanged(false);
@@ -297,35 +331,22 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
mHost.startActivityDismissingKeyguard(settingsIntent);
}
- @Override
- public void onDetailItemClick(Item item) {
- if (item == null || item.tag == null) return;
- final AccessPoint ap = (AccessPoint) item.tag;
- if (!ap.isActive()) {
- if (mWifiController.connect(ap)) {
- mHost.collapsePanels();
- }
- }
- showDetail(false);
- }
-
- @Override
- public void onDetailItemDisconnect(Item item) {
- // noop
- }
-
public void setItemsVisible(boolean visible) {
- if (mItems == null) return;
- mItems.setItemsVisible(visible);
+ if (mAdapter == null) return;
+ if (visible) {
+ updateItems();
+ } else {
+ mDisplayedAccessPoints.clear();
+ }
+ mAdapter.notifyDataSetChanged();
}
private void updateItems() {
- if (mItems == null) return;
- Item[] items = null;
+ if (mAdapter == null) return;
if (mAccessPoints != null) {
- items = new Item[mAccessPoints.length];
- for (int i = 0; i < mAccessPoints.length; i++) {
- final AccessPoint ap = mAccessPoints[i];
+ mDisplayedAccessPoints.clear();
+ for (int i = 0; i < mAccessPoints.size(); i++) {
+ final AccessPoint ap = mAccessPoints.get(i);
final Item item = new Item();
item.tag = ap;
item.icon = mWifiController.getIcon(ap);
@@ -334,10 +355,23 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
: null;
- items[i] = item;
+ mDisplayedAccessPoints.add(item);
+ }
+ }
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Item item = (Item) parent.getItemAtPosition(position);
+ if (item == null || item.tag == null) return;
+ final AccessPoint ap = (AccessPoint) item.tag;
+ if (!ap.isActive()) {
+ if (mWifiController.connect(ap)) {
+ mHost.collapsePanels();
}
}
- mItems.setItems(items);
+ showDetail(false);
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index a4acf83..b482a50 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -38,7 +38,7 @@ public class Constants {
// Enables the filtering of tasks according to their grouping
public static final boolean EnableTaskFiltering = false;
// Enables dismiss-all
- public static final boolean EnableDismissAll = false;
+ public static final boolean EnableDismissAll = true;
// Enables debug mode
public static final boolean EnableDebugMode = false;
// Enables the search bar layout
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 3917bab..b3a3dfd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -46,6 +46,7 @@ import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
+import com.android.systemui.cm.UserContentObserver;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
@@ -61,6 +62,8 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.util.ArrayList;
+import cyanogenmod.providers.CMSettings;
+
/**
* Annotation for a method that is only called from the primary user's SystemUI process and will be
* proxied to the current user.
@@ -161,6 +164,35 @@ public class Recents extends SystemUI
}
}
+ class RecentsSettingsObserver extends UserContentObserver {
+
+ public RecentsSettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.RECENTS_SHOW_SEARCH_BAR),
+ false, this);
+ update();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ protected void update() {
+ if (mConfig.updateShowSearch(mContext)) {
+ reloadHeaderBarLayout();
+ }
+ }
+ }
+
static RecentsComponent.Callbacks sRecentsComponentCallbacks;
static RecentsTaskLoadPlan sInstanceLoadPlan;
static Recents sInstance;
@@ -171,6 +203,7 @@ public class Recents extends SystemUI
TaskStackListenerImpl mTaskStackListener;
RecentsOwnerEventProxyReceiver mProxyBroadcastReceiver;
RecentsAppWidgetHost mAppWidgetHost;
+ RecentsSettingsObserver mSettingsObserver;
boolean mBootCompleted;
boolean mStartAnimationTriggered;
boolean mCanReuseTaskStackViews = true;
@@ -259,6 +292,9 @@ public class Recents extends SystemUI
// Load the header bar layout
reloadHeaderBarLayout();
+ mSettingsObserver = new RecentsSettingsObserver(mHandler);
+ mSettingsObserver.observe();
+
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -549,7 +585,8 @@ public class Recents extends SystemUI
// Try and pre-emptively bind the search widget on startup to ensure that we
// have the right thumbnail bounds to animate to.
// Note: We have to reload the widget id before we get the task stack bounds below
- if (mSystemServicesProxy.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) {
+ if (mConfig.searchBarEnabled &&
+ mSystemServicesProxy.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) {
mConfig.getSearchBarBounds(mWindowRect.width(), mWindowRect.height(),
mStatusBarHeight, searchBarBounds);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d0876fa..f4fe677 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -48,6 +48,7 @@ import com.android.systemui.recents.views.DebugOverlayView;
import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.recents.views.ViewAnimation;
+import cyanogenmod.providers.CMSettings;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -207,9 +208,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
ArrayList<TaskStack> stacks = plan.getAllTaskStacks();
mConfig.launchedWithNoRecentTasks = !plan.hasTasks();
- if (!mConfig.launchedWithNoRecentTasks) {
- mRecentsView.setTaskStacks(stacks);
- }
+ mRecentsView.setTaskStacks(stacks);
// Create the home intent runnable
Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
@@ -218,10 +217,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
ActivityOptions.makeCustomAnimation(this,
- mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_enter :
- R.anim.recents_to_launcher_enter,
- mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_exit :
- R.anim.recents_to_launcher_exit));
+ R.anim.recents_to_search_launcher_enter,
+ R.anim.recents_to_search_launcher_exit));
// Mark the task that is the launch target
int taskStackCount = stacks.size();
@@ -248,15 +245,26 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mEmptyView = mEmptyViewStub.inflate();
}
mEmptyView.setVisibility(View.VISIBLE);
+ mEmptyView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismissRecentsToHome(true);
+ }
+ });
mRecentsView.setSearchBarVisibility(View.GONE);
} else {
if (mEmptyView != null) {
mEmptyView.setVisibility(View.GONE);
+ mEmptyView.setOnClickListener(null);
}
- if (mRecentsView.hasValidSearchBar()) {
- mRecentsView.setSearchBarVisibility(View.VISIBLE);
+ if (!mConfig.searchBarEnabled) {
+ mRecentsView.setSearchBarVisibility(View.GONE);
} else {
- refreshSearchWidgetView();
+ if (mRecentsView.hasValidSearchBar()) {
+ mRecentsView.setSearchBarVisibility(View.VISIBLE);
+ } else {
+ refreshSearchWidgetView();
+ }
}
}
@@ -431,6 +439,14 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
@Override
+ protected void onResume() {
+ if (mConfig.searchBarEnabled && mConfig.launchedFromHome) {
+ overridePendingTransition(0, 0);
+ }
+ super.onResume();
+ }
+
+ @Override
protected void onPause() {
super.onPause();
if (mAfterPauseRunnable != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index dfe7e96..d7e8b99 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -31,6 +31,7 @@ import com.android.systemui.R;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import cyanogenmod.providers.CMSettings;
/** A static Recents configuration for the current context
* NOTE: We should not hold any references to a Context from a static instance */
@@ -73,6 +74,7 @@ public class RecentsConfiguration {
public int maxNumTasksToLoad;
/** Search bar */
+ public boolean searchBarEnabled = true;
public int searchBarSpaceHeightPx;
/** Task stack */
@@ -175,6 +177,14 @@ public class RecentsConfiguration {
return sInstance;
}
+ /** Returns the current recents configuration or creates and populates it if required */
+ public static RecentsConfiguration getInstance(Context context, SystemServicesProxy ssp) {
+ if (sInstance == null) {
+ sInstance = reinitialize(context, ssp);
+ }
+ return sInstance;
+ }
+
/** Updates the state, given the specified context */
void update(Context context) {
Resources res = context.getResources();
@@ -271,6 +281,13 @@ public class RecentsConfiguration {
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
}
+ public boolean updateShowSearch(Context context) {
+ boolean wasEnabled = searchBarEnabled;
+ searchBarEnabled = CMSettings.System.getInt(context.getContentResolver(),
+ CMSettings.System.RECENTS_SHOW_SEARCH_BAR, 1) == 1;
+ return wasEnabled != searchBarEnabled;
+ }
+
/** Updates the system insets */
public void updateSystemInsets(Rect insets) {
systemInsets.set(insets);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index cbf5c05..b1413c9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -30,9 +30,11 @@ import android.graphics.drawable.ColorDrawable;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.view.Gravity;
+import android.view.IWindowManager;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
@@ -49,6 +51,7 @@ public class ScreenPinningRequest implements View.OnClickListener {
private final AccessibilityManager mAccessibilityService;
private final WindowManager mWindowManager;
+ private final IWindowManager mWindowManagerService;
private RequestWindowView mRequestWindow;
@@ -58,6 +61,7 @@ public class ScreenPinningRequest implements View.OnClickListener {
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
mWindowManager = (WindowManager)
mContext.getSystemService(Context.WINDOW_SERVICE);
+ mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
}
public void clearPrompt() {
@@ -215,19 +219,33 @@ public class ScreenPinningRequest implements View.OnClickListener {
.setVisibility(View.INVISIBLE);
}
- final int description = mAccessibilityService.isEnabled()
+ final int description;
+ if (hasNavigationBar()) {
+ description = mAccessibilityService.isEnabled()
? R.string.screen_pinning_description_accessible
: R.string.screen_pinning_description;
+ final int backBgVis =
+ mAccessibilityService.isEnabled() ? View.INVISIBLE : View.VISIBLE;
+ mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVis);
+ mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVis);
+ } else {
+ description = R.string.screen_pinning_description_no_navbar;
+ ((ViewGroup) buttons.getParent()).removeView(buttons);
+ }
((TextView) mLayout.findViewById(R.id.screen_pinning_description))
.setText(description);
- final int backBgVisibility =
- mAccessibilityService.isEnabled() ? View.INVISIBLE : View.VISIBLE;
- mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
- mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
-
+
addView(mLayout, getRequestLayoutParams(isLandscape));
}
+ private boolean hasNavigationBar() {
+ try {
+ return mWindowManagerService.hasNavigationBar();
+ } catch (RemoteException e) {
+ //ignore
+ }
+ return false;
+ }
private void swapChildrenIfRtlAndVertical(View group) {
if (mContext.getResources().getConfiguration().getLayoutDirection()
!= View.LAYOUT_DIRECTION_RTL) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index ad25c85..4b3b391 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -458,7 +458,7 @@ public class RecentsTaskLoader {
/** Creates a new plan for loading the recent tasks. */
public RecentsTaskLoadPlan createLoadPlan(Context context) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
+ RecentsConfiguration config = RecentsConfiguration.getInstance(context, mSystemServicesProxy);
RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(context, config, mSystemServicesProxy);
return plan;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 947c19c..64622620 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -323,7 +323,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// Get the search bar bounds and measure the search bar layout
Rect searchBarSpaceBounds = new Rect();
- if (mSearchBar != null) {
+ if (mSearchBar != null && mConfig.searchBarEnabled) {
mConfig.getSearchBarBounds(width, height, mConfig.systemInsets.top, searchBarSpaceBounds);
mSearchBar.measure(
MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
@@ -360,7 +360,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// Get the search bar bounds so that we lay it out
- if (mSearchBar != null) {
+ if (mSearchBar != null && mConfig.searchBarEnabled) {
Rect searchBarSpaceBounds = new Rect();
mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
mConfig.systemInsets.top, searchBarSpaceBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0068f84..43b9a3e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -17,18 +17,27 @@
package com.android.systemui.recents.views;
import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDataObserver;
+import android.content.pm.PackageManager;
+import android.net.Uri;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
+import android.widget.PopupMenu;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
@@ -85,6 +94,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
boolean mDismissAllButtonAnimating;
int mFocusedTaskIndex = -1;
int mPrevAccessibilityFocusedIndex = -1;
+
+ private PopupMenu mPopup;
+
// Optimizations
int mStackViewsAnimationDuration;
boolean mStackViewsDirty = true;
@@ -1372,6 +1384,85 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
@Override
+ public void onTaskViewLongClicked(final TaskView tv) {
+ final PopupMenu popup = new PopupMenu(getContext(), tv.mHeaderView.mApplicationIcon);
+ mPopup = popup;
+ popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu());
+
+ final Task task = tv.getTask();
+ final String packageName = task.key.baseIntent.getComponent().getPackageName();
+
+ try {
+ PackageManager pm = (PackageManager) getContext().getPackageManager();
+ ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
+ DevicePolicyManager dpm = (DevicePolicyManager) getContext()
+ .getSystemService(Context.DEVICE_POLICY_SERVICE);
+
+ boolean hasActiveAdmins = dpm.packageHasActiveAdmins(packageName);
+ boolean isClearable = (appInfo.flags &
+ (ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA | ApplicationInfo.FLAG_SYSTEM)) !=
+ ApplicationInfo.FLAG_SYSTEM;
+ if (!isClearable || hasActiveAdmins) {
+ popup.getMenu().findItem(R.id.recent_wipe_app).setEnabled(false);
+ popup.getMenu().findItem(R.id.recent_uninstall).setEnabled(false);
+ }
+ } catch (PackageManager.NameNotFoundException ex) {
+ }
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.recent_remove_item:
+ onTaskViewDismissed(tv);
+ break;
+ case R.id.recent_inspect_item:
+ onTaskViewAppInfoClicked(tv);
+ break;
+ case R.id.recent_force_stop:
+ {
+ ActivityManager am = (ActivityManager) getContext()
+ .getSystemService(Context.ACTIVITY_SERVICE);
+ am.forceStopPackage(packageName);
+ onTaskViewDismissed(tv);
+ break;
+ }
+ case R.id.recent_wipe_app:
+ {
+ ActivityManager am = (ActivityManager) getContext()
+ .getSystemService(Context.ACTIVITY_SERVICE);
+ am.clearApplicationUserData(packageName, new IPackageDataObserver.Stub() {
+ @Override
+ public void onRemoveCompleted(String packageName, boolean succeeded) {}
+ });
+ onTaskViewDismissed(tv);
+ break;
+ }
+ case R.id.recent_uninstall:
+ {
+ Uri packageUri = Uri.parse("package:" + packageName);
+ Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri);
+ uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true);
+ getContext().startActivity(uninstallIntent);
+ onTaskViewDismissed(tv);
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+ }
+ });
+ popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
+ @Override
+ public void onDismiss(PopupMenu menu) {
+ mPopup = null;
+ }
+ });
+ popup.show();
+ }
+
+
+ @Override
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask) {
// Cancel any doze triggers
mUIDozeTrigger.stopDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index cbfe842..b7e46f4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -34,6 +34,7 @@ import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import cyanogenmod.providers.CMSettings;
/* A task view */
public class TaskView extends FrameLayout implements Task.TaskCallbacks,
@@ -43,6 +44,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
interface TaskViewCallbacks {
public void onTaskViewAppIconClicked(TaskView tv);
public void onTaskViewAppInfoClicked(TaskView tv);
+ public void onTaskViewLongClicked(TaskView tv);
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
public void onTaskViewDismissed(TaskView tv);
public void onTaskViewClipStateChanged(TaskView tv);
@@ -769,7 +771,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
public boolean onLongClick(View v) {
if (v == mHeaderView.mApplicationIcon) {
if (mCb != null) {
- mCb.onTaskViewAppInfoClicked(this);
+ boolean showDevShortcuts =
+ CMSettings.Secure.getInt(v.getContext().getContentResolver(),
+ CMSettings.Secure.DEVELOPMENT_SHORTCUT, 0) != 0;
+ if (showDevShortcuts) {
+ mCb.onTaskViewLongClicked(this);
+ } else {
+ mCb.onTaskViewAppInfoClicked(this);
+ }
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9e3cf37..260f625 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -430,6 +430,7 @@ class GlobalScreenshot {
private MediaActionSound mCameraSound;
+ private final int mSfHwRotation;
/**
* @param context everything needs a context :(
@@ -496,6 +497,9 @@ class GlobalScreenshot {
// Setup the Camera shutter sound
mCameraSound = new MediaActionSound();
mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
+
+ // Load hardware rotation from prop
+ mSfHwRotation = android.os.SystemProperties.getInt("ro.sf.hwrotation",0) / 90;
}
/**
@@ -539,7 +543,10 @@ class GlobalScreenshot {
// only in the natural orientation of the device :!)
mDisplay.getRealMetrics(mDisplayMetrics);
float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
- float degrees = getDegreesForRotation(mDisplay.getRotation());
+ int rot = mDisplay.getRotation();
+ // Allow for abnormal hardware orientation
+ rot = (rot + mSfHwRotation) % 4;
+ float degrees = getDegreesForRotation(rot);
boolean requiresRotation = (degrees > 0);
if (requiresRotation) {
// Get the dimensions of the device in its native orientation
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 77c27fa..e74edd0 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -42,7 +42,7 @@ public class BrightnessController implements ToggleSlider.Listener {
* {@link android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ} uses the range [-1, 1].
* Using this factor, it is converted to [0, BRIGHTNESS_ADJ_RESOLUTION] for the SeekBar.
*/
- private static final float BRIGHTNESS_ADJ_RESOLUTION = 2048;
+ public static final float BRIGHTNESS_ADJ_RESOLUTION = 2048;
private final int mMinimumBacklight;
private final int mMaximumBacklight;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessController.java
new file mode 100644
index 0000000..617ef8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessController.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2012-2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.systemui.R;
+
+import java.lang.Exception;
+import java.util.ArrayList;
+
+import cyanogenmod.providers.CMSettings;
+
+public class NotificationBrightnessController implements ToggleSlider.Listener {
+ private static final String TAG = "StatusBar.NotificationBrightnessController";
+
+ public static final int LIGHT_BRIGHTNESS_MINIMUM = 1;
+ public static final int LIGHT_BRIGHTNESS_MAXIMUM = 255;
+
+ // Minimum delay between LED notification updates
+ private final static long LED_UPDATE_DELAY_MS = 250;
+
+ private int mCurrentBrightness;
+ private final int mMinimumBrightness;
+ private final int mMaximumBrightness;
+
+ private final Context mContext;
+ private final ToggleSlider mControl;
+ private final CurrentUserTracker mUserTracker;
+ private final Handler mHandler;
+ private final NotificationBrightnessObserver mBrightnessObserver;
+
+ private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
+ new ArrayList<BrightnessStateChangeCallback>();
+
+ private boolean mListening;
+ private boolean mExternalChange;
+
+ private boolean mNotificationAllow;
+ private final Bundle mNotificationBundle;
+ private final Notification.Builder mNotificationBuilder;
+ private NotificationManager mNotificationManager;
+
+ public interface BrightnessStateChangeCallback {
+ public void onBrightnessLevelChanged();
+ }
+
+ /** ContentObserver to watch brightness **/
+ private class NotificationBrightnessObserver extends ContentObserver {
+
+ private final Uri NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL_URI =
+ CMSettings.System.getUriFor(CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL);
+
+ public NotificationBrightnessObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ onChange(selfChange, null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (selfChange) return;
+ try {
+ mExternalChange = true;
+ updateSlider();
+ for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
+ cb.onBrightnessLevelChanged();
+ }
+ } finally {
+ mExternalChange = false;
+ }
+ }
+
+ public void startObserving() {
+ final ContentResolver cr = mContext.getContentResolver();
+ cr.unregisterContentObserver(this);
+ cr.registerContentObserver(
+ NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL_URI,
+ false, this, UserHandle.USER_ALL);
+ }
+
+ public void stopObserving() {
+ final ContentResolver cr = mContext.getContentResolver();
+ cr.unregisterContentObserver(this);
+ }
+
+ }
+
+ public NotificationBrightnessController(Context context, ToggleSlider control) {
+ mContext = context;
+ mControl = control;
+ mHandler = new Handler();
+ mUserTracker = new CurrentUserTracker(mContext) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ updateSlider();
+ }
+ };
+ mBrightnessObserver = new NotificationBrightnessObserver(mHandler);
+
+ mMinimumBrightness = LIGHT_BRIGHTNESS_MINIMUM;
+ mMaximumBrightness = LIGHT_BRIGHTNESS_MAXIMUM;
+ mCurrentBrightness = LIGHT_BRIGHTNESS_MAXIMUM;
+
+ mNotificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ mNotificationBundle = new Bundle();
+ mNotificationBuilder = new Notification.Builder(mContext);
+
+ mNotificationBundle.putBoolean(Notification.EXTRA_FORCE_SHOW_LIGHTS, true);
+ mNotificationBuilder.setExtras(mNotificationBundle)
+ .setContentTitle(mContext.getString(R.string.led_notification_title))
+ .setContentText(mContext.getString(R.string.led_notification_text))
+ .setSmallIcon(R.drawable.ic_settings)
+ .setOngoing(true);
+ }
+
+ private Handler mLedHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ updateNotification();
+ }
+ };
+
+ public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+ }
+
+ public boolean removeStateChangedCallback(BrightnessStateChangeCallback cb) {
+ return mChangeCallbacks.remove(cb);
+ }
+
+ @Override
+ public void onInit(ToggleSlider control) {
+ // Do nothing
+ }
+
+ public void registerCallbacks() {
+ if (mListening) {
+ return;
+ }
+
+ // Update the slider and mode before attaching the listener so we don't
+ // receive the onChanged notifications for the initial values.
+ mNotificationAllow = true;
+ updateSlider();
+
+ mBrightnessObserver.startObserving();
+ mUserTracker.startTracking();
+
+ mControl.setOnChangedListener(this);
+ mListening = true;
+ }
+
+ /** Unregister all call backs, both to and from the controller */
+ public void unregisterCallbacks() {
+ if (!mListening) {
+ return;
+ }
+
+ mNotificationAllow = false;
+ mBrightnessObserver.stopObserving();
+ mUserTracker.stopTracking();
+ mControl.setOnChangedListener(null);
+ mNotificationManager.cancel(1);
+ mListening = false;
+
+ CMSettings.System.putIntForUser(mContext.getContentResolver(),
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
+ mCurrentBrightness, UserHandle.USER_CURRENT);
+ }
+
+ @Override
+ public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value,
+ boolean stopTracking) {
+ if (mExternalChange) return;
+
+ mCurrentBrightness = value + mMinimumBrightness;
+ updateNotification();
+
+ for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
+ cb.onBrightnessLevelChanged();
+ }
+ }
+
+ /** Fetch the brightness from the system settings and update the slider */
+ private void updateSlider() {
+ mCurrentBrightness = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
+ mMaximumBrightness, UserHandle.USER_CURRENT);
+
+ CMSettings.System.putIntForUser(mContext.getContentResolver(),
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
+ mMaximumBrightness, UserHandle.USER_CURRENT);
+
+ mControl.setMax(mMaximumBrightness - mMinimumBrightness);
+ mControl.setValue(mCurrentBrightness - mMinimumBrightness);
+ updateNotification();
+ }
+
+ /** Fetch the brightness from the system settings and update the slider */
+ private void updateNotification() {
+ // Dampen rate of consecutive LED changes
+ if (mLedHandler.hasMessages(0)) {
+ return;
+ }
+
+ if (mNotificationAllow) {
+ mLedHandler.sendEmptyMessageDelayed(0, LED_UPDATE_DELAY_MS);
+
+ // Instead of canceling the notification, force it to update with the color.
+ // Use a white light for a better preview of the brightness.
+ int notificationColor = 0xFFFFFF | (mCurrentBrightness << 24);
+ mNotificationBuilder.setLights(notificationColor, 1, 0);
+ mNotificationManager.notify(1, mNotificationBuilder.build());
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessDialog.java
new file mode 100644
index 0000000..82c1b3c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/NotificationBrightnessDialog.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012-2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+
+/** A dialog that provides controls for adjusting the notifications brightness. */
+public class NotificationBrightnessDialog extends Activity {
+
+ private NotificationBrightnessController mNotificationBrightnessController;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Window window = getWindow();
+
+ window.setGravity(Gravity.TOP);
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+ window.requestFeature(Window.FEATURE_NO_TITLE);
+
+ setContentView(R.layout.quick_settings_notification_brightness_dialog);
+
+ final ToggleSlider slider = (ToggleSlider) findViewById(R.id.notification_brightness_slider);
+ mNotificationBrightnessController = new NotificationBrightnessController(this, slider);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mNotificationBrightnessController.registerCallbacks();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mNotificationBrightnessController.unregisterCallbacks();
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
+ || keyCode == KeyEvent.KEYCODE_VOLUME_UP
+ || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
+ finish();
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 7f17885..dba74de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -34,6 +34,7 @@ import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
import com.android.systemui.R;
+import com.android.systemui.ViewInvertHelper;
/**
* Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
@@ -128,6 +129,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private final int mNormalColor;
private final int mLowPriorityColor;
private boolean mIsBelowSpeedBump;
+ private ViewInvertHelper mBackgroundNormalInvertHelper;
+ private ViewInvertHelper mBackgroundDimmedInvertHelper;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -145,6 +148,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mNormalColor = context.getColor(R.color.notification_material_background_color);
mLowPriorityColor = context.getColor(
R.color.notification_material_background_low_priority_color);
+ int roundedRectCornerRadius = getResources().getDimensionPixelSize(
+ R.dimen.notification_material_rounded_rect_radius);
+ setRoundCornerRadius(roundedRectCornerRadius); // Themes: For drop-shadow rounded corners
mTintedRippleColor = context.getColor(
R.color.notification_ripple_tinted_color);
mLowPriorityRippleColor = context.getColor(
@@ -160,6 +166,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
+ mBackgroundNormalInvertHelper =
+ new ViewInvertHelper(mBackgroundNormal, DARK_ANIMATION_LENGTH);
+ mBackgroundDimmedInvertHelper =
+ new ViewInvertHelper(mBackgroundDimmed, DARK_ANIMATION_LENGTH);
updateBackground();
updateBackgroundTint();
}
@@ -393,15 +403,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
*/
private void fadeInFromDark(long delay) {
final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal;
- background.setAlpha(0f);
- background.setPivotX(mBackgroundDimmed.getWidth() / 2f);
- background.setPivotY(getActualHeight() / 2f);
- background.setScaleX(DARK_EXIT_SCALE_START);
- background.setScaleY(DARK_EXIT_SCALE_START);
+ if (mDimmed) {
+ mBackgroundDimmedInvertHelper.fade(false, delay);
+ mBackgroundNormalInvertHelper.update(false);
+ } else {
+ mBackgroundDimmedInvertHelper.update(false);
+ mBackgroundNormalInvertHelper.fade(false, delay);
+ }
background.animate()
.alpha(1f)
- .scaleX(1f)
- .scaleY(1f)
.setDuration(DARK_ANIMATION_LENGTH)
.setStartDelay(delay)
.setInterpolator(mLinearOutSlowInInterpolator)
@@ -409,8 +419,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
@Override
public void onAnimationCancel(Animator animation) {
// Jump state if we are cancelled
- background.setScaleX(1f);
- background.setScaleY(1f);
background.setAlpha(1f);
}
})
@@ -463,9 +471,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private void updateBackground() {
cancelFadeAnimations();
+ mBackgroundNormalInvertHelper.update(mDark);
+ mBackgroundDimmedInvertHelper.update(mDark);
if (mDark) {
mBackgroundDimmed.setVisibility(View.INVISIBLE);
- mBackgroundNormal.setVisibility(View.INVISIBLE);
+ mBackgroundNormal.setVisibility(View.VISIBLE);
} else if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
mBackgroundNormal.setVisibility(View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f88b233..7b608bb 100644..100755
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -29,6 +29,8 @@ import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -38,10 +40,12 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.ThemeConfig;
import android.database.ContentObserver;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -87,6 +91,9 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.util.cm.SpamFilter;
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -97,6 +104,7 @@ import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.Recents;
+import com.android.systemui.cm.SpamMessageProvider;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -146,6 +154,12 @@ public abstract class BaseStatusBar extends SystemUI implements
private static final String BANNER_ACTION_SETUP =
"com.android.systemui.statusbar.banner_action_setup";
+ private static final Uri SPAM_MESSAGE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SpamMessageProvider.AUTHORITY)
+ .appendPath("messages")
+ .build();
+
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
protected H mHandler = createHandler();
@@ -237,6 +251,10 @@ public abstract class BaseStatusBar extends SystemUI implements
protected AssistManager mAssistManager;
+ // last theme that was applied in order to detect theme change (as opposed
+ // to some other configuration change).
+ protected ThemeConfig mCurrentTheme;
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -270,6 +288,10 @@ public abstract class BaseStatusBar extends SystemUI implements
}
};
+ public RemoteViews.OnClickHandler getOnClickHandler() {
+ return mOnClickHandler;
+ }
+
private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
@Override
public boolean onClickHandler(
@@ -915,6 +937,7 @@ public abstract class BaseStatusBar extends SystemUI implements
final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
final View appSettingsButton
= guts.findViewById(R.id.notification_inspect_app_provided_settings);
+ final View filterButton = guts.findViewById(R.id.notification_inspect_filter_notification);
if (appUid >= 0) {
final int appUidF = appUid;
settingsButton.setOnClickListener(new View.OnClickListener() {
@@ -924,6 +947,24 @@ public abstract class BaseStatusBar extends SystemUI implements
}
});
+ filterButton.setVisibility(View.VISIBLE);
+ filterButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ ContentValues values = new ContentValues();
+ String message = SpamFilter.getNotificationContent(
+ sbn.getNotification());
+ values.put(NotificationTable.MESSAGE_TEXT, message);
+ values.put(PackageTable.PACKAGE_NAME, pkg);
+ mContext.getContentResolver().insert(SPAM_MESSAGE_URI, values);
+ }
+ });
+ removeNotification(sbn.getKey(), null);
+ }
+ });
+
final Intent appSettingsQueryIntent
= new Intent(Intent.ACTION_MAIN)
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
@@ -953,6 +994,7 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
settingsButton.setVisibility(View.GONE);
appSettingsButton.setVisibility(View.GONE);
+ filterButton.setVisibility(View.GONE);
}
}
@@ -1092,26 +1134,6 @@ public abstract class BaseStatusBar extends SystemUI implements
protected abstract View getStatusBarView();
- protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
- // additional optimization when we have software system buttons - start loading the recent
- // tasks on touch down
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- int action = event.getAction() & MotionEvent.ACTION_MASK;
- if (action == MotionEvent.ACTION_DOWN) {
- preloadRecents();
- } else if (action == MotionEvent.ACTION_CANCEL) {
- cancelPreloadingRecents();
- } else if (action == MotionEvent.ACTION_UP) {
- if (!v.isPressed()) {
- cancelPreloadingRecents();
- }
-
- }
- return false;
- }
- };
-
/** Proxy for RecentsComponent */
protected void showRecents(boolean triggeredFromAltTab) {
@@ -1323,22 +1345,50 @@ public abstract class BaseStatusBar extends SystemUI implements
View contentViewLocal = null;
View bigContentViewLocal = null;
View headsUpContentViewLocal = null;
+ String themePackageName = mCurrentTheme != null
+ ? mCurrentTheme.getOverlayPkgNameForApp(sbn.getPackageName()) : null;
+ String statusBarThemePackageName = mCurrentTheme != null
+ ? mCurrentTheme.getOverlayForStatusBar() : null;
+
try {
contentViewLocal = contentView.apply(
sbn.getPackageContext(mContext),
contentContainer,
- mOnClickHandler);
+ mOnClickHandler,
+ statusBarThemePackageName);
+
+ final int platformTemplateRootViewId =
+ com.android.internal.R.id.status_bar_latest_event_content;
+ final String inflationThemePackageName;
+ if (themePackageName != null
+ && !TextUtils.equals(themePackageName, statusBarThemePackageName)
+ && contentViewLocal.getId() != platformTemplateRootViewId) {
+ // This notification uses custom RemoteViews, and its app uses a different
+ // theme than the status bar. Re-inflate the views using the app's theme,
+ // as the RemoteViews likely will contain resources of the app, not the platform
+ inflationThemePackageName = themePackageName;
+ contentViewLocal = contentView.apply(
+ sbn.getPackageContext(mContext),
+ contentContainer,
+ mOnClickHandler,
+ inflationThemePackageName);
+ } else {
+ inflationThemePackageName = statusBarThemePackageName;
+ }
+
if (bigContentView != null) {
bigContentViewLocal = bigContentView.apply(
sbn.getPackageContext(mContext),
contentContainer,
- mOnClickHandler);
+ mOnClickHandler,
+ inflationThemePackageName);
}
if (headsUpContentView != null) {
headsUpContentViewLocal = headsUpContentView.apply(
sbn.getPackageContext(mContext),
contentContainer,
- mOnClickHandler);
+ mOnClickHandler,
+ inflationThemePackageName);
}
}
catch (RuntimeException e) {
@@ -1403,49 +1453,12 @@ public abstract class BaseStatusBar extends SystemUI implements
title.setText(entry.notification.getPackageName());
}
- final ImageView icon = (ImageView) publicViewLocal.findViewById(R.id.icon);
- final ImageView profileBadge = (ImageView) publicViewLocal.findViewById(
- R.id.profile_badge_line3);
-
- final StatusBarIcon ic = new StatusBarIcon(
- entry.notification.getUser(),
- entry.notification.getPackageName(),
- entry.notification.getNotification().getSmallIcon(),
- entry.notification.getNotification().iconLevel,
- entry.notification.getNotification().number,
- entry.notification.getNotification().tickerText);
-
- Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
- icon.setImageDrawable(iconDrawable);
- if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP
- || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
- icon.setBackgroundResource(
- com.android.internal.R.drawable.notification_icon_legacy_bg);
- int padding = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_large_icon_circle_padding);
- icon.setPadding(padding, padding, padding, padding);
- if (sbn.getNotification().color != Notification.COLOR_DEFAULT) {
- icon.getBackground().setColorFilter(
- sbn.getNotification().color, PorterDuff.Mode.SRC_ATOP);
- }
- }
-
- if (profileBadge != null) {
- Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity(
- entry.notification.getUser(), 0);
- if (profileDrawable != null) {
- profileBadge.setImageDrawable(profileDrawable);
- profileBadge.setVisibility(View.VISIBLE);
- } else {
- profileBadge.setVisibility(View.GONE);
- }
- }
+ updatePublicViewProperties(publicViewLocal, entry);
final View privateTime = contentViewLocal.findViewById(com.android.internal.R.id.time);
final DateTimeView time = (DateTimeView) publicViewLocal.findViewById(R.id.time);
if (privateTime != null && privateTime.getVisibility() == View.VISIBLE) {
time.setVisibility(View.VISIBLE);
- time.setTime(entry.notification.getNotification().when);
}
final TextView text = (TextView) publicViewLocal.findViewById(R.id.text);
@@ -1958,7 +1971,9 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.icon.set(ic);
inflateViews(entry, mStackScroller);
}
- updateHeadsUp(key, entry, shouldInterrupt, alertAgain);
+ if (mUseHeadsUp) {
+ updateHeadsUp(key, entry, shouldInterrupt, alertAgain);
+ }
mNotificationData.updateRanking(ranking);
updateNotifications();
@@ -2052,6 +2067,7 @@ public abstract class BaseStatusBar extends SystemUI implements
final Notification publicVersion = notification.getNotification().publicVersion;
final RemoteViews publicContentView = publicVersion != null ? publicVersion.contentView
: null;
+ final View publicLocalView = entry.getPublicContentView();
// Reapply the RemoteViews
contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
@@ -2065,13 +2081,18 @@ public abstract class BaseStatusBar extends SystemUI implements
headsUpContentView.reapply(notification.getPackageContext(mContext),
headsUpChild, mOnClickHandler);
}
- if (publicContentView != null && entry.getPublicContentView() != null) {
- publicContentView.reapply(notification.getPackageContext(mContext),
- entry.getPublicContentView(), mOnClickHandler);
+ if (publicLocalView != null) {
+ if (publicContentView != null) {
+ publicContentView.reapply(notification.getPackageContext(mContext),
+ publicLocalView, mOnClickHandler);
+ } else {
+ updatePublicViewProperties(publicLocalView, entry);
+ }
}
// update the contentIntent
mNotificationClicker.register(entry.row, notification);
+ applyColorsAndBackgrounds(notification, entry);
entry.row.setStatusBarNotification(notification);
entry.row.notifyContentUpdated();
entry.row.resetHeight();
@@ -2081,6 +2102,55 @@ public abstract class BaseStatusBar extends SystemUI implements
maybeEscalateHeadsUp();
}
+ private void updatePublicViewProperties(View publicView, Entry entry) {
+ final StatusBarNotification n = entry.notification;
+ final ImageView icon = (ImageView) publicView.findViewById(R.id.icon);
+ final ImageView profileBadge =
+ (ImageView) publicView.findViewById(R.id.profile_badge_line3);
+ final DateTimeView time = (DateTimeView) publicView.findViewById(R.id.time);
+
+ if (icon != null) {
+ final StatusBarIcon ic = new StatusBarIcon(
+ n.getUser(), n.getPackageName(),
+ n.getNotification().getSmallIcon(),
+ n.getNotification().iconLevel,
+ n.getNotification().number,
+ n.getNotification().tickerText);
+
+ Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
+ icon.setImageDrawable(iconDrawable);
+ if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP
+ || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
+ icon.setBackgroundResource(
+ com.android.internal.R.drawable.notification_icon_legacy_bg);
+ int padding = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_large_icon_circle_padding);
+ icon.setPadding(padding, padding, padding, padding);
+ if (n.getNotification().color != Notification.COLOR_DEFAULT) {
+ icon.getBackground().setColorFilter(
+ n.getNotification().color, PorterDuff.Mode.SRC_ATOP);
+ }
+ } else {
+ icon.setBackgroundDrawable(null);
+ }
+ }
+
+ if (time != null) {
+ time.setTime(entry.notification.getNotification().when);
+ }
+
+ if (profileBadge != null) {
+ Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity(
+ n.getUser(), 0);
+ if (profileDrawable != null) {
+ profileBadge.setImageDrawable(profileDrawable);
+ profileBadge.setVisibility(View.VISIBLE);
+ } else {
+ profileBadge.setVisibility(View.GONE);
+ }
+ }
+ }
+
private boolean alertAgain(Entry oldEntry, Notification newNotification) {
return oldEntry == null || !oldEntry.hasInterrupted()
|| (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 897f5e5..83b2fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -78,6 +78,7 @@ public class CommandQueue extends IStatusBar.Stub {
private StatusBarIconList mList;
private Callbacks mCallbacks;
private Handler mHandler = new H();
+ private boolean mPaused = false;
/**
* These methods are called back on the main thread.
@@ -295,6 +296,14 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
+ public void pause() {
+ mPaused = true;
+ }
+
+ public void resume() {
+ mPaused = false;
+ }
+
@Override
public void onCameraLaunchGestureDetected(int source) {
synchronized (mList) {
@@ -305,6 +314,10 @@ public class CommandQueue extends IStatusBar.Stub {
private final class H extends Handler {
public void handleMessage(Message msg) {
+ if (mPaused) {
+ this.sendMessageAtFrontOfQueue(Message.obtain(msg));
+ return;
+ }
final int what = msg.what & MSG_MASK;
switch (what) {
case MSG_ICON: {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java b/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java
new file mode 100644
index 0000000..4be7292
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import cyanogenmod.app.StatusBarPanelCustomTile;
+
+import android.util.ArrayMap;
+
+/**
+ * Custom tile data to keep track of created 3rd party tiles
+ */
+public class CustomTileData {
+ public static final class Entry {
+ public final String key;
+ public final StatusBarPanelCustomTile sbc;
+
+ public Entry(StatusBarPanelCustomTile sbc) {
+ this.key = sbc.getKey();
+ this.sbc = sbc;
+ }
+ }
+
+ private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
+
+ public ArrayMap<String, Entry> getEntries() {
+ return mEntries;
+ }
+
+ public void add(Entry entry) {
+ mEntries.put(entry.key, entry);
+ }
+
+ public Entry remove(String key) {
+ Entry removed = mEntries.remove(key);
+ if (removed == null) return null;
+ return removed;
+ }
+
+ public Entry get(String key) {
+ return mEntries.get(key);
+ }
+
+ public Entry get(int i) {
+ return mEntries.valueAt(i);
+ }
+
+ public void clear() {
+ mEntries.clear();
+ }
+
+ public int size() {
+ return mEntries.size();
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 56e9af5..c964ca7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -531,6 +531,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
public void setExpandable(boolean expandable) {
mExpandable = expandable;
+ setClipToOutline(expandable);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index a6fc4bb..cc50e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -34,6 +34,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
private final Rect mOutlineRect = new Rect();
protected final int mRoundedRectCornerRadius;
private boolean mCustomOutline;
+ private float mRoundCornerRadius = 0;
private float mOutlineAlpha = 1f;
public ExpandableOutlineView(Context context, AttributeSet attrs) {
@@ -44,12 +45,12 @@ public abstract class ExpandableOutlineView extends ExpandableView {
@Override
public void getOutline(View view, Outline outline) {
if (!mCustomOutline) {
- outline.setRect(0,
+ outline.setRoundRect(0,
mClipTopAmount,
getWidth(),
- Math.max(getActualHeight(), mClipTopAmount));
+ Math.max(getActualHeight(), mClipTopAmount), mRoundCornerRadius);
} else {
- outline.setRoundRect(mOutlineRect, mRoundedRectCornerRadius);
+ outline.setRoundRect(mOutlineRect, mRoundCornerRadius);
}
outline.setAlpha(mOutlineAlpha);
}
@@ -96,4 +97,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
invalidateOutline();
}
+ protected void setRoundCornerRadius(float roundRadius) {
+ mRoundCornerRadius = roundRadius;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 8058933..26b9c8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -25,9 +25,13 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Color;
+import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.support.v7.graphics.Palette;
import android.util.AttributeSet;
import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
@@ -45,7 +49,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
* An ImageView which does not have overlapping renderings commands and therefore does not need a
* layer when alpha is changed.
*/
-public class KeyguardAffordanceView extends ImageView {
+public class KeyguardAffordanceView extends ImageView implements Palette.PaletteAsyncListener {
private static final long CIRCLE_APPEAR_DURATION = 80;
private static final long CIRCLE_DISAPPEAR_MAX_DURATION = 200;
@@ -81,6 +85,7 @@ public class KeyguardAffordanceView extends ImageView {
private boolean mSupportHardware;
private boolean mFinishing;
private boolean mLaunchingAffordance;
+ private ColorFilter mDefaultFilter;
private CanvasProperty<Float> mHwCircleRadius;
private CanvasProperty<Float> mHwCenterX;
@@ -162,21 +167,66 @@ public class KeyguardAffordanceView extends ImageView {
canvas.restore();
}
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ super.setImageDrawable(drawable);
+ doPaletteIfNecessary();
+ }
+
+ private void doPaletteIfNecessary() {
+ if (mDefaultFilter != null && getDrawable() instanceof BitmapDrawable) {
+ Palette.generateAsync(((BitmapDrawable) getDrawable()).getBitmap(), this);
+ }
+ }
+
+
public void setPreviewView(View v) {
View oldPreviewView = mPreviewView;
mPreviewView = v;
if (mPreviewView != null) {
mPreviewView.setVisibility(mLaunchingAffordance
? oldPreviewView.getVisibility() : INVISIBLE);
+ mPreviewView.setVisibility(INVISIBLE);
+ addOverlay();
}
}
+ private void addOverlay() {
+ if (mPreviewView != null) {
+ mPreviewView.getOverlay().clear();
+ if (mDefaultFilter != null) {
+ ColorDrawable d = new ColorDrawable(mCircleColor);
+ d.setBounds(0, 0, mPreviewView.getWidth(), mPreviewView.getHeight());
+ mPreviewView.getOverlay().add(d);
+ }
+ }
+ }
+
+ public void setDefaultFilter(ColorFilter filter) {
+ mDefaultFilter = filter;
+ mCircleColor = Color.WHITE;
+ addOverlay();
+ updateIconColor();
+ }
+
private void updateIconColor() {
+ if (getDrawable() == null) {
+ return;
+ }
Drawable drawable = getDrawable().mutate();
float alpha = mCircleRadius / mMinBackgroundRadius;
alpha = Math.min(1.0f, alpha);
int color = (int) mColorInterpolator.evaluate(alpha, mNormalColor, mInverseColor);
- drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+ if (mDefaultFilter != null) {
+ if (alpha == 0) {
+ drawable.setColorFilter(mDefaultFilter);
+ } else {
+ drawable.setColorFilter(color, PorterDuff.Mode.DST_IN);
+ }
+ } else {
+ drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+ }
}
private void drawBackgroundCircle(Canvas canvas) {
@@ -551,4 +601,10 @@ public class KeyguardAffordanceView extends ImageView {
public void setLaunchingAffordance(boolean launchingAffordance) {
mLaunchingAffordance = launchingAffordance;
}
+
+ @Override
+ public void onGenerated(Palette palette) {
+ mCircleColor = palette.getDarkVibrantColor(Color.WHITE);
+ addOverlay();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index fd84345..318ef5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -153,6 +153,11 @@ public class KeyguardIndicationController {
}
}
+ public void cleanup() {
+ KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor);
+ mContext.unregisterReceiver(mReceiver);
+ }
+
private void updateIndication() {
if (mVisible) {
mTextView.switchIndication(computeIndication());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index aedae52..c8c318b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -191,6 +191,14 @@ public class NotificationData {
return mEntries.get(key);
}
+ public Entry get(int i) {
+ return mEntries.valueAt(i);
+ }
+
+ public RankingMap getRankingMap() {
+ return mRankingMap;
+ }
+
public void add(Entry entry, RankingMap ranking) {
mEntries.put(entry.notification.getKey(), entry);
updateRankingAndSort(ranking);
@@ -288,6 +296,14 @@ public class NotificationData {
return false;
}
+ public void clear() {
+ mEntries.clear();
+ }
+
+ public int size() {
+ return mEntries.size();
+ }
+
// Q: What kinds of notifications should show during setup?
// A: Almost none! Only things coming from the system (package is "android") that also
// have special "kind" tags marking them as relevant for setup (see below).
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 68e483c..ecaa809 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -88,8 +88,6 @@ public class SignalClusterView
private int mWideTypeIconStartPadding;
private int mSecondaryTelephonyPadding;
- private int mEndPadding;
- private int mEndPaddingNothingVisible;
private boolean mBlockAirplane;
private boolean mBlockMobile;
@@ -138,9 +136,14 @@ public class SignalClusterView
public void setSecurityController(SecurityController sc) {
if (DEBUG) Log.d(TAG, "SecurityController=" + sc);
+ if (sc == null && mSC != null) {
+ mSC.removeCallback(this);
+ }
mSC = sc;
- mSC.addCallback(this);
- mVpnVisible = mSC.isVpnEnabled();
+ if (mSC != null) {
+ mSC.addCallback(this);
+ mVpnVisible = mSC.isVpnEnabled();
+ }
}
@Override
@@ -150,10 +153,6 @@ public class SignalClusterView
R.dimen.wide_type_icon_start_padding);
mSecondaryTelephonyPadding = getContext().getResources().getDimensionPixelSize(
R.dimen.secondary_telephony_padding);
- mEndPadding = getContext().getResources().getDimensionPixelSize(
- R.dimen.signal_cluster_battery_padding);
- mEndPaddingNothingVisible = getContext().getResources().getDimensionPixelSize(
- R.dimen.no_signal_cluster_battery_padding);
}
@Override
@@ -204,8 +203,10 @@ public class SignalClusterView
post(new Runnable() {
@Override
public void run() {
- mVpnVisible = mSC.isVpnEnabled();
- apply();
+ if (mSC != null) {
+ mVpnVisible = mSC.isVpnEnabled();
+ apply();
+ }
}
});
}
@@ -223,7 +224,7 @@ public class SignalClusterView
@Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
- String description, boolean isWide, int subId) {
+ String description, boolean isWide, boolean showRoamingIndicator, int subId) {
PhoneState state = getState(subId);
if (state == null) {
return;
@@ -234,6 +235,7 @@ public class SignalClusterView
state.mMobileDescription = statusIcon.contentDescription;
state.mMobileTypeDescription = typeContentDescription;
state.mIsMobileTypeIconWide = statusType != 0 && isWide;
+ state.mShowRoamingIndicator = showRoamingIndicator;
apply();
}
@@ -450,10 +452,6 @@ public class SignalClusterView
}
mNoSimsCombo.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
-
- boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
- || anyMobileVisible || mVpnVisible || mEthernetVisible;
- setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
}
public void setIconTint(int tint, float darkIntensity) {
@@ -493,9 +491,11 @@ public class SignalClusterView
private int mLastMobileTypeId = -1;
private boolean mIsMobileTypeIconWide;
private String mMobileDescription, mMobileTypeDescription;
+ private boolean mShowRoamingIndicator;
private ViewGroup mMobileGroup;
private ImageView mMobile, mMobileDark, mMobileType;
+ private ImageView mMobileRoaming;
public PhoneState(int subId, Context context) {
ViewGroup root = (ViewGroup) LayoutInflater.from(context)
@@ -509,6 +509,7 @@ public class SignalClusterView
mMobile = (ImageView) root.findViewById(R.id.mobile_signal);
mMobileDark = (ImageView) root.findViewById(R.id.mobile_signal_dark);
mMobileType = (ImageView) root.findViewById(R.id.mobile_type);
+ mMobileRoaming = (ImageView) root.findViewById(R.id.mobile_roaming);
}
public boolean apply(boolean isSecondaryIcon) {
@@ -526,6 +527,7 @@ public class SignalClusterView
mMobileGroup.setContentDescription(mMobileTypeDescription
+ " " + mMobileDescription);
mMobileGroup.setVisibility(View.VISIBLE);
+ mMobileRoaming.setVisibility(mShowRoamingIndicator ? View.VISIBLE : View.GONE);
} else {
mMobileGroup.setVisibility(View.GONE);
}
@@ -582,6 +584,7 @@ public class SignalClusterView
public void setIconTint(int tint, float darkIntensity) {
applyDarkIntensity(darkIntensity, mMobile, mMobileDark);
setTint(mMobileType, tint);
+ setTint(mMobileRoaming, tint);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
index 2f66c41..9103525 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
@@ -87,6 +87,7 @@ public abstract class StackScrollerDecorView extends ExpandableView {
mAnimating = true;
mContent.animate()
.alpha(endValue)
+ .withLayer()
.setInterpolator(interpolator)
.setDuration(260)
.withEndAction(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index baac8ac..4371cce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -19,12 +19,16 @@ package com.android.systemui.statusbar;
import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
+import android.content.res.ThemeConfig;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.graphics.Typeface;
+import android.os.Handler;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
@@ -34,8 +38,12 @@ import android.widget.ImageView;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
import java.text.NumberFormat;
+import java.util.ArrayList;
+
+import cyanogenmod.providers.CMSettings;
public class StatusBarIconView extends AnimatedImageView {
private static final String TAG = "StatusBarIconView";
@@ -43,12 +51,14 @@ public class StatusBarIconView extends AnimatedImageView {
private StatusBarIcon mIcon;
@ViewDebug.ExportedProperty private String mSlot;
private Drawable mNumberBackground;
- private Paint mNumberPain;
+ private Paint mNumberPaint;
private int mNumberX;
private int mNumberY;
private String mNumberText;
private Notification mNotification;
private final boolean mBlocked;
+ private boolean mShowNotificationCount;
+ private GlobalSettingsObserver mObserver;
public StatusBarIconView(Context context, String slot, Notification notification) {
this(context, slot, notification, false);
@@ -60,12 +70,10 @@ public class StatusBarIconView extends AnimatedImageView {
final Resources res = context.getResources();
mBlocked = blocked;
mSlot = slot;
- mNumberPain = new Paint();
- mNumberPain.setTextAlign(Paint.Align.CENTER);
- mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
- mNumberPain.setAntiAlias(true);
setNotification(notification);
+ mObserver = GlobalSettingsObserver.getInstance(context);
+
// We do not resize and scale system icons (on the right), only notification icons (on the
// left).
if (notification != null) {
@@ -81,6 +89,8 @@ public class StatusBarIconView extends AnimatedImageView {
public void setNotification(Notification notification) {
mNotification = notification;
+ mShowNotificationCount = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.STATUS_BAR_NOTIF_COUNT, 0, UserHandle.USER_CURRENT) == 1;
setContentDescription(notification);
}
@@ -124,6 +134,10 @@ public class StatusBarIconView extends AnimatedImageView {
* Returns whether the set succeeded.
*/
public boolean set(StatusBarIcon icon) {
+ return set(icon, false);
+ }
+
+ private boolean set(StatusBarIcon icon, boolean force) {
final boolean iconEquals = mIcon != null && equalIcons(mIcon.icon, icon.icon);
final boolean levelEquals = iconEquals
&& mIcon.iconLevel == icon.iconLevel;
@@ -133,17 +147,25 @@ public class StatusBarIconView extends AnimatedImageView {
&& mIcon.number == icon.number;
mIcon = icon.clone();
setContentDescription(icon.contentDescription);
- if (!iconEquals) {
+ if (!iconEquals || force) {
if (!updateDrawable(false /* no clear */)) return false;
}
- if (!levelEquals) {
+ if (!levelEquals || force) {
setImageLevel(icon.iconLevel);
}
- if (!numberEquals) {
- if (icon.number > 0 && getContext().getResources().getBoolean(
- R.bool.config_statusBarShowNumber)) {
+ if (!numberEquals || force) {
+ if (icon.number > 1 && mShowNotificationCount) {
if (mNumberBackground == null) {
+ final Resources res = mContext.getResources();
+ final float densityMultiplier = res.getDisplayMetrics().density;
+ final float scaledPx = 8 * densityMultiplier;
+ mNumberPaint = new Paint();
+ mNumberPaint.setTextAlign(Paint.Align.CENTER);
+ mNumberPaint.setColor(res.getColor(R.drawable.notification_number_text_color));
+ mNumberPaint.setAntiAlias(true);
+ mNumberPaint.setTypeface(Typeface.DEFAULT_BOLD);
+ mNumberPaint.setTextSize(scaledPx);
mNumberBackground = getContext().getResources().getDrawable(
R.drawable.ic_notification_overlay);
}
@@ -151,10 +173,11 @@ public class StatusBarIconView extends AnimatedImageView {
} else {
mNumberBackground = null;
mNumberText = null;
+ mNumberPaint = null;
}
invalidate();
}
- if (!visibilityEquals) {
+ if (!visibilityEquals || force) {
setVisibility(icon.visible && !mBlocked ? VISIBLE : GONE);
}
return true;
@@ -211,6 +234,10 @@ public class StatusBarIconView extends AnimatedImageView {
}
}
+ public String getStatusBarSlot() {
+ return mSlot;
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
@@ -231,7 +258,25 @@ public class StatusBarIconView extends AnimatedImageView {
if (mNumberBackground != null) {
mNumberBackground.draw(canvas);
- canvas.drawText(mNumberText, mNumberX, mNumberY, mNumberPain);
+ canvas.drawText(mNumberText, mNumberX, mNumberY, mNumberPaint);
+ }
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (mObserver != null) {
+ mObserver.attach(this);
+ }
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ if (mObserver != null) {
+ mObserver.detach(this);
}
}
@@ -248,7 +293,7 @@ public class StatusBarIconView extends AnimatedImageView {
android.R.integer.status_bar_notification_info_maxnum);
if (mIcon.number > tooBig) {
str = getContext().getResources().getString(
- android.R.string.status_bar_notification_info_overflow);
+ R.string.status_bar_notification_info_overflow);
} else {
NumberFormat f = NumberFormat.getIntegerInstance();
str = f.format(mIcon.number);
@@ -258,7 +303,7 @@ public class StatusBarIconView extends AnimatedImageView {
final int w = getWidth();
final int h = getHeight();
final Rect r = new Rect();
- mNumberPain.getTextBounds(str, 0, str.length(), r);
+ mNumberPaint.getTextBounds(str, 0, str.length(), r);
final int tw = r.right - r.left;
final int th = r.bottom - r.top;
mNumberBackground.getPadding(r);
@@ -292,4 +337,63 @@ public class StatusBarIconView extends AnimatedImageView {
public String getSlot() {
return mSlot;
}
+
+ static class GlobalSettingsObserver extends UserContentObserver {
+ private static GlobalSettingsObserver sInstance;
+ private ArrayList<StatusBarIconView> mIconViews = new ArrayList<StatusBarIconView>();
+ private Context mContext;
+
+ GlobalSettingsObserver(Handler handler, Context context) {
+ super(handler);
+ mContext = context.getApplicationContext();
+ }
+
+ static GlobalSettingsObserver getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new GlobalSettingsObserver(new Handler(), context);
+ }
+ return sInstance;
+ }
+
+ void attach(StatusBarIconView sbiv) {
+ if (mIconViews.isEmpty()) {
+ observe();
+ }
+ mIconViews.add(sbiv);
+ }
+
+ void detach(StatusBarIconView sbiv) {
+ mIconViews.remove(sbiv);
+ if (mIconViews.isEmpty()) {
+ unobserve();
+ }
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_NOTIF_COUNT),
+ false, this);
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ public void update() {
+ boolean showIconCount = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.STATUS_BAR_NOTIF_COUNT, 0, UserHandle.USER_CURRENT) == 1;
+ for (StatusBarIconView sbiv : mIconViews) {
+ sbiv.mShowNotificationCount = showIconCount;
+ sbiv.set(sbiv.mIcon, true);
+ }
+ }
+ }
}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java
new file mode 100644
index 0000000..1991602
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java
@@ -0,0 +1,377 @@
+/*
+* Copyright (C) 2015 The CyanogenMod Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.android.systemui.statusbar;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.media.audiofx.Visualizer;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v7.graphics.Palette;
+import android.util.AttributeSet;
+import android.view.View;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import cyanogenmod.providers.CMSettings;
+
+import java.util.Arrays;
+
+public class VisualizerView extends View implements Palette.PaletteAsyncListener,
+ KeyguardMonitor.Callback {
+
+ private Paint mPaint;
+ private Visualizer mVisualizer;
+ private ObjectAnimator mVisualizerColorAnimator;
+
+ private ValueAnimator[] mValueAnimators;
+ private float[] mFFTPoints;
+
+ private boolean mVisualizerEnabled = false;
+ private boolean mVisible = false;
+ private boolean mPlaying = false;
+ private boolean mPowerSaveMode = false;
+ private boolean mDisplaying = false; // the state we're animating to
+ private boolean mDozing = false;
+ private boolean mOccluded = false;
+
+ private int mColor;
+ private Bitmap mCurrentBitmap;
+
+ private KeyguardMonitor mKeyguardMonitor;
+ private SettingsObserver mObserver;
+
+ private Visualizer.OnDataCaptureListener mVisualizerListener =
+ new Visualizer.OnDataCaptureListener() {
+ byte rfk, ifk;
+ int dbValue;
+ float magnitude;
+
+ @Override
+ public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {
+ }
+
+ @Override
+ public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
+ for (int i = 0; i < 32; i++) {
+ mValueAnimators[i].cancel();
+ rfk = fft[i * 2 + 2];
+ ifk = fft[i * 2 + 3];
+ magnitude = rfk * rfk + ifk * ifk;
+ dbValue = magnitude > 0 ? (int) (10 * Math.log10(magnitude)) : 0;
+
+ mValueAnimators[i].setFloatValues(mFFTPoints[i * 4 + 1],
+ mFFTPoints[3] - (dbValue * 16f));
+ mValueAnimators[i].start();
+ }
+ }
+ };
+
+ private final Runnable mLinkVisualizer = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mVisualizer = new Visualizer(0);
+ } catch (Exception e) {
+ return;
+ }
+
+ mVisualizer.setEnabled(false);
+ mVisualizer.setCaptureSize(66);
+ mVisualizer.setDataCaptureListener(mVisualizerListener,Visualizer.getMaxCaptureRate(),
+ false, true);
+ mVisualizer.setEnabled(true);
+
+ }
+ };
+
+ private final Runnable mUnlinkVisualizer = new Runnable() {
+ @Override
+ public void run() {
+ if (mVisualizer != null) {
+ mVisualizer.setEnabled(false);
+ mVisualizer.release();
+ mVisualizer = null;
+ }
+ }
+ };
+
+ public VisualizerView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ mColor = Color.TRANSPARENT;
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(mColor);
+
+ mFFTPoints = new float[128];
+ mValueAnimators = new ValueAnimator[32];
+ for (int i = 0; i < 32; i++) {
+ final int j = i * 4 + 1;
+ mValueAnimators[i] = new ValueAnimator();
+ mValueAnimators[i].setDuration(128);
+ mValueAnimators[i].addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mFFTPoints[j] = (float) animation.getAnimatedValue();
+ postInvalidate();
+ }
+ });
+ }
+ }
+
+ public VisualizerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public VisualizerView(Context context) {
+ this(context, null, 0);
+ }
+
+ @Override
+ public void onKeyguardChanged() {
+ updateViewVisibility();
+ }
+
+ private void updateViewVisibility() {
+ setVisibility(mKeyguardMonitor != null && mKeyguardMonitor.isShowing()
+ && mVisualizerEnabled ? View.VISIBLE : View.GONE);
+ checkStateChanged();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (mKeyguardMonitor != null) {
+ mKeyguardMonitor.addCallback(this);
+ }
+ mObserver = new SettingsObserver(new Handler());
+ mObserver.observe();
+ mObserver.update();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mKeyguardMonitor != null) {
+ mKeyguardMonitor.removeCallback(this);
+ }
+ mObserver.unobserve();
+ mObserver = null;
+ mCurrentBitmap = null;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ final int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
+ setMeasuredDimension(size, size);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ float barUnit = w / 32f;
+ float barWidth = barUnit * 8f / 9f;
+ barUnit = barWidth + (barUnit - barWidth) * 32f / 31f;
+ mPaint.setStrokeWidth(barWidth);
+
+ for (int i = 0; i < 32; i++) {
+ mFFTPoints[i * 4] = mFFTPoints[i * 4 + 2] = i * barUnit + (barWidth / 2);
+ mFFTPoints[i * 4 + 1] = h;
+ mFFTPoints[i * 4 + 3] = h;
+ }
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return mVisualizerEnabled && mDisplaying;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mVisualizer != null) {
+ canvas.drawLines(mFFTPoints, mPaint);
+ }
+ }
+
+ public void setKeyguardMonitor(KeyguardMonitor kgm) {
+ mKeyguardMonitor = kgm;
+ if (isAttachedToWindow()) {
+ // otherwise we might never register ourselves
+ mKeyguardMonitor.addCallback(this);
+ updateViewVisibility();
+ }
+ }
+
+ public void setVisible(boolean visible) {
+ if (mVisible != visible) {
+ mVisible = visible;
+ checkStateChanged();
+ }
+ }
+
+ public void setDozing(boolean dozing) {
+ if (mDozing != dozing) {
+ mDozing = dozing;
+ checkStateChanged();
+ }
+ }
+
+ public void setPlaying(boolean playing) {
+ if (mPlaying != playing) {
+ mPlaying = playing;
+ checkStateChanged();
+ }
+ }
+
+ public void setPowerSaveMode(boolean powerSaveMode) {
+ if (mPowerSaveMode != powerSaveMode) {
+ mPowerSaveMode = powerSaveMode;
+ checkStateChanged();
+ }
+ }
+
+ public void setOccluded(boolean occluded) {
+ if (mOccluded != occluded) {
+ mOccluded = occluded;
+ checkStateChanged();
+ }
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ if (mCurrentBitmap == bitmap) {
+ return;
+ }
+ mCurrentBitmap = bitmap;
+ if (bitmap != null) {
+ Palette.generateAsync(bitmap, this);
+ } else {
+ setColor(Color.TRANSPARENT);
+ }
+ }
+
+ @Override
+ public void onGenerated(Palette palette) {
+ int color = Color.TRANSPARENT;
+
+ color = palette.getVibrantColor(color);
+ if (color == Color.TRANSPARENT) {
+ color = palette.getLightVibrantColor(color);
+ if (color == Color.TRANSPARENT) {
+ color = palette.getDarkVibrantColor(color);
+ }
+ }
+
+ setColor(color);
+ }
+
+ private void setColor(int color) {
+ if (color == Color.TRANSPARENT) {
+ color = Color.WHITE;
+ }
+
+ color = Color.argb(140, Color.red(color), Color.green(color), Color.blue(color));
+
+ if (mColor != color) {
+ mColor = color;
+
+ if (mVisualizer != null) {
+ if (mVisualizerColorAnimator != null) {
+ mVisualizerColorAnimator.cancel();
+ }
+
+ mVisualizerColorAnimator = ObjectAnimator.ofArgb(mPaint, "color",
+ mPaint.getColor(), mColor);
+ mVisualizerColorAnimator.setStartDelay(600);
+ mVisualizerColorAnimator.setDuration(1200);
+ mVisualizerColorAnimator.start();
+ } else {
+ mPaint.setColor(mColor);
+ }
+ }
+ }
+
+ private void checkStateChanged() {
+ if (getVisibility() == View.VISIBLE && mVisible && mPlaying && !mDozing && !mPowerSaveMode
+ && mVisualizerEnabled && !mOccluded) {
+ if (!mDisplaying) {
+ mDisplaying = true;
+ AsyncTask.execute(mLinkVisualizer);
+ animate()
+ .alpha(1f)
+ .withEndAction(null)
+ .setDuration(800);
+ }
+ } else {
+ if (mDisplaying) {
+ mDisplaying = false;
+ if (mVisible) {
+ animate()
+ .alpha(0f)
+ .withEndAction(mUnlinkVisualizer)
+ .setDuration(600);
+ } else {
+ AsyncTask.execute(mUnlinkVisualizer);
+ animate().
+ alpha(0f)
+ .withEndAction(null)
+ .setDuration(0);
+ }
+ }
+ }
+ }
+
+ private class SettingsObserver extends UserContentObserver {
+
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void update() {
+ mVisualizerEnabled = CMSettings.Secure.getInt(getContext().getContentResolver(),
+ CMSettings.Secure.LOCKSCREEN_VISUALIZER_ENABLED, 1) != 0;
+ checkStateChanged();
+ updateViewVisibility();
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+ getContext().getContentResolver().registerContentObserver(
+ CMSettings.Secure.getUriFor(CMSettings.Secure.LOCKSCREEN_VISUALIZER_ENABLED),
+ false, this, UserHandle.USER_CURRENT);
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+ getContext().getContentResolver().unregisterContentObserver(this);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BackButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BackButtonDrawable.java
new file mode 100644
index 0000000..c76b5d3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BackButtonDrawable.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.systemui.statusbar.phone;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.FloatProperty;
+import android.util.Property;
+
+public class BackButtonDrawable extends Drawable {
+ private final Drawable mWrappedDrawable;
+ private float mRotation;
+ private Animator mCurrentAnimator;
+
+ private static final int ANIMATION_DURATION = 200;
+ public static final Property<BackButtonDrawable, Float> ROTATION
+ = new FloatProperty<BackButtonDrawable>("rotation") {
+ @Override
+ public void setValue(BackButtonDrawable object, float value) {
+ object.setRotation(value);
+ }
+
+ @Override
+ public Float get(BackButtonDrawable object) {
+ return object.getRotation();
+ }
+ };
+
+ public BackButtonDrawable(Drawable wrappedDrawable) {
+ mWrappedDrawable = wrappedDrawable;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final Rect bounds = mWrappedDrawable.getBounds();
+ final int boundsCenterX = bounds.width() / 2;
+ final int boundsCenterY = bounds.height() / 2;
+
+ canvas.translate(boundsCenterX, boundsCenterY);
+ canvas.rotate(mRotation);
+ canvas.translate(- boundsCenterX, - boundsCenterY);
+
+ mWrappedDrawable.draw(canvas);
+ }
+
+ @Override
+ public void setBounds(Rect bounds) {
+ mWrappedDrawable.setBounds(bounds);
+ }
+
+ @Override
+ public void setBounds(int left, int top, int right, int bottom) {
+ mWrappedDrawable.setBounds(left, top, right, bottom);
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ mWrappedDrawable.setBounds(bounds);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mWrappedDrawable.setAlpha(alpha);
+ if (mCurrentAnimator != null) {
+ mCurrentAnimator.end();
+ }
+ }
+
+ @Override
+ public int getAlpha() {
+ return mWrappedDrawable.getAlpha();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return mWrappedDrawable.getOpacity();
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mWrappedDrawable.getIntrinsicWidth();
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mWrappedDrawable.getIntrinsicHeight();
+ }
+
+ public void setRotation(float rotation) {
+ mRotation = rotation;
+ invalidateSelf();
+ }
+
+ public float getRotation() {
+ return mRotation;
+ }
+
+ public void setImeVisible(boolean ime) {
+ if (mCurrentAnimator != null) {
+ mCurrentAnimator.cancel();
+ }
+
+ final float nextRotation = ime ? - 90 : 0;
+ if (mRotation == nextRotation) {
+ return;
+ }
+
+ if (isVisible() && ActivityManager.isHighEndGfx()) {
+ mCurrentAnimator = ObjectAnimator.ofFloat(this, ROTATION, nextRotation)
+ .setDuration(ANIMATION_DURATION);
+ mCurrentAnimator.start();
+ } else {
+ setRotation(nextRotation);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 1601b83..093d18c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -57,15 +57,28 @@ public class BarTransitions {
private int mMode;
- public BarTransitions(View view, int gradientResourceId) {
+ public BarTransitions(View view, int gradientResourceId, int opaqueColorResourceId,
+ int semiTransparentColorResourceId, int transparentColorResourceId,
+ int warningColorResourceId) {
mTag = "BarTransitions." + view.getClass().getSimpleName();
mView = view;
- mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
+ mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId,
+ opaqueColorResourceId, semiTransparentColorResourceId,
+ transparentColorResourceId, warningColorResourceId);
if (HIGH_END) {
mView.setBackground(mBarBackground);
}
}
+ protected void setGradientResourceId(int gradientResourceId) {
+ mBarBackground.setGradientResourceId(mView.getContext().getResources(),
+ gradientResourceId);
+ }
+
+ public void updateResources(Resources res) {
+ mBarBackground.updateResources(res);
+ }
+
public int getMode() {
return mMode;
}
@@ -119,11 +132,11 @@ public class BarTransitions {
}
private static class BarBackgroundDrawable extends Drawable {
- private final int mOpaque;
- private final int mSemiTransparent;
- private final int mTransparent;
- private final int mWarning;
- private final Drawable mGradient;
+ private int mOpaque;
+ private int mSemiTransparent;
+ private int mTransparent;
+ private int mWarning;
+ private Drawable mGradient;
private final TimeInterpolator mInterpolator;
private int mMode = -1;
@@ -137,7 +150,15 @@ public class BarTransitions {
private int mGradientAlphaStart;
private int mColorStart;
- public BarBackgroundDrawable(Context context, int gradientResourceId) {
+ private int mGradientResourceId;
+ private final int mOpaqueColorResourceId;
+ private final int mSemiTransparentColorResourceId;
+ private final int mTransparentColorResourceId;
+ private final int mWarningColorResourceId;
+
+ public BarBackgroundDrawable(Context context, int gradientResourceId,
+ int opaqueColorResourceId, int semiTransparentColorResourceId,
+ int transparentColorResourceId, int warningColorResourceId) {
final Resources res = context.getResources();
if (DEBUG_COLORS) {
mOpaque = 0xff0000ff;
@@ -145,13 +166,36 @@ public class BarTransitions {
mTransparent = 0x2f0000ff;
mWarning = 0xffff0000;
} else {
- mOpaque = context.getColor(R.color.system_bar_background_opaque);
- mSemiTransparent = context.getColor(R.color.system_bar_background_semi_transparent);
- mTransparent = context.getColor(R.color.system_bar_background_transparent);
- mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
+ mOpaque = res.getColor(R.color.system_bar_background_opaque);
+ mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent);
+ mTransparent = res.getColor(transparentColorResourceId);
+ mWarning = res.getColor(warningColorResourceId);
}
mGradient = context.getDrawable(gradientResourceId);
mInterpolator = new LinearInterpolator();
+ mGradientResourceId = gradientResourceId;
+ mOpaqueColorResourceId = opaqueColorResourceId;
+ mSemiTransparentColorResourceId = semiTransparentColorResourceId;
+ mTransparentColorResourceId = transparentColorResourceId;
+ mWarningColorResourceId = warningColorResourceId;
+ }
+
+ public void setGradientResourceId(Resources res, int gradientResourceId) {
+ mGradient = res.getDrawable(gradientResourceId);
+ mGradientResourceId = gradientResourceId;
+ }
+
+ public void updateResources(Resources res) {
+ mOpaque = res.getColor(mOpaqueColorResourceId);
+ mSemiTransparent = res.getColor(mSemiTransparentColorResourceId);
+ mTransparent = res.getColor(mTransparentColorResourceId);
+ mWarning = res.getColor(mWarningColorResourceId);
+ // Retrieve the current bounds for mGradient so they can be set to
+ // the new drawable being loaded, otherwise the bounds will be (0, 0, 0, 0)
+ // and the gradient will not be drawn.
+ Rect bounds = mGradient.getBounds();
+ mGradient = res.getDrawable(mGradientResourceId);
+ mGradient.setBounds(bounds);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BlurLayer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BlurLayer.java
new file mode 100644
index 0000000..a966409
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BlurLayer.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.graphics.PixelFormat;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+import java.io.PrintWriter;
+
+public class BlurLayer {
+ private static final String TAG = "BlurLayer";
+ private static final boolean DEBUG = true;
+ private SurfaceControl mBlurSurface;
+ private int mLayer = -1;
+ private float mAlpha = 0;
+ private float mBlur = 0;
+ private int mX, mY;
+ private int mW, mH;
+ private boolean mIsShow;
+
+ public BlurLayer(SurfaceSession mFxSession, int w, int h, String tag) {
+ this(mFxSession, 0, 0, w, h, tag);
+ }
+
+ public BlurLayer(SurfaceSession mFxSession, int x, int y, int w, int h, String tag) {
+ mX = x;
+ mY = y;
+ mW = w;
+ mH = h;
+ mIsShow = false;
+
+ SurfaceControl.openTransaction();
+ try {
+ mBlurSurface = new SurfaceControl(mFxSession, TAG+"_"+tag, 16, 16, PixelFormat.OPAQUE,
+ SurfaceControl.FX_SURFACE_BLUR | SurfaceControl.HIDDEN);
+ mBlurSurface.setLayerStack(0);
+ mBlurSurface.setPosition(mX, mY);
+ mBlurSurface.setSize(mW, mH);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception creating BlurLayer surface", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
+ public void setSize(int w, int h) {
+ if (mBlurSurface != null && (mW != w || mH != h) ) {
+ SurfaceControl.openTransaction();
+ try {
+ mBlurSurface.setSize(w, h);
+ mW = w;
+ mH = h;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting setSize immediately", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception setSize", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void setPosition(int x, int y) {
+ if (mBlurSurface != null && (mX != x || mY != y) ) {
+ SurfaceControl.openTransaction();
+ try {
+ mBlurSurface.setPosition(x, y);
+ mX = x;
+ mY = y;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting setPosition immediately", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception setPosition", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void setLayer(int layer) {
+ if (mBlurSurface != null && mLayer != layer) {
+ SurfaceControl.openTransaction();
+ try {
+ mBlurSurface.setLayer(layer);
+ mLayer = layer;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting setLayer immediately", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception setLayer", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void setAlpha(float alpha){
+ if(mBlurSurface != null && mAlpha != alpha){
+ SurfaceControl.openTransaction();
+ try {
+ mBlurSurface.setAlpha(alpha);
+ mAlpha = alpha;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting alpha immediately", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception setAlpha", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void setBlur(float blur){
+ if(mBlurSurface != null && mBlur != blur ){
+ SurfaceControl.openTransaction();
+ try {
+ mBlurSurface.setBlur(blur);
+ mBlur = blur;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting blur immediately", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception setBlur", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void show() {
+ if(mBlurSurface != null && !mIsShow ){
+ try {
+ mBlurSurface.show();
+ mIsShow = true;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure show()", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception show()", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void hide(){
+ if(mBlurSurface != null && mIsShow ){
+ try {
+ mBlurSurface.hide();
+ mIsShow = false;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure hide()", e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception hide()", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ public void destroySurface() {
+ if (DEBUG) Slog.v(TAG, "destroySurface.");
+ if (mBlurSurface != null) {
+ mBlurSurface.destroy();
+ mBlurSurface = null;
+ }
+ }
+
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java
new file mode 100644
index 0000000..84eeb31
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java
@@ -0,0 +1,149 @@
+package com.android.systemui.statusbar.phone;
+
+import com.android.systemui.FontSizeUtils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.graphics.Color;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.view.View;
+import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.statusbar.policy.Clock;
+
+import cyanogenmod.providers.CMSettings;
+
+/**
+ * To control your...clock
+ */
+public class ClockController {
+
+ public static final int STYLE_HIDE_CLOCK = 0;
+ public static final int STYLE_CLOCK_RIGHT = 1;
+ public static final int STYLE_CLOCK_CENTER = 2;
+ public static final int STYLE_CLOCK_LEFT = 3;
+
+ private final IconMerger mNotificationIcons;
+ private final Context mContext;
+ private final SettingsObserver mSettingsObserver;
+ private Clock mRightClock, mCenterClock, mLeftClock, mActiveClock;
+
+ private int mClockLocation;
+ private int mAmPmStyle;
+ private int mIconTint = Color.WHITE;
+
+ class SettingsObserver extends UserContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_AM_PM), false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_CLOCK), false, this, UserHandle.USER_ALL);
+ updateSettings();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ public void update() {
+ updateSettings();
+ }
+ }
+
+ public ClockController(View statusBar, IconMerger notificationIcons, Handler handler) {
+ mRightClock = (Clock) statusBar.findViewById(R.id.clock);
+ mCenterClock = (Clock) statusBar.findViewById(R.id.center_clock);
+ mLeftClock = (Clock) statusBar.findViewById(R.id.left_clock);
+ mNotificationIcons = notificationIcons;
+ mContext = statusBar.getContext();
+
+ mActiveClock = mRightClock;
+ mSettingsObserver = new SettingsObserver(handler);
+ mSettingsObserver.observe();
+ }
+
+ private Clock getClockForCurrentLocation() {
+ Clock clockForAlignment;
+ switch (mClockLocation) {
+ case STYLE_CLOCK_CENTER:
+ clockForAlignment = mCenterClock;
+ break;
+ case STYLE_CLOCK_LEFT:
+ clockForAlignment = mLeftClock;
+ break;
+ case STYLE_CLOCK_RIGHT:
+ case STYLE_HIDE_CLOCK:
+ default:
+ clockForAlignment = mRightClock;
+ break;
+ }
+ return clockForAlignment;
+ }
+
+ private void updateActiveClock() {
+ mActiveClock.setVisibility(View.GONE);
+ if (mClockLocation == STYLE_HIDE_CLOCK) {
+ return;
+ }
+
+ mActiveClock = getClockForCurrentLocation();
+ mActiveClock.setVisibility(View.VISIBLE);
+ mActiveClock.setAmPmStyle(mAmPmStyle);
+
+ setClockAndDateStatus();
+ setTextColor(mIconTint);
+ updateFontSize();
+ }
+
+ private void updateSettings() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mAmPmStyle = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.STATUS_BAR_AM_PM, Clock.AM_PM_STYLE_GONE,
+ UserHandle.USER_CURRENT);
+ mClockLocation = CMSettings.System.getIntForUser(
+ resolver, CMSettings.System.STATUS_BAR_CLOCK, STYLE_CLOCK_RIGHT,
+ UserHandle.USER_CURRENT);
+ updateActiveClock();
+ }
+
+ private void setClockAndDateStatus() {
+ if (mNotificationIcons != null) {
+ mNotificationIcons.setClockAndDateStatus(mClockLocation);
+ }
+ }
+
+ public void setVisibility(boolean visible) {
+ if (mActiveClock != null) {
+ mActiveClock.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ public void setTextColor(int iconTint) {
+ mIconTint = iconTint;
+ if (mActiveClock != null) {
+ mActiveClock.setTextColor(iconTint);
+ }
+ }
+
+ public void updateFontSize() {
+ if (mActiveClock != null) {
+ FontSizeUtils.updateFontSize(mActiveClock, R.dimen.status_bar_clock_size);
+ }
+ }
+
+ public void cleanup() {
+ mSettingsObserver.unobserve();
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 1d890d0..9897098 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -22,6 +22,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.MathUtils;
+import com.android.systemui.doze.DozeLog;
import com.android.systemui.R;
import java.io.PrintWriter;
@@ -46,17 +47,20 @@ public class DozeParameters {
public void dump(PrintWriter pw) {
pw.println(" DozeParameters:");
pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported());
- pw.print(" getPulseDuration(pickup=false): "); pw.println(getPulseDuration(false));
- pw.print(" getPulseDuration(pickup=true): "); pw.println(getPulseDuration(true));
- pw.print(" getPulseInDuration(pickup=false): "); pw.println(getPulseInDuration(false));
- pw.print(" getPulseInDuration(pickup=true): "); pw.println(getPulseInDuration(true));
+ pw.print(" getPulseDuration(notification): "); pw.println(getPulseDuration(DozeLog.PULSE_REASON_NOTIFICATION));
+ pw.print(" getPulseDuration(pickup): "); pw.println(getPulseDuration(DozeLog.PULSE_REASON_SENSOR_PICKUP));
+ pw.print(" getPulseDuration(intent): "); pw.println(getPulseDuration(DozeLog.PULSE_REASON_INTENT));
+ pw.print(" getPulseInDuration(notification): "); pw.println(getPulseInDuration(DozeLog.PULSE_REASON_NOTIFICATION));
+ pw.print(" getPulseInDuration(pickup): "); pw.println(getPulseInDuration(DozeLog.PULSE_REASON_SENSOR_PICKUP));
+ pw.print(" getPulseInDuration(intent): "); pw.println(getPulseInDuration(DozeLog.PULSE_REASON_INTENT));
pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
pw.print(" getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion());
pw.print(" getPulseOnPickup(): "); pw.println(getPulseOnPickup());
pw.print(" getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
- pw.print(" getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
+ pw.print(" getProxCheckBeforePulse(pickup): "); pw.println(getProxCheckBeforePulse(DozeLog.PULSE_REASON_SENSOR_PICKUP));
+ pw.print(" getProxCheckBeforePulse(intent): "); pw.println(getProxCheckBeforePulse(DozeLog.PULSE_REASON_INTENT));
pw.print(" getPulseOnNotifications(): "); pw.println(getPulseOnNotifications());
pw.print(" getPulseSchedule(): "); pw.println(getPulseSchedule());
pw.print(" getPulseScheduleResets(): "); pw.println(getPulseScheduleResets());
@@ -68,14 +72,19 @@ public class DozeParameters {
return getBoolean("doze.display.supported", R.bool.doze_display_state_supported);
}
- public int getPulseDuration(boolean pickup) {
- return getPulseInDuration(pickup) + getPulseVisibleDuration() + getPulseOutDuration();
+ public int getPulseDuration(int reason) {
+ return getPulseInDuration(reason) + getPulseVisibleDuration() + getPulseOutDuration();
}
- public int getPulseInDuration(boolean pickup) {
- return pickup
- ? getInt("doze.pulse.duration.in.pickup", R.integer.doze_pulse_duration_in_pickup)
- : getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
+ public int getPulseInDuration(int reason) {
+ switch(reason) {
+ case DozeLog.PULSE_REASON_SENSOR_PICKUP:
+ return getInt("doze.pulse.duration.in.pickup", R.integer.doze_pulse_duration_in_pickup);
+ case DozeLog.PULSE_REASON_INTENT:
+ return getInt("doze.pulse.duration.in.intent", R.integer.doze_pulse_duration_in_intent);
+ default:
+ return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
+ }
}
public int getPulseVisibleDuration() {
@@ -102,8 +111,15 @@ public class DozeParameters {
return SystemProperties.getBoolean("doze.vibrate.pickup", false);
}
- public boolean getProxCheckBeforePulse() {
- return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
+ public boolean getProxCheckBeforePulse(int reason) {
+ switch(reason) {
+ case DozeLog.PULSE_REASON_SENSOR_PICKUP:
+ return getBoolean("doze.pulse.proxcheck.pickup", R.bool.doze_proximity_check_before_pulse);
+ case DozeLog.PULSE_REASON_INTENT:
+ return getBoolean("doze.pulse.proxcheck.intent", R.bool.doze_proximity_check_before_pulse_intent);
+ default:
+ return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
+ }
}
public boolean getPickupPerformsProxCheck() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 3ff69c9..b3e0104 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -115,7 +115,7 @@ public class DozeScrimController {
if (isPulsing()) {
final boolean pickup = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
startScrimAnimation(true /* inFront */, 0f,
- mDozeParameters.getPulseInDuration(pickup),
+ mDozeParameters.getPulseInDuration(mPulseReason),
pickup ? mPulseInInterpolatorPickup : mPulseInInterpolator,
mPulseInFinished);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index 50ead3d..5750372 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -22,12 +22,14 @@ import android.view.View;
import android.widget.LinearLayout;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.Clock;
public class IconMerger extends LinearLayout {
private static final String TAG = "IconMerger";
private static final boolean DEBUG = false;
private int mIconSize;
+ private int mClockLocation;
private View mMoreView;
public IconMerger(Context context, AttributeSet attrs) {
@@ -50,6 +52,10 @@ public class IconMerger extends LinearLayout {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// we need to constrain this to an integral multiple of our children
int width = getMeasuredWidth();
+ if (mClockLocation == ClockController.STYLE_CLOCK_CENTER) {
+ int totalWidth = getResources().getDisplayMetrics().widthPixels;
+ width = totalWidth / 2 - mIconSize * 2;
+ }
setMeasuredDimension(width - (width % mIconSize), getMeasuredHeight());
}
@@ -69,7 +75,14 @@ public class IconMerger extends LinearLayout {
}
final boolean overflowShown = (mMoreView.getVisibility() == View.VISIBLE);
// let's assume we have one more slot if the more icon is already showing
- if (overflowShown) visibleChildren --;
+ if (overflowShown) {
+ int totalWidth = getResources().getDisplayMetrics().widthPixels;
+ if ((mClockLocation != ClockController.STYLE_CLOCK_CENTER &&
+ mClockLocation != ClockController.STYLE_CLOCK_LEFT) ||
+ (visibleChildren > (totalWidth / mIconSize / 2 + 1))) {
+ visibleChildren--;
+ }
+ }
final boolean moreRequired = visibleChildren * mIconSize > width;
if (moreRequired != overflowShown) {
post(new Runnable() {
@@ -80,4 +93,9 @@ public class IconMerger extends LinearLayout {
});
}
}
+
+ public void setClockAndDateStatus(int mode) {
+ mClockLocation = mode;
+
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 14176a6..d95a46a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,6 +29,14 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.hardware.fingerprint.FingerprintManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
@@ -49,7 +57,6 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
-
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -57,6 +64,8 @@ import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.cm.LockscreenShortcutsHelper;
+import com.android.systemui.cm.LockscreenShortcutsHelper.Shortcuts;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -72,7 +81,7 @@ import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityActi
* text.
*/
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
- UnlockMethodCache.OnUnlockMethodChangedListener,
+ UnlockMethodCache.OnUnlockMethodChangedListener, LockscreenShortcutsHelper.OnChangeListener,
AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
@@ -110,6 +119,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private KeyguardIndicationController mIndicationController;
private AccessibilityController mAccessibilityController;
private PhoneStatusBar mPhoneStatusBar;
+ private LockscreenShortcutsHelper mShortcutHelper;
+ private final ColorMatrixColorFilter mGrayScaleFilter;
private final Interpolator mLinearOutSlowInInterpolator;
private boolean mUserSetupComplete;
@@ -128,7 +139,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
};
- private boolean mLeftIsVoiceAssist;
private AssistManager mAssistManager;
public KeyguardBottomAreaView(Context context) {
@@ -148,6 +158,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
super(context, attrs, defStyleAttr, defStyleRes);
mLinearOutSlowInInterpolator =
AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
+ ColorMatrix cm = new ColorMatrix();
+ cm.setSaturation(0);
+ mGrayScaleFilter = new ColorMatrixColorFilter(cm);
}
private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
@@ -158,12 +171,20 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (host == mLockIcon) {
label = getResources().getString(R.string.unlock_label);
} else if (host == mCameraImageView) {
- label = getResources().getString(R.string.camera_label);
+ if (isTargetCustom(Shortcuts.RIGHT_SHORTCUT)) {
+ label = mShortcutHelper.getFriendlyNameForUri(Shortcuts.RIGHT_SHORTCUT);
+ } else {
+ label = getResources().getString(R.string.camera_label);
+ }
} else if (host == mLeftAffordanceView) {
- if (mLeftIsVoiceAssist) {
- label = getResources().getString(R.string.voice_assist_label);
+ if (isTargetCustom(Shortcuts.LEFT_SHORTCUT)) {
+ label = mShortcutHelper.getFriendlyNameForUri(Shortcuts.LEFT_SHORTCUT);
} else {
- label = getResources().getString(R.string.phone_label);
+ if (isLeftVoiceAssist()) {
+ label = getResources().getString(R.string.voice_assist_label);
+ } else {
+ label = getResources().getString(R.string.phone_label);
+ }
}
}
info.addAction(new AccessibilityAction(ACTION_CLICK, label));
@@ -197,20 +218,47 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
+ mShortcutHelper = new LockscreenShortcutsHelper(mContext, this);
watchForCameraPolicyChanges();
updateCameraVisibility();
+ updateLeftButtonVisibility();
mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
mUnlockMethodCache.addListener(this);
mLockIcon.update();
setClipChildren(false);
setClipToPadding(false);
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
- inflateCameraPreview();
mLockIcon.setOnClickListener(this);
mLockIcon.setOnLongClickListener(this);
mCameraImageView.setOnClickListener(this);
mLeftAffordanceView.setOnClickListener(this);
initAccessibility();
+ updateCustomShortcuts();
+ }
+
+ private void updateCustomShortcuts() {
+ updateLeftAffordanceIcon();
+ updateRightAffordanceIcon();
+ inflateCameraPreview();
+ }
+
+ private void updateRightAffordanceIcon() {
+ Drawable drawable;
+ String contentDescription;
+ boolean shouldGrayScale = false;
+ if (isTargetCustom(Shortcuts.RIGHT_SHORTCUT)) {
+ drawable = mShortcutHelper.getDrawableForTarget(Shortcuts.RIGHT_SHORTCUT);
+ shouldGrayScale = true;
+ contentDescription = mShortcutHelper.getFriendlyNameForUri(Shortcuts.RIGHT_SHORTCUT);
+ } else {
+ drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
+ contentDescription = mContext.getString(R.string.accessibility_camera_button);
+ }
+ mCameraImageView.setImageDrawable(drawable);
+ mCameraImageView.setContentDescription(contentDescription);
+ mCameraImageView.setDefaultFilter(shouldGrayScale ? mGrayScaleFilter : null);
+ updateCameraVisibility();
+ updateLeftButtonVisibility();
}
private void initAccessibility() {
@@ -253,11 +301,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
mPhoneStatusBar = phoneStatusBar;
updateCameraVisibility(); // in case onFinishInflate() was called too early
+ updateLeftButtonVisibility();
}
public void setUserSetupComplete(boolean userSetupComplete) {
mUserSetupComplete = userSetupComplete;
updateCameraVisibility();
+ updateLeftButtonVisibility();
updateLeftAffordanceIcon();
}
@@ -278,38 +328,66 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
KeyguardUpdateMonitor.getCurrentUser());
}
+ private void updateLeftButtonVisibility() {
+ if (mLeftAffordanceView == null) {
+ return;
+ }
+ boolean visible = mUserSetupComplete;
+ if (visible) {
+ if (isTargetCustom(Shortcuts.LEFT_SHORTCUT)) {
+ visible = !mShortcutHelper.isTargetEmpty(Shortcuts.LEFT_SHORTCUT);
+ } else {
+ // Display left shortcut
+ }
+ }
+ mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
private void updateCameraVisibility() {
if (mCameraImageView == null) {
// Things are not set up yet; reply hazy, ask again later
return;
}
- ResolveInfo resolved = resolveCameraIntent();
- boolean visible = !isCameraDisabledByDpm() && resolved != null
- && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
- && mUserSetupComplete;
+ boolean visible = mUserSetupComplete;
+ if (visible) {
+ if (isTargetCustom(Shortcuts.RIGHT_SHORTCUT)) {
+ visible = !mShortcutHelper.isTargetEmpty(Shortcuts.RIGHT_SHORTCUT);
+ } else {
+ ResolveInfo resolved = resolveCameraIntent();
+ visible = !isCameraDisabledByDpm() && resolved != null
+ && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance);
+ }
+ }
mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
private void updateLeftAffordanceIcon() {
- mLeftIsVoiceAssist = canLaunchVoiceAssist();
- int drawableId;
- int contentDescription;
+ Drawable drawable;
+ String contentDescription;
+ boolean shouldGrayScale = false;
boolean visible = mUserSetupComplete;
- if (mLeftIsVoiceAssist) {
- drawableId = R.drawable.ic_mic_26dp;
- contentDescription = R.string.accessibility_voice_assist_button;
+ if (mShortcutHelper.isTargetCustom(Shortcuts.LEFT_SHORTCUT)) {
+ drawable = mShortcutHelper.getDrawableForTarget(Shortcuts.LEFT_SHORTCUT);
+ shouldGrayScale = true;
+ contentDescription = mShortcutHelper.getFriendlyNameForUri(Shortcuts.LEFT_SHORTCUT);
+ visible |= !mShortcutHelper.isTargetEmpty(Shortcuts.LEFT_SHORTCUT);
+ } else if (canLaunchVoiceAssist()) {
+ drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
+ contentDescription = mContext.getString(R.string.accessibility_voice_assist_button);
} else {
visible &= isPhoneVisible();
- drawableId = R.drawable.ic_phone_24dp;
- contentDescription = R.string.accessibility_phone_button;
+ drawable = mContext.getDrawable(R.drawable.ic_phone_24dp);
+ contentDescription = mContext.getString(R.string.accessibility_phone_button);
}
mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE);
- mLeftAffordanceView.setImageDrawable(mContext.getDrawable(drawableId));
- mLeftAffordanceView.setContentDescription(mContext.getString(contentDescription));
+ mLeftAffordanceView.setImageDrawable(drawable);
+ mLeftAffordanceView.setContentDescription(contentDescription);
+ mLeftAffordanceView.setDefaultFilter(shouldGrayScale ? mGrayScaleFilter : null);
+ updateLeftButtonVisibility();
}
public boolean isLeftVoiceAssist() {
- return mLeftIsVoiceAssist;
+ return !isTargetCustom(Shortcuts.LEFT_SHORTCUT) && canLaunchVoiceAssist();
}
private boolean isPhoneVisible() {
@@ -425,8 +503,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
public void launchCamera(String source) {
- final Intent intent = getCameraIntent();
- intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
+ final Intent intent;
+ if (!mShortcutHelper.isTargetCustom(LockscreenShortcutsHelper.Shortcuts.RIGHT_SHORTCUT)) {
+ intent = getCameraIntent();
+ } else {
+ intent = mShortcutHelper.getIntent(LockscreenShortcutsHelper.Shortcuts.RIGHT_SHORTCUT);
+ intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
+ }
boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
@@ -475,7 +558,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
public void launchLeftAffordance() {
- if (mLeftIsVoiceAssist) {
+ if (mShortcutHelper.isTargetCustom(Shortcuts.LEFT_SHORTCUT)) {
+ Intent intent = mShortcutHelper.getIntent(Shortcuts.LEFT_SHORTCUT);
+ mActivityStarter.startActivity(intent, false /* dismissShade */);
+ } else if (isLeftVoiceAssist()) {
launchVoiceAssist();
} else {
launchPhone();
@@ -499,6 +585,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
private boolean canLaunchVoiceAssist() {
+ if (mAssistManager == null) {
+ return false;
+ }
return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
}
@@ -523,6 +612,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (changedView == this && visibility == VISIBLE) {
mLockIcon.update();
updateCameraVisibility();
+ updateLeftButtonVisibility();
}
}
@@ -559,13 +649,18 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public void onUnlockMethodStateChanged() {
mLockIcon.update();
updateCameraVisibility();
+ updateLeftButtonVisibility();
}
private void inflateCameraPreview() {
- mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
- if (mCameraPreview != null) {
- mPreviewContainer.addView(mCameraPreview);
- mCameraPreview.setVisibility(View.INVISIBLE);
+ if (isTargetCustom(Shortcuts.RIGHT_SHORTCUT)) {
+ mPreviewContainer.removeView(mCameraPreview);
+ } else {
+ mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
+ if (mCameraPreview != null) {
+ mPreviewContainer.addView(mCameraPreview);
+ mCameraPreview.setVisibility(View.INVISIBLE);
+ }
}
}
@@ -574,7 +669,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (previewBefore != null) {
mPreviewContainer.removeView(previewBefore);
}
- if (mLeftIsVoiceAssist) {
+ if (isTargetCustom(Shortcuts.LEFT_SHORTCUT)) {
+ // Custom shortcuts don't support previews
+ return;
+ }
+ if (isLeftVoiceAssist()) {
mLeftPreview = mPreviewInflater.inflatePreviewFromService(
mAssistManager.getVoiceInteractorComponentName());
} else {
@@ -622,6 +721,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public void run() {
updateCameraVisibility();
+ updateLeftButtonVisibility();
}
});
}
@@ -632,6 +732,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public void onUserSwitchComplete(int userId) {
updateCameraVisibility();
+ updateLeftButtonVisibility();
}
@Override
@@ -684,4 +785,61 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
updateLeftAffordanceIcon();
updateLeftPreview();
}
+
+ private String getIndexHint(LockscreenShortcutsHelper.Shortcuts shortcut) {
+ if (mShortcutHelper.isTargetCustom(shortcut)) {
+ boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ String label = mShortcutHelper.getFriendlyNameForUri(shortcut);
+ int resId = 0;
+ switch (shortcut) {
+ case LEFT_SHORTCUT:
+ resId = isRtl ? R.string.right_shortcut_hint : R.string.left_shortcut_hint;
+ break;
+ case RIGHT_SHORTCUT:
+ resId = isRtl ? R.string.left_shortcut_hint : R.string.right_shortcut_hint;
+ break;
+ }
+ return mContext.getString(resId, label);
+ } else {
+ return null;
+ }
+ }
+
+ public String getLeftHint() {
+ String label = getIndexHint(LockscreenShortcutsHelper.Shortcuts.LEFT_SHORTCUT);
+ if (label == null) {
+ if (isLeftVoiceAssist()) {
+ label = mContext.getString(R.string.voice_hint);
+ } else {
+ label = mContext.getString(R.string.phone_hint);
+ }
+ }
+ return label;
+ }
+
+ public String getRightHint() {
+ String label = getIndexHint(LockscreenShortcutsHelper.Shortcuts.RIGHT_SHORTCUT);
+ if (label == null) {
+ label = mContext.getString(R.string.camera_hint);
+ }
+ return label;
+ }
+
+ public boolean isTargetCustom(LockscreenShortcutsHelper.Shortcuts shortcut) {
+ return mShortcutHelper.isTargetCustom(shortcut);
+ }
+
+ @Override
+ public void onChange() {
+ updateCustomShortcuts();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mAccessibilityController.removeStateChangedCallback(this);
+ mContext.unregisterReceiver(mDevicePolicyReceiver);
+ mShortcutHelper.cleanup();
+ mUnlockMethodCache.removeListener(this);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 893b352..65e2096 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -32,6 +32,8 @@ import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
+import org.cyanogenmod.internal.util.CmLockPatternUtils;
+
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -40,9 +42,14 @@ import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
*/
public class KeyguardBouncer {
+ public static final int UNLOCK_SEQUENCE_DEFAULT = 0;
+ public static final int UNLOCK_SEQUENCE_BOUNCER_FIRST = 1;
+ public static final int UNLOCK_SEQUENCE_FORCE_BOUNCER = 2;
+
private Context mContext;
private ViewMediatorCallback mCallback;
private LockPatternUtils mLockPatternUtils;
+ private CmLockPatternUtils mCmLockPatternUtils;
private ViewGroup mContainer;
private StatusBarWindowManager mWindowManager;
private KeyguardHostView mKeyguardView;
@@ -65,6 +72,7 @@ public class KeyguardBouncer {
mLockPatternUtils = lockPatternUtils;
mContainer = container;
mWindowManager = windowManager;
+ mCmLockPatternUtils = new CmLockPatternUtils(mContext);
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
}
@@ -195,7 +203,7 @@ public class KeyguardBouncer {
mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
}
- private void removeView() {
+ void removeView() {
if (mRoot != null && mRoot.getParent() == mContainer) {
mContainer.removeView(mRoot);
mRoot = null;
@@ -207,28 +215,42 @@ public class KeyguardBouncer {
}
/**
- * @return True if and only if the security method should be shown before showing the
- * notifications on Keyguard, like SIM PIN/PUK.
+ * @return Whether the bouncer should be shown first, this could be because of SIM PIN/PUK
+ * or it just could be chosen to be shown first.
*/
- public boolean needsFullscreenBouncer() {
+ public int needsFullscreenBouncer() {
ensureView();
if (mKeyguardView != null) {
SecurityMode mode = mKeyguardView.getSecurityMode();
- return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
+ if (mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk)
+ return UNLOCK_SEQUENCE_FORCE_BOUNCER;
+ // "Bouncer first" mode currently only available to some security methods.
+ else if ((mode == SecurityMode.Pattern || mode == SecurityMode.Password
+ || mode == SecurityMode.PIN) && (mLockPatternUtils != null &&
+ mCmLockPatternUtils.shouldPassToSecurityView(
+ KeyguardUpdateMonitor.getCurrentUser())))
+ return UNLOCK_SEQUENCE_BOUNCER_FIRST;
}
- return false;
+ return UNLOCK_SEQUENCE_DEFAULT;
}
/**
* Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
* makes this method much faster.
*/
- public boolean isFullscreenBouncer() {
+ public int isFullscreenBouncer() {
if (mKeyguardView != null) {
SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
- return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
+ if (mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk)
+ return UNLOCK_SEQUENCE_FORCE_BOUNCER;
+ // "Bouncer first" mode currently only available to some security methods.
+ else if ((mode == SecurityMode.Pattern || mode == SecurityMode.Password
+ || mode == SecurityMode.PIN) && (mLockPatternUtils != null &&
+ mCmLockPatternUtils.shouldPassToSecurityView(
+ KeyguardUpdateMonitor.getCurrentUser())))
+ return UNLOCK_SEQUENCE_BOUNCER_FIRST;
}
- return false;
+ return UNLOCK_SEQUENCE_DEFAULT;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index b93fc76..ec307de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- *
+ * Copyright (C) 2016 The CyanogenMod 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
@@ -29,37 +29,37 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.BatteryMeterView;
+import com.android.systemui.DockBatteryMeterView;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DockBatteryController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import java.text.NumberFormat;
-
/**
* The header group on Keyguard.
*/
-public class KeyguardStatusBarView extends RelativeLayout
- implements BatteryController.BatteryStateChangeCallback {
+public class KeyguardStatusBarView extends RelativeLayout {
- private boolean mBatteryCharging;
private boolean mKeyguardUserSwitcherShowing;
- private boolean mBatteryListening;
private TextView mCarrierLabel;
private View mSystemIconsSuperContainer;
private MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
- private TextView mBatteryLevel;
+ private BatteryLevelTextView mBatteryLevel;
+ private BatteryLevelTextView mDockBatteryLevel;
- private BatteryController mBatteryController;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private int mSystemIconsSwitcherHiddenExpandedMargin;
private Interpolator mFastOutSlowInInterpolator;
+ private UserInfoController mUserInfoController;
+
public KeyguardStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -70,12 +70,14 @@ public class KeyguardStatusBarView extends RelativeLayout
mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container);
mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
- mBatteryLevel = (TextView) findViewById(R.id.battery_level);
+ mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text);
+ mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text);
mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text);
loadDimens();
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_slow_in);
updateUserSwitcher();
+ updateVisibilities();
}
@Override
@@ -86,8 +88,14 @@ public class KeyguardStatusBarView extends RelativeLayout
mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material));
- mBatteryLevel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- getResources().getDimensionPixelSize(R.dimen.battery_level_text_size));
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mUserInfoController != null) {
+ mUserInfoController.removeListener(mUserInfoChangedListener);
+ }
}
private void loadDimens() {
@@ -104,7 +112,10 @@ public class KeyguardStatusBarView extends RelativeLayout
} else if (mMultiUserSwitch.getParent() == this && mKeyguardUserSwitcherShowing) {
removeView(mMultiUserSwitch);
}
- mBatteryLevel.setVisibility(mBatteryCharging ? View.VISIBLE : View.GONE);
+ mBatteryLevel.setVisibility(View.VISIBLE);
+ if (mDockBatteryLevel != null) {
+ mDockBatteryLevel.setVisibility(View.VISIBLE);
+ }
}
private void updateSystemIconsLayoutParams() {
@@ -117,18 +128,6 @@ public class KeyguardStatusBarView extends RelativeLayout
}
}
- public void setListening(boolean listening) {
- if (listening == mBatteryListening) {
- return;
- }
- mBatteryListening = listening;
- if (mBatteryListening) {
- mBatteryController.addStateChangedCallback(this);
- } else {
- mBatteryController.removeStateChangedCallback(this);
- }
- }
-
private void updateUserSwitcher() {
boolean keyguardSwitcherAvailable = mKeyguardUserSwitcher != null;
mMultiUserSwitch.setClickable(keyguardSwitcherAvailable);
@@ -137,37 +136,43 @@ public class KeyguardStatusBarView extends RelativeLayout
}
public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
- ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
+ BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery));
+ v.setBatteryStateRegistar(batteryController);
+ v.setBatteryController(batteryController);
+ mBatteryLevel.setBatteryStateRegistar(batteryController);
}
- public void setUserSwitcherController(UserSwitcherController controller) {
- mMultiUserSwitch.setUserSwitcherController(controller);
+ public void setDockBatteryController(DockBatteryController dockBatteryController) {
+ DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery));
+ if (dockBatteryController != null) {
+ v.setBatteryStateRegistar(dockBatteryController);
+ mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController);
+ } else {
+ if (v != null ) {
+ removeView(v);
+ }
+ if (mDockBatteryLevel != null) {
+ removeView(mDockBatteryLevel);
+ mDockBatteryLevel = null;
+ }
+ }
}
- public void setUserInfoController(UserInfoController userInfoController) {
- userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture) {
- mMultiUserAvatar.setImageDrawable(picture);
- }
- });
+ public void setUserSwitcherController(UserSwitcherController controller) {
+ mMultiUserSwitch.setUserSwitcherController(controller);
}
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
- mBatteryLevel.setText(percentage);
- boolean changed = mBatteryCharging != charging;
- mBatteryCharging = charging;
- if (changed) {
- updateVisibilities();
+ private UserInfoController.OnUserInfoChangedListener mUserInfoChangedListener =
+ new UserInfoController.OnUserInfoChangedListener() {
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ mMultiUserAvatar.setImageDrawable(picture);
}
- }
+ };
- @Override
- public void onPowerSaveChanged() {
- // could not care less
+ public void setUserInfoController(UserInfoController userInfoController) {
+ mUserInfoController = userInfoController;
+ userInfoController.addListener(mUserInfoChangedListener);
}
public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index e70d146..e89cd3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -30,6 +30,7 @@ import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
@@ -37,16 +38,20 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
*/
public class MultiUserSwitch extends FrameLayout implements View.OnClickListener {
+ public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
+
private QSPanel mQsPanel;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private boolean mKeyguardMode;
private UserSwitcherController.BaseUserAdapter mUserListener;
final UserManager mUserManager;
+ private ActivityStarter mActivityStarter;
private final int[] mTmpInt2 = new int[2];
private UserSwitcherController mUserSwitcherController;
+ private UserInfoController mUserInfoController;
public MultiUserSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -101,6 +106,10 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
}
}
+ public void setActivityStarter(ActivityStarter activityStarter) {
+ mActivityStarter = activityStarter;
+ }
+
@Override
public void onClick(View v) {
if (UserSwitcherController.isUserSwitcherAvailable(mUserManager)) {
@@ -120,10 +129,20 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
mTmpInt2);
}
} else {
- Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
- getContext(), v, ContactsContract.Profile.CONTENT_URI,
- ContactsContract.QuickContact.MODE_LARGE, null);
- getContext().startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ Intent intent;
+ if (mUserInfoController == null || mUserInfoController.isProfileSetup()) {
+ intent = ContactsContract.QuickContact.composeQuickContactsIntent(
+ getContext(), v, ContactsContract.Profile.CONTENT_URI,
+ ContactsContract.QuickContact.MODE_LARGE, null);
+ } else {
+ intent = new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI);
+ intent.putExtra(INTENT_EXTRA_NEW_LOCAL_PROFILE, true);
+ }
+ if (mActivityStarter != null) {
+ mActivityStarter.startActivity(intent, true /* dismissShade */);
+ } else {
+ getContext().startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
}
}
@@ -171,4 +190,7 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
return false;
}
+ public void setUserInfoController(UserInfoController userInfoController) {
+ mUserInfoController = userInfoController;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java
new file mode 100644
index 0000000..e767ca5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.widget.FrameLayout;
+import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.statusbar.BaseStatusBar;
+import cyanogenmod.providers.CMSettings;
+
+public class NavBarInsetLayout extends FrameLayout {
+ public static final String TAG = "NavBarInsetLayout";
+ public static final boolean DEBUG = BaseStatusBar.DEBUG;
+
+ boolean mLeftInsetMode = false;
+
+ private int mLeftInset = 0;
+ private int mRightInset = 0;
+
+ private final Paint mTransparentSrcPaint = new Paint();
+
+ private SettingsObserver mSettingsObserver;
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mSettingsObserver.observe();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mSettingsObserver.unobserve();
+ }
+
+ public NavBarInsetLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mTransparentSrcPaint.setColor(0);
+ mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+
+ mSettingsObserver = new SettingsObserver(new Handler());
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ if (getFitsSystemWindows()) {
+ boolean paddingChanged;
+
+ if (mLeftInsetMode) {
+ paddingChanged = insets.right != getPaddingRight()
+ || insets.top != getPaddingTop()
+ || insets.bottom != getPaddingBottom();
+
+ if (insets.left != mLeftInset) {
+ mLeftInset = insets.left;
+ applyMargins();
+ }
+ } else {
+ paddingChanged = insets.left != getPaddingLeft()
+ || insets.top != getPaddingTop()
+ || insets.bottom != getPaddingBottom();
+
+ if (insets.right != mRightInset) {
+ mRightInset = insets.right;
+ applyMargins();
+ }
+ }
+
+ // Drop top inset, apply left inset and pass through bottom inset.
+ if (paddingChanged) {
+ setPadding(mLeftInsetMode ? 0 : insets.left,
+ 0,
+ mLeftInsetMode ? insets.right : 0,
+ 0);
+ }
+ insets.left = 0;
+ insets.top = 0;
+ insets.right = 0;
+ } else {
+ boolean applyMargins = false;
+ if (mLeftInset != 0) {
+ mLeftInset = 0;
+ applyMargins = true;
+ }
+ if (mRightInset != 0) {
+ mRightInset = 0;
+ applyMargins = true;
+ }
+ if (applyMargins) {
+ applyMargins();
+ }
+ boolean changed = getPaddingLeft() != 0
+ || getPaddingRight() != 0
+ || getPaddingTop() != 0
+ || getPaddingBottom() != 0;
+ if (changed) {
+ setPadding(0, 0, 0, 0);
+ }
+ insets.top = 0;
+ }
+ return false;
+ }
+
+ private void applyMargins() {
+ final int N = getChildCount();
+ for (int i = 0; i < N; i++) {
+ View child = getChildAt(i);
+ if (child.getLayoutParams() instanceof InsetLayoutParams) {
+ InsetLayoutParams lp = (InsetLayoutParams) child.getLayoutParams();
+ if (!lp.ignoreRightInset) {
+ if (mLeftInsetMode && lp.leftMargin != mLeftInset) {
+ lp.leftMargin = mLeftInset;
+ if (lp.rightMargin != 0) {
+ lp.rightMargin = 0;
+ }
+ } else if (lp.rightMargin != mRightInset) {
+ lp.rightMargin = mRightInset;
+ if (lp.leftMargin != 0) {
+ lp.leftMargin = 0;
+ }
+ }
+ child.requestLayout();
+ }
+ }
+ }
+ }
+
+ @Override
+ public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new InsetLayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
+ return new InsetLayoutParams(InsetLayoutParams.MATCH_PARENT,
+ InsetLayoutParams.MATCH_PARENT);
+ }
+
+ private class SettingsObserver extends UserContentObserver {
+
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE), false,
+ this, UserHandle.USER_CURRENT);
+ update();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ protected void update() {
+ boolean before = mLeftInsetMode;
+ mLeftInsetMode = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE, 0, UserHandle.USER_CURRENT) == 1;
+ if (mLeftInsetMode != before) {
+ applyMargins();
+ }
+ }
+ }
+
+ public static class InsetLayoutParams extends FrameLayout.LayoutParams {
+
+ public boolean ignoreRightInset;
+
+ public InsetLayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public InsetLayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+
+ TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
+ ignoreRightInset = a.getBoolean(
+ R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
+ a.recycle();
+ }
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java
new file mode 100644
index 0000000..7b4d7f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.view.DisplayInfo;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.KeyButtonView;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import cyanogenmod.providers.CMSettings;
+
+/**
+ * Handles the editing of the navigation bar
+ * @author Danesh M
+ * @hide
+ */
+public class NavbarEditor implements View.OnTouchListener {
+ /**
+ * Holds reference to all assignable button ids
+ */
+ private static final int[] BUTTON_IDS =
+ { R.id.one, R.id.two, R.id.three, R.id.four, R.id.five, R.id.six };
+
+ /**
+ * Subset of BUTTON_IDS, to differentiate small/side buttons
+ * since they can be assigned additional functionality.
+ */
+ private static final int[] SMALL_BUTTON_IDS = { R.id.one, R.id.six };
+
+ // holds the button views in the order they currently appear on screen
+ private final ArrayList<KeyButtonView> mButtonViews;
+ private final boolean mRtl;
+
+ private Context mContext;
+ private static Boolean sIsDevicePhone = null;
+ private boolean mInEditMode = false;
+
+ // Holds reference to the parent/root of the inflated view
+ private View mParent;
+
+ // Button chooser dialog
+ private AlertDialog mDialog;
+
+ // true == we're in landscape mode
+ private boolean mVertical;
+ // true == we're currently checking for long press
+ private boolean mLongPressed;
+ // start point of the current drag operation
+ private float mDragOrigin;
+
+ // just to avoid reallocations
+ private static final int[] sLocation = new int[2];
+
+ private Resources mResources;
+
+ /**
+ * Longpress runnable to assign buttons in edit mode
+ */
+ private Runnable mCheckLongPress = new Runnable() {
+ public void run() {
+ if (mInEditMode) {
+ mLongPressed = true;
+ mParent.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ }
+ }
+ };
+
+ //Available buttons
+ public static final ButtonInfo NAVBAR_EMPTY = new ButtonInfo("empty",
+ R.string.navbar_empty_button, R.string.accessibility_clear_all,
+ 0, R.drawable.ic_sysbar_add,
+ R.drawable.ic_sysbar_add_land, R.drawable.ic_sysbar_add_side);
+ public static final ButtonInfo NAVBAR_HOME = new ButtonInfo("home",
+ R.string.navbar_home_button, R.string.accessibility_home,
+ KeyEvent.KEYCODE_HOME, R.drawable.ic_sysbar_home,
+ R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home);
+ public static final ButtonInfo NAVBAR_BACK = new ButtonInfo("back",
+ R.string.navbar_back_button, R.string.accessibility_back,
+ KeyEvent.KEYCODE_BACK, R.drawable.ic_sysbar_back,
+ R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_side);
+ public static final ButtonInfo NAVBAR_SEARCH = new ButtonInfo("search",
+ R.string.navbar_search_button, R.string.accessibility_back,
+ KeyEvent.KEYCODE_SEARCH, R.drawable.ic_sysbar_search,
+ R.drawable.ic_sysbar_search_land, R.drawable.ic_sysbar_search_side);
+ public static final ButtonInfo NAVBAR_RECENT = new ButtonInfo("recent",
+ R.string.navbar_recent_button, R.string.accessibility_recent,
+ 0, R.drawable.ic_sysbar_recent,
+ R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_side);
+ public static final ButtonInfo NAVBAR_CONDITIONAL_MENU = new ButtonInfo("menu0",
+ R.string.navbar_menu_conditional_button, R.string.accessibility_menu,
+ KeyEvent.KEYCODE_MENU, R.drawable.ic_sysbar_menu,
+ R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu);
+ public static final ButtonInfo NAVBAR_ALWAYS_MENU = new ButtonInfo("menu1",
+ R.string.navbar_menu_always_button, R.string.accessibility_menu,
+ KeyEvent.KEYCODE_MENU, R.drawable.ic_sysbar_menu,
+ R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu);
+ public static final ButtonInfo NAVBAR_MENU_BIG = new ButtonInfo("menu2",
+ R.string.navbar_menu_big_button, R.string.accessibility_menu,
+ KeyEvent.KEYCODE_MENU, R.drawable.ic_sysbar_menu_big,
+ R.drawable.ic_sysbar_menu_big_land, 0);
+ public static final ButtonInfo NAVBAR_DPAD_LEFT = new ButtonInfo("dpad_left",
+ 0, R.string.accessibility_dpad_left,
+ KeyEvent.KEYCODE_DPAD_LEFT, 0,
+ 0, R.drawable.ic_sysbar_ime_left);
+ public static final ButtonInfo NAVBAR_DPAD_RIGHT = new ButtonInfo("dpad_right",
+ 0, R.string.accessibility_dpad_right,
+ KeyEvent.KEYCODE_DPAD_RIGHT, 0,
+ 0, R.drawable.ic_sysbar_ime_right);
+
+ private static final ButtonInfo[] ALL_BUTTONS = new ButtonInfo[] {
+ NAVBAR_EMPTY, NAVBAR_HOME, NAVBAR_BACK, NAVBAR_SEARCH,
+ NAVBAR_RECENT, NAVBAR_CONDITIONAL_MENU, NAVBAR_ALWAYS_MENU, NAVBAR_MENU_BIG
+ };
+
+ private static final String DEFAULT_SETTING_STRING = "empty|back|home|recent|empty|menu0";
+
+ public NavbarEditor (View parent, boolean orientation, boolean isRtl, Resources res) {
+ mContext = parent.getContext();
+ mParent = parent;
+ mVertical = orientation;
+ mRtl = isRtl;
+ mResources = res;
+
+ mButtonViews = new ArrayList<KeyButtonView>();
+
+ KeyButtonView dpadLeft = (KeyButtonView) mParent.findViewById(R.id.dpad_left);
+ dpadLeft.setInfo(NAVBAR_DPAD_LEFT, orientation, true);
+ mButtonViews.add(dpadLeft);
+
+ for (int id : BUTTON_IDS) {
+ mButtonViews.add((KeyButtonView) mParent.findViewById(id));
+ }
+
+ KeyButtonView dpadRight = (KeyButtonView) mParent.findViewById(R.id.dpad_right);
+ dpadRight.setInfo(NAVBAR_DPAD_RIGHT, orientation, true);
+ mButtonViews.add(dpadRight);
+ }
+
+ public void setEditMode(boolean editMode) {
+ mInEditMode = editMode;
+ for (Integer id : BUTTON_IDS) {
+ KeyButtonView button = (KeyButtonView) mParent.findViewById(id);
+ if (button != null) {
+ button.setEditMode(editMode);
+ button.setOnTouchListener(editMode ? this : null);
+ }
+ }
+ if (!editMode && mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ }
+
+ public static boolean isDevicePhone(Context context) {
+ if (sIsDevicePhone == null) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ DisplayInfo outDisplayInfo = new DisplayInfo();
+
+ wm.getDefaultDisplay().getDisplayInfo(outDisplayInfo);
+
+ int shortSize = Math.min(outDisplayInfo.logicalHeight, outDisplayInfo.logicalWidth);
+ int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / outDisplayInfo.logicalDensityDpi;
+
+ // 0-599dp: "phone" UI with a separate status & navigation bar
+ sIsDevicePhone = shortSizeDp < 600;
+ }
+
+ return sIsDevicePhone;
+ }
+
+ /**
+ * Find intersecting view in mButtonViews
+ * @param pos - pointer location
+ * @param v - view being dragged
+ * @return intersecting view or null
+ */
+ private View findInterceptingView(float pos, View v) {
+ for (KeyButtonView otherView : mButtonViews) {
+ if (otherView == v) {
+ continue;
+ }
+
+ if (ArrayUtils.contains(SMALL_BUTTON_IDS, otherView.getId())) {
+ continue;
+ }
+
+ otherView.getLocationOnScreen(sLocation);
+ float otherPos = sLocation[mVertical ? 1 : 0];
+ float otherDimension = mVertical ? v.getHeight() : v.getWidth();
+
+ if (pos > (otherPos + otherDimension / 4) && pos < (otherPos + otherDimension)) {
+ return otherView;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean onTouch(final View view, MotionEvent event) {
+ if (!mInEditMode || (mDialog != null && mDialog.isShowing())) {
+ return false;
+ }
+
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ view.setPressed(true);
+ view.getLocationOnScreen(sLocation);
+ mDragOrigin = sLocation[mVertical ? 1 : 0];
+ view.postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
+ } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ view.setPressed(false);
+
+ if (!mLongPressed || ArrayUtils.contains(SMALL_BUTTON_IDS, view.getId())) {
+ return false;
+ }
+
+ ViewGroup viewParent = (ViewGroup) view.getParent();
+ float pos = mVertical ? event.getRawY() : event.getRawX();
+ float buttonSize = mVertical ? view.getHeight() : view.getWidth();
+ float min = mVertical ? viewParent.getTop() : (viewParent.getLeft() - buttonSize / 2);
+ float max = mVertical ? (viewParent.getTop() + viewParent.getHeight())
+ : (viewParent.getLeft() + viewParent.getWidth());
+
+ // Prevents user from dragging view outside of bounds
+ if (pos < min || pos > max) {
+ return false;
+ }
+ if (!mVertical) {
+ view.setX(pos - viewParent.getLeft() - buttonSize / 2);
+ } else {
+ view.setY(pos - viewParent.getTop() - buttonSize / 2);
+ }
+ View affectedView = findInterceptingView(pos, view);
+ if (affectedView == null) {
+ return false;
+ }
+ switchId(affectedView, view);
+ } else if (event.getAction() == MotionEvent.ACTION_UP
+ || event.getAction() == MotionEvent.ACTION_CANCEL) {
+ view.setPressed(false);
+ view.removeCallbacks(mCheckLongPress);
+
+ if (!mLongPressed && !view.getTag().equals(NAVBAR_HOME) &&
+ !view.getTag().equals(NAVBAR_RECENT) && !view.getTag().equals(NAVBAR_BACK)) {
+ final boolean isSmallButton = ArrayUtils.contains(SMALL_BUTTON_IDS, view.getId());
+ final ButtonAdapter list = new ButtonAdapter(mContext, mButtonViews, isSmallButton,
+ getResources());
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
+ .setTitle(mContext.getString(R.string.navbar_dialog_title))
+ .setAdapter(list, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ KeyButtonView button = (KeyButtonView) view;
+ ButtonInfo info = list.getItem(which);
+
+ button.setInfo(info, mVertical, isSmallButton);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
+
+ mDialog = builder.create();
+ mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+ mDialog.setCanceledOnTouchOutside(false);
+ mDialog.show();
+ } else {
+ // Reset the dragged view to its original location
+ ViewGroup parent = (ViewGroup) view.getParent();
+
+ if (!mVertical) {
+ view.setX(mDragOrigin - parent.getLeft());
+ } else {
+ view.setY(mDragOrigin - parent.getTop());
+ }
+ }
+ mLongPressed = false;
+ }
+ return true;
+ }
+
+ /**
+ * Switches positions of two views and
+ * updates their mButtonViews entry
+ * @param targetView - view to be replaced
+ * @param view - view being dragged
+ */
+ private void switchId(View targetView, View view) {
+ ViewGroup parent = (ViewGroup) view.getParent();
+
+ targetView.getLocationOnScreen(sLocation);
+ if (!mVertical) {
+ targetView.setX(mDragOrigin - parent.getLeft());
+ mDragOrigin = sLocation[0];
+ } else {
+ targetView.setY(mDragOrigin - parent.getTop());
+ mDragOrigin = sLocation[1];
+ }
+
+ int targetIndex = mButtonViews.indexOf(targetView);
+ int draggedIndex = mButtonViews.indexOf(view);
+ Collections.swap(mButtonViews, draggedIndex, targetIndex);
+ }
+
+ /**
+ * Saves the current key arrangement
+ * to the settings provider
+ */
+ protected void saveKeys() {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < BUTTON_IDS.length; i++) {
+ int idIndex = mVertical && !mRtl ? BUTTON_IDS.length - (i + 1) : i;
+ ButtonInfo info = (ButtonInfo) mButtonViews.get(idIndex).getTag();
+ if (i != 0) sb.append("|");
+ sb.append(info.key);
+ }
+ CMSettings.System.putStringForUser(mContext.getContentResolver(),
+ CMSettings.System.NAV_BUTTONS, sb.toString(), UserHandle.USER_CURRENT);
+ }
+
+ /**
+ * Updates the buttons according to the
+ * key arrangement stored in settings provider
+ */
+ protected void updateKeys() {
+ String saved = CMSettings.System.getStringForUser(mContext.getContentResolver(),
+ CMSettings.System.NAV_BUTTONS, UserHandle.USER_CURRENT);
+ if (saved == null) {
+ saved = DEFAULT_SETTING_STRING;
+ }
+
+ String[] buttons = saved.split("\\|");
+ if (buttons.length < BUTTON_IDS.length) {
+ buttons = DEFAULT_SETTING_STRING.split("\\|");
+ }
+
+ int visibleCount = 0;
+
+ for (int i = 0; i < BUTTON_IDS.length; i++) {
+ int id = BUTTON_IDS[i];
+ int index = mVertical && !mRtl ? BUTTON_IDS.length - i - 1 : i;
+ String key = index < buttons.length ? buttons[index] : null;
+ KeyButtonView buttonView = (KeyButtonView) mParent.findViewById(id);
+ boolean isSmallButton = ArrayUtils.contains(SMALL_BUTTON_IDS, id);
+ ButtonInfo button = NAVBAR_EMPTY;
+
+ for (ButtonInfo info : ALL_BUTTONS) {
+ if (info.key.equals(key)) {
+ button = info;
+ break;
+ }
+ }
+
+ buttonView.setInfo(button, mVertical, isSmallButton, getResources());
+ if (button != NAVBAR_EMPTY && !isSmallButton) {
+ visibleCount++;
+ }
+
+ buttonView.setTranslationX(0);
+ mButtonViews.set(i, buttonView);
+ }
+
+ if (isDevicePhone(mContext)) {
+ adjustPadding(visibleCount);
+ }
+ updateLowLights(visibleCount);
+ }
+
+ /**
+ * Accommodates the padding between keys based on
+ * number of keys in use.
+ */
+ private void adjustPadding(int visibleCount) {
+ ViewGroup viewParent = (ViewGroup) mParent.findViewById(R.id.mid_nav_buttons);
+ int totalViews = viewParent.getChildCount();
+
+ for (int v = 0; v < totalViews; v++) {
+ View currentKey = viewParent.getChildAt(v);
+ if (!(currentKey instanceof KeyButtonView)) {
+ continue;
+ }
+ View nextPadding = viewParent.getChildAt(v + 1);
+ if (nextPadding == null) {
+ continue;
+ }
+
+ View nextKey = viewParent.getChildAt(v + 2);
+ ButtonInfo nextInfo = nextKey == null ? null : (ButtonInfo) nextKey.getTag();
+ ButtonInfo currentInfo = (ButtonInfo) currentKey.getTag();
+
+ if (nextInfo != null && currentInfo != null && currentInfo != NAVBAR_EMPTY) {
+ if (nextInfo != NAVBAR_EMPTY || visibleCount > 1) {
+ nextPadding.setVisibility(View.VISIBLE);
+ } else {
+ nextPadding.setVisibility(View.GONE);
+ }
+ visibleCount--;
+ } else {
+ nextPadding.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ protected void updateLowLights(int visibleCount) {
+ ViewGroup lowLights = (ViewGroup) mParent.findViewById(R.id.lights_out);
+ int totalViews = lowLights.getChildCount();
+
+ for (int v = 0;v < totalViews; v++) {
+ View currentView = lowLights.getChildAt(v);
+ if (!(currentView instanceof ImageView)) {
+ continue;
+ }
+
+ if (visibleCount <= 0) {
+ currentView.setVisibility(View.GONE);
+ } else {
+ currentView.setVisibility(View.VISIBLE);
+ visibleCount--;
+ }
+
+ View blank = lowLights.getChildAt(v + 1);
+ if (blank != null) {
+ blank.setVisibility(visibleCount > 0 ? View.VISIBLE : View.GONE);
+ }
+ }
+ }
+
+ private Resources getResources() {
+ return mResources != null ? mResources : mContext.getResources();
+ }
+
+ public void updateResources(Resources res) {
+ mResources = res;
+ }
+
+ /**
+ * Class to store info about supported buttons
+ */
+ public static final class ButtonInfo {
+ private final String key;
+ public int displayId;
+ public int contentDescription;
+ public int keyCode;
+ public int portResource;
+ public int landResource;
+ public int sideResource;
+ /**
+ * Constructor for new button type
+ * @param key - the internal key of the button
+ * @param rId - resource id of text shown to user in choose dialog
+ * @param cD - accessibility information regarding button
+ * @param mC - keyCode to execute on button press
+ * @param pR - portrait resource used to display button
+ * @param lR - landscape resource used to display button
+ * @param sR - smaller scaled resource for side buttons
+ */
+ ButtonInfo (String key, int rId, int cD, int mC, int pR, int lR, int sR) {
+ this.key = key;
+ displayId = rId;
+ contentDescription = cD;
+ keyCode = mC;
+ portResource = pR;
+ landResource = lR;
+ sideResource = sR;
+ }
+
+ @Override
+ public String toString() {
+ return "ButtonInfo[" + key + "]";
+ }
+ }
+
+ private static class ButtonAdapter extends ArrayAdapter<ButtonInfo> {
+ private ArrayList<ButtonInfo> mTakenItems;
+ private Resources mResources;
+
+ public ButtonAdapter(Context context,
+ ArrayList<KeyButtonView> buttons, boolean smallButtons, Resources resources) {
+ super(context, R.layout.navigation_bar_edit_menu_item, R.id.key_text,
+ buildItems(smallButtons));
+
+ mTakenItems = new ArrayList<ButtonInfo>();
+ for (KeyButtonView button : buttons) {
+ ButtonInfo info = (ButtonInfo) button.getTag();
+ if (info != null && info != NAVBAR_EMPTY) {
+ mTakenItems.add(info);
+ }
+ }
+ mResources = resources;
+ }
+
+ private static List<ButtonInfo> buildItems(boolean smallButtons) {
+ List<ButtonInfo> items = new ArrayList<ButtonInfo>(Arrays.asList(ALL_BUTTONS));
+
+ // Not re-assignable
+ items.remove(NAVBAR_HOME);
+ items.remove(NAVBAR_RECENT);
+ items.remove(NAVBAR_BACK);
+ // menu buttons can only be assigned to side buttons
+ if (!smallButtons) {
+ items.remove(NAVBAR_CONDITIONAL_MENU);
+ items.remove(NAVBAR_ALWAYS_MENU);
+ } else {
+ items.remove(NAVBAR_MENU_BIG);
+ }
+
+ return items;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view = super.getView(position, convertView, parent);
+ ButtonInfo info = getItem(position);
+ boolean enabled = isEnabled(position);
+
+ TextView text = (TextView) view.findViewById(R.id.key_text);
+ text.setText(getContext().getResources().getString(info.displayId));
+ text.setEnabled(enabled);
+
+ ImageView icon = (ImageView) view.findViewById(R.id.key_icon);
+ icon.setImageDrawable(mResources.getDrawable(info.portResource));
+ icon.setColorFilter(new PorterDuffColorFilter(
+ text.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
+
+ return view;
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return !mTakenItems.contains(getItem(position));
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 134c579..50656ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -35,7 +35,10 @@ public final class NavigationBarTransitions extends BarTransitions {
private boolean mLightsOut;
public NavigationBarTransitions(NavigationBarView view) {
- super(view, R.drawable.nav_background);
+ super(view, R.drawable.nav_background, R.color.navigation_bar_background_opaque,
+ R.color.navigation_bar_background_semi_transparent,
+ R.color.navigation_bar_background_transparent,
+ com.android.internal.R.color.battery_saver_mode_color);
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 8046eb5..b3ba926 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -23,15 +23,22 @@ import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
@@ -48,6 +55,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonView;
@@ -55,6 +63,8 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import cyanogenmod.providers.CMSettings;
+
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
final static String TAG = "PhoneStatusBar/NavigationBarView";
@@ -69,26 +79,56 @@ public class NavigationBarView extends LinearLayout {
int mBarSize;
boolean mVertical;
boolean mScreenOn;
+ boolean mLeftInLandscape;
boolean mShowMenu;
int mDisabledFlags = 0;
int mNavigationIconHints = 0;
- private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
+ private BackButtonDrawable mBackIcon, mBackLandIcon;
private Drawable mRecentIcon;
private Drawable mRecentLandIcon;
+ private Drawable mHomeIcon, mHomeLandIcon;
private NavigationBarViewTaskSwitchHelper mTaskSwitchHelper;
private DeadZone mDeadZone;
private final NavigationBarTransitions mBarTransitions;
+ /**
+ * Tracks the current visibilities of the far left (R.id.one) and right (R.id.six) buttons
+ * while dpad arrow keys are visible.
+ *
+ * We keep track of the orientations separately because they can get in different states,
+ * We can be showing dpad arrow keys on vertical, but on portrait that may not be so.
+ */
+ public int[][] mSideButtonVisibilities = new int[][] {
+ {-1, -1} /* portrait */, {-1, -1} /* vertical */
+ };
+
+
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
final static boolean WORKAROUND_INVALID_LAYOUT = true;
final static int MSG_CHECK_INVALID_LAYOUT = 8686;
+ final static String NAVBAR_EDIT_ACTION = "android.intent.action.NAVBAR_EDIT";
+
+ private boolean mInEditMode;
+ private NavbarEditor mEditBar;
+ private NavBarReceiver mNavBarReceiver;
+ private OnClickListener mRecentsClickListener;
+ private OnTouchListener mRecentsPreloadListener;
+ private OnTouchListener mHomeSearchActionListener;
+ private OnLongClickListener mRecentsBackListener;
+ private OnLongClickListener mLongPressHomeListener;
+
+ private SettingsObserver mSettingsObserver;
+ private boolean mShowDpadArrowKeys;
+
// performs manual animation in sync with layout transitions
private final NavTransitionListener mTransitionListener = new NavTransitionListener();
+ private Resources mThemedResources;
+
private OnVerticalChangedListener mOnVerticalChangedListener;
private boolean mIsLayoutRtl;
private boolean mLayoutTransitionsEnabled = true;
@@ -104,9 +144,9 @@ public class NavigationBarView extends LinearLayout {
@Override
public void startTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
- if (view.getId() == R.id.back) {
+ if (NavbarEditor.NAVBAR_BACK.equals(view.getTag())) {
mBackTransitioning = true;
- } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
+ } else if (NavbarEditor.NAVBAR_HOME.equals(view.getTag()) && transitionType == LayoutTransition.APPEARING) {
mHomeAppearing = true;
mStartDelay = transition.getStartDelay(transitionType);
mDuration = transition.getDuration(transitionType);
@@ -117,9 +157,9 @@ public class NavigationBarView extends LinearLayout {
@Override
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
- if (view.getId() == R.id.back) {
+ if (NavbarEditor.NAVBAR_BACK.equals(view.getTag())) {
mBackTransitioning = false;
- } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
+ } else if (NavbarEditor.NAVBAR_HOME.equals(view.getTag()) && transitionType == LayoutTransition.APPEARING) {
mHomeAppearing = false;
}
}
@@ -176,7 +216,7 @@ public class NavigationBarView extends LinearLayout {
mDisplay = ((WindowManager)context.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay();
- final Resources res = getContext().getResources();
+ final Resources res = getResources();
mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
mVertical = false;
mShowMenu = false;
@@ -185,6 +225,10 @@ public class NavigationBarView extends LinearLayout {
getIcons(res);
mBarTransitions = new NavigationBarTransitions(this);
+
+ mNavBarReceiver = new NavBarReceiver();
+ getContext().registerReceiver(mNavBarReceiver, new IntentFilter(NAVBAR_EDIT_ACTION));
+ mSettingsObserver = new SettingsObserver(new Handler());
}
@Override
@@ -194,6 +238,13 @@ public class NavigationBarView extends LinearLayout {
if (root != null) {
root.setDrawDuringWindowsAnimating(true);
}
+ mSettingsObserver.observe();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mSettingsObserver.unobserve();
}
public BarTransitions getBarTransitions() {
@@ -211,7 +262,7 @@ public class NavigationBarView extends LinearLayout {
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mTaskSwitchHelper.onTouchEvent(event)) {
+ if (!mInEditMode && mTaskSwitchHelper.onTouchEvent(event)) {
return true;
}
if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
@@ -222,7 +273,7 @@ public class NavigationBarView extends LinearLayout {
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- return mTaskSwitchHelper.onInterceptTouchEvent(event);
+ return !mInEditMode && mTaskSwitchHelper.onInterceptTouchEvent(event);
}
public void abortCurrentGesture() {
@@ -236,19 +287,19 @@ public class NavigationBarView extends LinearLayout {
}
public View getRecentsButton() {
- return mCurrentView.findViewById(R.id.recent_apps);
+ return mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_RECENT);
}
public View getMenuButton() {
- return mCurrentView.findViewById(R.id.menu);
+ return mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_CONDITIONAL_MENU);
}
public View getBackButton() {
- return mCurrentView.findViewById(R.id.back);
+ return mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_BACK);
}
public KeyButtonView getHomeButton() {
- return (KeyButtonView) mCurrentView.findViewById(R.id.home);
+ return (KeyButtonView) mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_HOME);
}
public View getImeSwitchButton() {
@@ -256,17 +307,51 @@ public class NavigationBarView extends LinearLayout {
}
private void getIcons(Resources res) {
- mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back);
- mBackLandIcon = mBackIcon;
- mBackAltIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
- mBackAltLandIcon = mBackAltIcon;
+ mBackIcon = new BackButtonDrawable(res.getDrawable(R.drawable.ic_sysbar_back));
+ mBackLandIcon = mBackIcon;
mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent);
mRecentLandIcon = mRecentIcon;
+ mHomeIcon = res.getDrawable(R.drawable.ic_sysbar_home);
+ mHomeLandIcon = mHomeIcon;
+ }
+
+ public void updateResources(Resources res) {
+ mThemedResources = res;
+ getIcons(mThemedResources);
+ mBarTransitions.updateResources(res);
+ for (int i = 0; i < mRotatedViews.length; i++) {
+ ViewGroup container = (ViewGroup) mRotatedViews[i];
+ if (container != null) {
+ updateLightsOutResources(container);
+ }
+ }
+ if (mEditBar != null) {
+ mEditBar.updateResources(res);
+ }
+ }
+
+ private void updateLightsOutResources(ViewGroup container) {
+ ViewGroup lightsOut = (ViewGroup) container.findViewById(R.id.lights_out);
+ if (lightsOut != null) {
+ final int nChildren = lightsOut.getChildCount();
+ for (int i = 0; i < nChildren; i++) {
+ final View child = lightsOut.getChildAt(i);
+ if (child instanceof ImageView) {
+ final ImageView iv = (ImageView) child;
+ // clear out the existing drawable, this is required since the
+ // ImageView keeps track of the resource ID and if it is the same
+ // it will not update the drawable.
+ iv.setImageDrawable(null);
+ iv.setImageDrawable(mThemedResources.getDrawable(
+ R.drawable.ic_sysbar_lights_out_dot_large));
+ }
+ }
+ }
}
@Override
public void setLayoutDirection(int layoutDirection) {
- getIcons(getContext().getResources());
+ getIcons(getResources());
super.setLayoutDirection(layoutDirection);
}
@@ -294,19 +379,61 @@ public class NavigationBarView extends LinearLayout {
mNavigationIconHints = hints;
- ((ImageView)getBackButton()).setImageDrawable(backAlt
- ? (mVertical ? mBackAltLandIcon : mBackAltIcon)
- : (mVertical ? mBackLandIcon : mBackIcon));
+ ((ImageView)getBackButton()).setImageDrawable(null);
+ ((ImageView)getBackButton()).setImageDrawable(mVertical ? mBackLandIcon : mBackIcon);
+ mBackLandIcon.setImeVisible(backAlt);
+ mBackIcon.setImeVisible(backAlt);
((ImageView)getRecentsButton()).setImageDrawable(mVertical ? mRecentLandIcon : mRecentIcon);
+ ((ImageView)getHomeButton()).setImageDrawable(mVertical ? mHomeLandIcon : mHomeIcon);
- final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
+ final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0)
+ && !mShowDpadArrowKeys;
getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
+
+ setDisabledFlags(mDisabledFlags, true);
+
// Update menu button in case the IME state has changed.
setMenuVisibility(mShowMenu, true);
+ if (mShowDpadArrowKeys) { // overrides IME button
+ final boolean showingIme = ((mNavigationIconHints
+ & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0);
- setDisabledFlags(mDisabledFlags, true);
+ setVisibleOrGone(getCurrentView().findViewById(R.id.dpad_left), showingIme);
+ setVisibleOrGone(getCurrentView().findViewById(R.id.dpad_right), showingIme);
+
+ View one = getCurrentView().findViewById(mVertical ? R.id.six : R.id.one);
+ View six = getCurrentView().findViewById(mVertical ? R.id.one : R.id.six);
+ if (showingIme) {
+ if (one.getVisibility() != View.GONE) {
+ setSideButtonVisibility(true, one.getVisibility());
+ setVisibleOrGone(one, false);
+ }
+
+ if (six.getVisibility() != View.GONE) {
+ setSideButtonVisibility(false, six.getVisibility());
+ setVisibleOrGone(six, false);
+ }
+ } else {
+ if (getSideButtonVisibility(true) != -1) {
+ one.setVisibility(getSideButtonVisibility(true));
+ setSideButtonVisibility(true, - 1);
+ }
+ if (getSideButtonVisibility(false) != -1) {
+ six.setVisibility(getSideButtonVisibility(false));
+ setSideButtonVisibility(false, -1);
+ }
+ }
+ }
+ }
+
+ private int getSideButtonVisibility(boolean left) {
+ return mSideButtonVisibilities[mVertical ? 1 : 0][left ? 0 : 1];
+ }
+
+ private void setSideButtonVisibility(boolean left, int vis) {
+ mSideButtonVisibilities[mVertical ? 1 : 0][left ? 0 : 1] = vis;
}
public void setDisabledFlags(int disabledFlags) {
@@ -343,9 +470,10 @@ public class NavigationBarView extends LinearLayout {
disableRecent = false;
}
- getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
- getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
- getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_BACK, !disableBack);
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_HOME, !disableHome);
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_RECENT, !disableRecent);
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_SEARCH, !disableSearch);
}
private boolean inLockTask() {
@@ -436,18 +564,19 @@ public class NavigationBarView extends LinearLayout {
// Only show Menu if IME switcher not shown.
final boolean shouldShow = mShowMenu &&
((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
- getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
+ final boolean shouldShowAlwaysMenu = (mNavigationIconHints &
+ StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0;
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_ALWAYS_MENU, shouldShowAlwaysMenu);
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_CONDITIONAL_MENU, shouldShow);
+ setButtonWithTagVisibility(NavbarEditor.NAVBAR_SEARCH, shouldShowAlwaysMenu);
}
@Override
public void onFinishInflate() {
mRotatedViews[Surface.ROTATION_0] =
- mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
-
+ mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
-
mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];
-
mCurrentView = mRotatedViews[Surface.ROTATION_0];
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -459,6 +588,11 @@ public class NavigationBarView extends LinearLayout {
return mVertical;
}
+ public void setLeftInLandscape(boolean leftInLandscape) {
+ mLeftInLandscape = leftInLandscape;
+ mDeadZone.setStartFromRight(leftInLandscape);
+ }
+
public void reorient() {
final int rot = mDisplay.getRotation();
for (int i=0; i<4; i++) {
@@ -466,11 +600,22 @@ public class NavigationBarView extends LinearLayout {
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
+
updateLayoutTransitionsEnabled();
+ if (NavbarEditor.isDevicePhone(getContext())) {
+ int rotation = mDisplay.getRotation();
+ mVertical = rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270;
+ } else {
+ mVertical = getWidth() > 0 && getHeight() > getWidth();
+ }
+ mEditBar = new NavbarEditor(mCurrentView, mVertical, mIsLayoutRtl, getResources());
+ updateSettings();
+
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
+ mDeadZone.setStartFromRight(mLeftInLandscape);
// force the low profile & disabled states into compliance
mBarTransitions.init();
@@ -529,55 +674,8 @@ public class NavigationBarView extends LinearLayout {
boolean isLayoutRtl = getResources().getConfiguration()
.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
if (mIsLayoutRtl != isLayoutRtl) {
-
- // We swap all children of the 90 and 270 degree layouts, since they are vertical
- View rotation90 = mRotatedViews[Surface.ROTATION_90];
- swapChildrenOrderIfVertical(rotation90.findViewById(R.id.nav_buttons));
- adjustExtraKeyGravity(rotation90, isLayoutRtl);
-
- View rotation270 = mRotatedViews[Surface.ROTATION_270];
- if (rotation90 != rotation270) {
- swapChildrenOrderIfVertical(rotation270.findViewById(R.id.nav_buttons));
- adjustExtraKeyGravity(rotation270, isLayoutRtl);
- }
mIsLayoutRtl = isLayoutRtl;
- }
- }
-
- private void adjustExtraKeyGravity(View navBar, boolean isLayoutRtl) {
- View menu = navBar.findViewById(R.id.menu);
- View imeSwitcher = navBar.findViewById(R.id.ime_switcher);
- if (menu != null) {
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) menu.getLayoutParams();
- lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP;
- menu.setLayoutParams(lp);
- }
- if (imeSwitcher != null) {
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) imeSwitcher.getLayoutParams();
- lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP;
- imeSwitcher.setLayoutParams(lp);
- }
- }
-
- /**
- * Swaps the children order of a LinearLayout if it's orientation is Vertical
- *
- * @param group The LinearLayout to swap the children from.
- */
- private void swapChildrenOrderIfVertical(View group) {
- if (group instanceof LinearLayout) {
- LinearLayout linearLayout = (LinearLayout) group;
- if (linearLayout.getOrientation() == VERTICAL) {
- int childCount = linearLayout.getChildCount();
- ArrayList<View> childList = new ArrayList<>(childCount);
- for (int i = 0; i < childCount; i++) {
- childList.add(linearLayout.getChildAt(i));
- }
- linearLayout.removeAllViews();
- for (int i = childCount - 1; i >= 0; i--) {
- linearLayout.addView(childList.get(i));
- }
- }
+ reorient();
}
}
@@ -605,7 +703,7 @@ public class NavigationBarView extends LinearLayout {
private String getResourceName(int resId) {
if (resId != 0) {
- final android.content.res.Resources res = getContext().getResources();
+ final android.content.res.Resources res = getResources();
try {
return res.getResourceName(resId);
} catch (android.content.res.Resources.NotFoundException ex) {
@@ -671,9 +769,9 @@ public class NavigationBarView extends LinearLayout {
pw.print("null");
} else {
pw.print(PhoneStatusBar.viewInfo(button)
- + " " + visibilityToString(button.getVisibility())
- + " alpha=" + button.getAlpha()
- );
+ + " " + visibilityToString(button.getVisibility())
+ + " alpha=" + button.getAlpha()
+ );
}
pw.println();
}
@@ -681,4 +779,145 @@ public class NavigationBarView extends LinearLayout {
public interface OnVerticalChangedListener {
void onVerticalChanged(boolean isVertical);
}
+
+ void setListeners(OnClickListener recentsClickListener, OnTouchListener recentsPreloadListener,
+ OnLongClickListener recentsBackListener, OnTouchListener homeSearchActionListener,
+ OnLongClickListener longPressHomeListener) {
+ mRecentsClickListener = recentsClickListener;
+ mRecentsPreloadListener = recentsPreloadListener;
+ mHomeSearchActionListener = homeSearchActionListener;
+ mRecentsBackListener = recentsBackListener;
+ mLongPressHomeListener = longPressHomeListener;
+ updateButtonListeners();
+ }
+
+ private void removeButtonListeners() {
+ ViewGroup container = (ViewGroup) mCurrentView.findViewById(R.id.container);
+ int viewCount = container.getChildCount();
+ for (int i = 0; i < viewCount; i++) {
+ View button = container.getChildAt(i);
+ if (button instanceof KeyButtonView) {
+ button.setOnClickListener(null);
+ button.setOnTouchListener(null);
+ button.setLongClickable(false);
+ button.setOnLongClickListener(null);
+ }
+ }
+ }
+
+ protected void updateButtonListeners() {
+ View recentView = mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_RECENT);
+ if (recentView != null) {
+ recentView.setOnClickListener(mRecentsClickListener);
+ recentView.setOnTouchListener(mRecentsPreloadListener);
+ recentView.setLongClickable(true);
+ recentView.setOnLongClickListener(mRecentsBackListener);
+ }
+ View backView = mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_BACK);
+ if (backView != null) {
+ backView.setLongClickable(true);
+ backView.setOnLongClickListener(mRecentsBackListener);
+ }
+ View homeView = mCurrentView.findViewWithTag(NavbarEditor.NAVBAR_HOME);
+ if (homeView != null) {
+ homeView.setOnTouchListener(mHomeSearchActionListener);
+ homeView.setLongClickable(true);
+ homeView.setOnLongClickListener(mLongPressHomeListener);
+ }
+ }
+
+ public boolean isInEditMode() {
+ return mInEditMode;
+ }
+
+ private void setButtonWithTagVisibility(Object tag, boolean visible) {
+ View findView = mCurrentView.findViewWithTag(tag);
+ if (findView == null) {
+ return;
+ }
+ int visibility = visible ? View.VISIBLE : View.INVISIBLE;
+ // if we're showing dpad arrow keys (e.g. the side button visibility where it's shown != -1)
+ // then don't actually update that buttons visibility, but update the stored value
+ if (getSideButtonVisibility(true) != -1
+ && findView.getId() == (mVertical ? R.id.six : R.id.one)) {
+ setSideButtonVisibility(true, visibility);
+ } else if (getSideButtonVisibility(false) != -1
+ && findView.getId() == (mVertical ? R.id.one : R.id.six)) {
+ setSideButtonVisibility(false, visibility);
+ } else {
+ findView.setVisibility(visibility);
+ }
+ }
+
+ @Override
+ public Resources getResources() {
+ return mThemedResources != null ? mThemedResources : getContext().getResources();
+ }
+
+ public class NavBarReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean edit = intent.getBooleanExtra("edit", false);
+ boolean save = intent.getBooleanExtra("save", false);
+ if (edit != mInEditMode) {
+ mInEditMode = edit;
+ if (edit) {
+ removeButtonListeners();
+ mEditBar.setEditMode(true);
+ } else {
+ if (save) {
+ mEditBar.saveKeys();
+ }
+ mEditBar.setEditMode(false);
+ updateSettings();
+ }
+ }
+ }
+ }
+
+ public void updateSettings() {
+ mEditBar.updateKeys();
+ removeButtonListeners();
+ updateButtonListeners();
+ setDisabledFlags(mDisabledFlags, true /* force */);
+ setMenuVisibility(mShowMenu, true);
+ }
+
+ private class SettingsObserver extends UserContentObserver {
+
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void observe() {
+ super.observe();
+ ContentResolver resolver = getContext().getContentResolver();
+ resolver.registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS),
+ false, this);
+
+ // intialize mModlockDisabled
+ onChange(false);
+ }
+
+ @Override
+ public void unobserve() {
+ super.unobserve();
+ getContext().getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ protected void update() {
+ mShowDpadArrowKeys = CMSettings.System.getIntForUser(getContext().getContentResolver(),
+ CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0;
+ // reset saved side button visibilities
+ for (int i = 0; i < mSideButtonVisibilities.length; i++) {
+ for (int j = 0; j < mSideButtonVisibilities[i].length; j++) {
+ mSideButtonVisibilities[i][j] = -1;
+ }
+ }
+ setNavigationIconHints(mNavigationIconHints, true);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index bdd2c73..aaa7019 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -21,20 +21,32 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.PowerManager;
import android.util.AttributeSet;
import android.util.MathUtils;
+import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
@@ -51,7 +63,7 @@ import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.qs.QSContainer;
-import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSDragPanel;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -64,7 +76,13 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
+import cyanogenmod.externalviews.KeyguardExternalView;
+import cyanogenmod.providers.CMSettings;
+
import java.util.List;
+import java.util.Objects;
+
+import org.cyanogenmod.internal.util.CmLockPatternUtils;
public class NotificationPanelView extends PanelView implements
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
@@ -90,12 +108,18 @@ public class NotificationPanelView extends PanelView implements
public static final long DOZE_ANIMATION_DURATION = 700;
+
+ // Layout params for external keyguard view
+ private static final FrameLayout.LayoutParams EXTERNAL_KEYGUARD_VIEW_PARAMS =
+ new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+
private KeyguardAffordanceHelper mAfforanceHelper;
private StatusBarHeaderView mHeader;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private KeyguardStatusBarView mKeyguardStatusBar;
private QSContainer mQsContainer;
- private QSPanel mQsPanel;
+ private QSDragPanel mQsPanel;
private KeyguardStatusView mKeyguardStatusView;
private ObservableScrollView mScrollView;
private TextView mClockView;
@@ -205,6 +229,11 @@ public class NotificationPanelView extends PanelView implements
private boolean mLaunchingAffordance;
private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ private ComponentName mThirdPartyKeyguardViewComponent;
+ private KeyguardExternalView mKeyguardExternalView;
+ private CmLockPatternUtils mLockPatternUtils;
+ private boolean mLiveLockScreenEnabled;
+
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
@Override
public void run() {
@@ -217,9 +246,28 @@ public class NotificationPanelView extends PanelView implements
private final Interpolator mTouchResponseInterpolator =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+ private Handler mHandler = new Handler();
+ private SettingsObserver mSettingsObserver;
+
+ private int mOneFingerQuickSettingsIntercept;
+ private boolean mDoubleTapToSleepEnabled;
+ private int mStatusBarHeaderHeight;
+ private GestureDetector mDoubleTapGesture;
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(!DEBUG);
+
+ mSettingsObserver = new SettingsObserver(mHandler);
+ mDoubleTapGesture = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ if(pm != null)
+ pm.goToSleep(e.getEventTime());
+ return true;
+ }
+ });
}
public void setStatusBar(PhoneStatusBar bar) {
@@ -234,10 +282,9 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container);
- mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
+ mQsPanel = (QSDragPanel) findViewById(R.id.quick_settings_panel);
mClockView = (TextView) findViewById(R.id.clock_view);
mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
- mScrollView.setListener(this);
mScrollView.setFocusable(false);
mReserveNotificationSpace = findViewById(R.id.reserve_notification_space);
mNotificationContainerParent = (NotificationsQuickSettingsContainer)
@@ -271,6 +318,28 @@ public class NotificationPanelView extends PanelView implements
}
}
});
+
+ mLockPatternUtils = new CmLockPatternUtils(getContext());
+ if (mLockPatternUtils.isThirdPartyKeyguardEnabled() && mLiveLockScreenEnabled) {
+ mThirdPartyKeyguardViewComponent = mLockPatternUtils.getThirdPartyKeyguardComponent();
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mSettingsObserver.observe();
+ mContext.registerReceiver(mExternalKeyguardViewChangedReceiver,
+ new IntentFilter(CmLockPatternUtils.ACTION_THIRD_PARTY_KEYGUARD_COMPONENT_CHANGED));
+
+ mScrollView.setListener(this);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mSettingsObserver.unobserve();
+ mContext.unregisterReceiver(mExternalKeyguardViewChangedReceiver);
}
@Override
@@ -292,6 +361,7 @@ public class NotificationPanelView extends PanelView implements
R.dimen.qs_falsing_threshold);
mPositionMinSideMargin = getResources().getDimensionPixelSize(
R.dimen.notification_panel_min_side_margin);
+ mStatusBarHeaderHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
}
public void updateResources() {
@@ -382,6 +452,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onAnimationEnd(Animator animation) {
mQsSizeChangeAnimator = null;
+ mQsContainer.setHeightOverride(-1);
}
});
mQsSizeChangeAnimator.start();
@@ -558,6 +629,14 @@ public class NotificationPanelView extends PanelView implements
MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
return true;
}
+ if (mQsPanel.isOnSettingsPage() && isInQsArea(event.getX(), event.getY(), false)
+ && mQsExpanded) {
+ mIntercepting = false;
+ // we explicitly do not intercept the touch event here to let the qs settings page
+ // scroll as necessary while not blocking horizontal swipes and allowing the panel
+ // to be collapsed when grabbed below the qs settings page as well.
+ return false;
+ }
if (!isFullyCollapsed() && onQsIntercept(event)) {
return true;
}
@@ -716,6 +795,11 @@ public class NotificationPanelView extends PanelView implements
if (mBlockTouches) {
return false;
}
+ if (mDoubleTapToSleepEnabled
+ && mStatusBarState == StatusBarState.KEYGUARD
+ && event.getY() < mStatusBarHeaderHeight) {
+ mDoubleTapGesture.onTouchEvent(event);
+ }
initDownStates(event);
if (mListenForHeadsUp && !mHeadsUpTouchHelper.isTrackingHeadsUp()
&& mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
@@ -786,9 +870,14 @@ public class NotificationPanelView extends PanelView implements
}
private boolean isInQsArea(float x, float y) {
+ return isInQsArea(x, y, true);
+ }
+
+ private boolean isInQsArea(float x, float y, boolean includeNotifications) {
return (x >= mScrollView.getX() && x <= mScrollView.getX() + mScrollView.getWidth()) &&
- (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
- || y <= mQsContainer.getY() + mQsContainer.getHeight());
+ ((includeNotifications
+ && y <= mNotificationStackScroller.getBottomMostNotificationBottom())
+ || y <= mQsContainer.getY() + mQsContainer.getHeight());
}
private boolean isOpenQsEvent(MotionEvent event) {
@@ -806,7 +895,22 @@ public class NotificationPanelView extends PanelView implements
&& (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
|| event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
- return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag;
+ final float w = getMeasuredWidth();
+ final float x = event.getX();
+ float region = (w * (1.f/4.f)); // TODO overlay region fraction?
+ boolean showQsOverride = false;
+
+ switch (mOneFingerQuickSettingsIntercept) {
+ case 1: // Right side pulldown
+ showQsOverride = isLayoutRtl() ? (x < region) : (w - region < x);
+ break;
+ case 2: // Left side pulldown
+ showQsOverride = isLayoutRtl() ? (w - region < x) : (x < region);
+ break;
+ }
+ showQsOverride &= mStatusBarState == StatusBarState.SHADE;
+
+ return twoFingerDrag || showQsOverride || stylusButtonClickDrag || mouseButtonClickDrag;
}
private void handleQsDown(MotionEvent event) {
@@ -1012,8 +1116,26 @@ public class NotificationPanelView extends PanelView implements
mAfforanceHelper.updatePreviews();
}
}
- if (keyguardShowing) {
+ if (statusBarState == StatusBarState.KEYGUARD ||
+ statusBarState == StatusBarState.SHADE_LOCKED) {
updateDozingVisibilities(false /* animate */);
+ if (mThirdPartyKeyguardViewComponent != null) {
+ if (mKeyguardExternalView == null) {
+ mKeyguardExternalView =
+ getExternalKeyguardView(mThirdPartyKeyguardViewComponent);
+ if (mKeyguardExternalView != null) {
+ mKeyguardExternalView.registerKeyguardExternalViewCallback(
+ mExternalKeyguardViewCallbacks);
+ }
+ }
+ if (mKeyguardExternalView != null && !mKeyguardExternalView.isAttachedToWindow()) {
+ addView(mKeyguardExternalView, 0, EXTERNAL_KEYGUARD_VIEW_PARAMS);
+ }
+ }
+ } else {
+ if (mKeyguardExternalView != null && mKeyguardExternalView.isAttachedToWindow()) {
+ removeView(mKeyguardExternalView);
+ }
}
resetVerticalPanelPosition();
updateQsState();
@@ -1091,6 +1213,82 @@ public class NotificationPanelView extends PanelView implements
}
};
+ private KeyguardExternalView.KeyguardExternalViewCallbacks mExternalKeyguardViewCallbacks =
+ new KeyguardExternalView.KeyguardExternalViewCallbacks() {
+ @Override
+ public boolean requestDismiss() {
+ if (hasExternalKeyguardView()) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mStatusBar.showKeyguard();
+ mStatusBar.showBouncer();
+ }
+ });
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean requestDismissAndStartActivity(final Intent intent) {
+ if (hasExternalKeyguardView()) {
+ if (hasExternalKeyguardView()) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mStatusBar.showKeyguard();
+ mStatusBar.startActivityDismissingKeyguard(intent, false, true, true,
+ null);
+ }
+ });
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void collapseNotificationPanel() {
+ if (mStatusBar.getBarState() == StatusBarState.KEYGUARD && hasExternalKeyguardView() &&
+ mKeyguardExternalView.isInteractive()) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mStatusBar.focusKeyguardExternalView();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void providerDied() {
+ mKeyguardExternalView.unregisterKeyguardExternalViewCallback(
+ mExternalKeyguardViewCallbacks);
+ mKeyguardExternalView = null;
+ }
+ };
+
+ private BroadcastReceiver mExternalKeyguardViewChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String pkgName = getSendingPackage(intent);
+ if (pkgName != null) {
+ PackageManager pm = context.getPackageManager();
+ if (pm.checkPermission(android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
+ pkgName) != PackageManager.PERMISSION_GRANTED) {
+ // we should not be here if the sending app does not have the proper permission,
+ // so do nothing and return.
+ return;
+ }
+ } else {
+ // null package name? something is not right so just return and skip doing anything
+ return;
+ }
+ updateExternalKeyguardView();
+ }
+ };
+
private void animateHeaderSlidingIn() {
// If the QS is already expanded we don't need to slide in the header as it's already
// visible.
@@ -1469,6 +1667,7 @@ public class NotificationPanelView extends PanelView implements
View header = mKeyguardShowing ? mKeyguardStatusBar : mHeader;
boolean onHeader = x >= header.getX() && x <= header.getX() + header.getWidth()
&& y >= header.getTop() && y <= header.getBottom();
+
if (mQsExpanded) {
return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y);
} else {
@@ -1732,6 +1931,7 @@ public class NotificationPanelView extends PanelView implements
* mKeyguardStatusBarAnimateAlpha);
mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f
&& !mDozing ? VISIBLE : INVISIBLE);
+ mStatusBar.getVisualizer().setAlpha(mKeyguardStatusBar.getAlpha());
}
private void updateHeaderKeyguard() {
@@ -1802,7 +2002,6 @@ public class NotificationPanelView extends PanelView implements
private void setListening(boolean listening) {
mHeader.setListening(listening);
- mKeyguardStatusBar.setListening(listening);
mQsPanel.setListening(listening);
}
@@ -2025,13 +2224,9 @@ public class NotificationPanelView extends PanelView implements
});
rightIcon = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon : rightIcon;
if (rightIcon) {
- mStatusBar.onCameraHintStarted();
+ mStatusBar.onCameraHintStarted(mKeyguardBottomArea.getRightHint());
} else {
- if (mKeyguardBottomArea.isLeftVoiceAssist()) {
- mStatusBar.onVoiceAssistHintStarted();
- } else {
- mStatusBar.onPhoneHintStarted();
- }
+ mStatusBar.onLeftHintStarted(mKeyguardBottomArea.getLeftHint());
}
}
@@ -2200,6 +2395,11 @@ public class NotificationPanelView extends PanelView implements
// Hide "No notifications" in QS.
mNotificationStackScroller.updateEmptyShadeView(mShadeEmpty && !mQsExpanded);
+ if (mStatusBarState == StatusBarState.KEYGUARD
+ && (!mQsExpanded || mQsExpandImmediate || mIsExpanding
+ && mQsExpandedWhenExpandingStarted)) {
+ positionClockAndNotifications();
+ }
}
public void setQsScrimEnabled(boolean qsScrimEnabled) {
@@ -2342,7 +2542,7 @@ public class NotificationPanelView extends PanelView implements
* @param x the x-coordinate the touch event
*/
private void updateVerticalPanelPosition(float x) {
- if (mNotificationStackScroller.getWidth() * 1.75f > getWidth()) {
+ if (mNotificationStackScroller.getWidth() * 1.75f >= getWidth()) {
resetVerticalPanelPosition();
return;
}
@@ -2384,6 +2584,53 @@ public class NotificationPanelView extends PanelView implements
return mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway;
}
+ class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN), false, this);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE), false, this);
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED), false, this);
+ update();
+ }
+
+ void unobserve() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update();
+ }
+
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mOneFingerQuickSettingsIntercept = CMSettings.System.getInt(
+ resolver, CMSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN, 1);
+ mDoubleTapToSleepEnabled = CMSettings.System.getInt(
+ resolver, CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE, 1) == 1;
+
+ boolean liveLockScreenEnabled = CMSettings.Secure.getInt(
+ resolver, CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED, 0) == 1;
+ if (liveLockScreenEnabled != mLiveLockScreenEnabled) {
+ mLiveLockScreenEnabled = liveLockScreenEnabled;
+ updateExternalKeyguardView();
+ }
+ }
+ }
+
@Override
public boolean hasOverlappingRendering() {
return !mDozing;
@@ -2451,4 +2698,49 @@ public class NotificationPanelView extends PanelView implements
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
}
+
+ public boolean hasExternalKeyguardView() {
+ return mKeyguardExternalView != null && mKeyguardExternalView.isAttachedToWindow();
+ }
+
+ public boolean isExternalKeyguardViewInteractive() {
+ return mKeyguardExternalView != null && mKeyguardExternalView.isInteractive();
+ }
+
+ public KeyguardExternalView getExternalKeyguardView() {
+ return mKeyguardExternalView;
+ }
+
+ private KeyguardExternalView getExternalKeyguardView(ComponentName componentName) {
+ try {
+ return new KeyguardExternalView(getContext(), null, componentName);
+ } catch (Exception e) {
+ // just return null below and move on
+ }
+ return null;
+ }
+
+ private void updateExternalKeyguardView() {
+ ComponentName cn = mLiveLockScreenEnabled ?
+ mLockPatternUtils.getThirdPartyKeyguardComponent() : null;
+ // If mThirdPartyKeyguardViewComponent differs from cn, go ahead and update
+ if (!Objects.equals(mThirdPartyKeyguardViewComponent, cn)) {
+ mThirdPartyKeyguardViewComponent = cn;
+ if (mKeyguardExternalView != null) {
+ if (indexOfChild(mKeyguardExternalView) >= 0) {
+ removeView(mKeyguardExternalView);
+ }
+ mKeyguardExternalView.unregisterKeyguardExternalViewCallback(
+ mExternalKeyguardViewCallbacks);
+ if (mThirdPartyKeyguardViewComponent != null) {
+ mKeyguardExternalView =
+ getExternalKeyguardView(mThirdPartyKeyguardViewComponent);
+ mKeyguardExternalView.registerKeyguardExternalViewCallback(
+ mExternalKeyguardViewCallbacks);
+ } else {
+ mKeyguardExternalView = null;
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index e1a400d..82b1e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -146,6 +146,16 @@ public abstract class PanelBar extends FrameLayout {
return result;
}
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ for (PanelView pv : mPanels) {
+ pv.setBar(null);
+ }
+ mPanels.clear();
+ mPanelHolder.setBar(null);
+ }
+
// called from PanelView when self-expanding, too
public void startOpeningPanel(PanelView panel) {
if (DEBUG) LOG("startOpeningPanel: " + panel);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e03bcfb..e5711b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
@@ -26,6 +27,7 @@ import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.view.animation.AnimationUtils;
@@ -86,6 +88,20 @@ public abstract class PanelView extends FrameLayout {
private VelocityTrackerInterface mVelocityTracker;
private FlingAnimationUtils mFlingAnimationUtils;
+ private boolean mUpdateExpandOnLayout;
+ private View.OnLayoutChangeListener mLayoutChangeListener = new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ // update expand height
+ if (mHeightAnimator != null && mExpanding && mUpdateExpandOnLayout) {
+ final int maxPanelHeight = getMaxPanelHeight();
+ final PropertyValuesHolder[] values = mHeightAnimator.getValues();
+ values[0].setFloatValues(maxPanelHeight);
+ }
+ }
+ };
+
/**
* Whether an instant expand request is currently pending and we are just waiting for layout.
*/
@@ -122,6 +138,18 @@ public abstract class PanelView extends FrameLayout {
}
};
+ private ViewTreeObserver.OnGlobalLayoutListener mInstantExpandLayoutListener =
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (mStatusBar.getStatusBarWindow().getHeight() != mStatusBar.getStatusBarHeight()) {
+ getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ setExpandedFraction(1f);
+ mInstantExpanding = false;
+ }
+ }
+ };
+
protected void onExpandingFinished() {
mBar.onExpandingFinished();
}
@@ -623,7 +651,7 @@ public abstract class PanelView extends FrameLayout {
flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
}
- protected void flingToHeight(float vel, boolean expand, float target,
+ protected void flingToHeight(float vel, final boolean expand, float target,
float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
// Hack to make the expand transition look nice when clear all button is visible - we make
// the animation only to the last notification, and then jump to the maximum panel height so
@@ -644,6 +672,7 @@ public abstract class PanelView extends FrameLayout {
if (expandBecauseOfFalsing) {
vel = 0;
}
+ mUpdateExpandOnLayout = isFullyCollapsed();
mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
if (expandBecauseOfFalsing) {
animator.setDuration(350);
@@ -659,16 +688,23 @@ public abstract class PanelView extends FrameLayout {
/ collapseSpeedUpFactor));
}
}
+
animator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@Override
+ public void onAnimationStart(Animator animation) {
+ if (expand) PanelView.this.addOnLayoutChangeListener(mLayoutChangeListener);
+ }
+
+ @Override
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
+ if (expand) PanelView.this.removeOnLayoutChangeListener(mLayoutChangeListener);
if (clearAllExpandHack && !mCancelled) {
setExpandedHeightInternal(getMaxPanelHeight());
}
@@ -874,18 +910,7 @@ public abstract class PanelView extends FrameLayout {
// Wait for window manager to pickup the change, so we know the maximum height of the panel
// then.
- getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- if (mStatusBar.getStatusBarWindow().getHeight()
- != mStatusBar.getStatusBarHeight()) {
- getViewTreeObserver().removeOnGlobalLayoutListener(this);
- setExpandedFraction(1f);
- mInstantExpanding = false;
- }
- }
- });
+ getViewTreeObserver().addOnGlobalLayoutListener(mInstantExpandLayoutListener);
// Make sure a layout really happens.
requestLayout();
@@ -894,6 +919,7 @@ public abstract class PanelView extends FrameLayout {
public void instantCollapse() {
abortAnimations();
setExpandedFraction(0f);
+ getViewTreeObserver().removeOnGlobalLayoutListener(mInstantExpandLayoutListener);
if (mExpanding) {
notifyExpandingFinished();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 73361bd..c5e74a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -17,22 +17,32 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.settings.BrightnessController.BRIGHTNESS_ADJ_RESOLUTION;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
import android.app.IActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.StatusBarManager;
+import android.app.WallpaperManager;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.content.res.ThemeConfig;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -54,10 +64,12 @@ import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.AsyncTask;
+import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.IPowerManager;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
@@ -75,15 +87,21 @@ import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Pair;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.WindowManagerGlobal;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewStub;
+import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
@@ -92,28 +110,36 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.cm.ActionUtils;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
+import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.DemoMode;
+import com.android.systemui.DockBatteryMeterView;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.cm.UserContentObserver;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.qs.QSDragPanel;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSTile;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.settings.BrightnessController;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -130,14 +156,17 @@ import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.SpeedBumpView;
+import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.VisualizerView;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+import com.android.systemui.statusbar.policy.BatteryStateRegistar.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.DockBatteryController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HotspotControllerImpl;
@@ -145,19 +174,25 @@ import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
+import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
+import com.android.systemui.statusbar.policy.SuControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.WeatherControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.StackViewState;
import com.android.systemui.volume.VolumeComponent;
+import cyanogenmod.app.CMContextConstants;
+import cyanogenmod.app.CustomTileListenerService;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -183,6 +218,9 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCE
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
+import cyanogenmod.providers.CMSettings;
+import cyanogenmod.themes.IThemeService;
+
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
HeadsUpManager.OnHeadsUpChangedListener {
@@ -231,6 +269,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
+ private static final float BRIGHTNESS_CONTROL_PADDING = 0.15f;
+ private static final int BRIGHTNESS_CONTROL_LONG_PRESS_TIMEOUT = 750; // ms
+ private static final int BRIGHTNESS_CONTROL_LINGER_THRESHOLD = 20;
+
public static final int FADE_KEYGUARD_START_DELAY = 100;
public static final int FADE_KEYGUARD_DURATION = 300;
public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
@@ -258,7 +300,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// These are no longer handled by the policy, because we need custom strategies for them
BluetoothControllerImpl mBluetoothController;
SecurityControllerImpl mSecurityController;
+ BatteryManager mBatteryManager;
BatteryController mBatteryController;
+ DockBatteryController mDockBatteryController;
LocationControllerImpl mLocationController;
NetworkControllerImpl mNetworkController;
HotspotControllerImpl mHotspotController;
@@ -274,6 +318,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
KeyguardMonitor mKeyguardMonitor;
BrightnessMirrorController mBrightnessMirrorController;
AccessibilityController mAccessibilityController;
+ WeatherControllerImpl mWeatherController;
+ SuControllerImpl mSuController;
FingerprintUnlockController mFingerprintUnlockController;
int mNaturalBarHeight = -1;
@@ -282,6 +328,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Point mCurrentDisplaySize = new Point();
StatusBarWindowView mStatusBarWindow;
+ FrameLayout mStatusBarWindowContent;
PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
private StatusBarWindowManager mStatusBarWindowManager;
@@ -290,6 +337,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private boolean mWakeUpComingFromTouch;
private PointF mWakeUpTouchLocation;
private boolean mScreenTurningOn;
+ private BatteryMeterView mBatteryView;
+ private BatteryLevelTextView mBatteryTextView;
int mPixelFormat;
Object mQueueLock = new Object();
@@ -302,7 +351,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
TextView mNotificationPanelDebugText;
// settings
- private QSPanel mQSPanel;
+ private QSDragPanel mQSPanel;
+ private QSTileHost mQSTileHost;
+ private DevForceNavbarObserver mDevForceNavbarObserver;
// top bar
StatusBarHeaderView mHeader;
@@ -316,15 +367,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private boolean mKeyguardGoingAway;
// Keyguard is actually fading away now.
private boolean mKeyguardFadingAway;
+ private boolean mKeyguardShowingMedia;
private long mKeyguardFadingAwayDelay;
private long mKeyguardFadingAwayDuration;
+ private Bitmap mKeyguardWallpaper;
+
int mKeyguardMaxNotificationCount;
boolean mExpandedVisible;
private int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
+ private int mStatusBarHeaderHeight;
+
// the tracker view
int mTrackingPosition; // the position of the top of the tracking view.
@@ -335,6 +391,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
int[] mAbsPos = new int[2];
ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
+ private boolean mAutomaticBrightness;
+ private boolean mBrightnessControl;
+ private boolean mBrightnessChanged;
+ private float mScreenWidth;
+ private int mMinBrightness;
+ private boolean mJustPeeked;
+ int mLinger;
+ int mInitialTouchX;
+ int mInitialTouchY;
+
+ private boolean mRecreating = false;
+
// for disabling the status bar
int mDisabled1 = 0;
int mDisabled2 = 0;
@@ -357,6 +425,123 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private int mNavigationIconHints = 0;
private HandlerThread mHandlerThread;
+ private IThemeService mThemeService;
+ private long mLastThemeChangeTime = 0;
+
+ Runnable mLongPressBrightnessChange = new Runnable() {
+ @Override
+ public void run() {
+ mStatusBarView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ adjustBrightness(mInitialTouchX);
+ mLinger = BRIGHTNESS_CONTROL_LINGER_THRESHOLD + 1;
+ }
+ };
+
+ // Custom Recents Long Press
+ // - Tracks Event state for custom (user-configurable) Long Presses.
+ private boolean mCustomRecentsLongPressed = false;
+ // - The ArrayList is updated when packages are added and removed.
+ private List<ComponentName> mCustomRecentsLongPressHandlerCandidates = new ArrayList<>();
+ // - The custom Recents Long Press, if selected. When null, use default (switch last app).
+ private ComponentName mCustomRecentsLongPressHandler = null;
+
+ class SettingsObserver extends UserContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_BRIGHTNESS_CONTROL), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.SCREEN_BRIGHTNESS_MODE), false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE), false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.Secure.RECENTS_LONG_PRESS_ACTIVITY), false, this);
+ update();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ int mode = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
+ UserHandle.USER_CURRENT);
+ mAutomaticBrightness = mode != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
+ mBrightnessControl = CMSettings.System.getIntForUser(
+ resolver, CMSettings.System.STATUS_BAR_BRIGHTNESS_CONTROL, 0,
+ UserHandle.USER_CURRENT) == 1;
+
+ if (mNavigationBarView != null) {
+ boolean navLeftInLandscape = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE, 0, UserHandle.USER_CURRENT) == 1;
+ mNavigationBarView.setLeftInLandscape(navLeftInLandscape);
+ }
+
+ // This method reads CMSettings.Secure.RECENTS_LONG_PRESS_ACTIVITY
+ updateCustomRecentsLongPressHandler(false);
+ }
+ }
+
+ class DevForceNavbarObserver extends UserContentObserver {
+ DevForceNavbarObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR), false, this, UserHandle.USER_ALL);
+ }
+
+ @Override
+ public void update() {
+ boolean visible = CMSettings.Secure.getIntForUser(mContext.getContentResolver(),
+ CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1;
+
+ if (visible) {
+ forceAddNavigationBar();
+ } else {
+ removeNavigationBar();
+ }
+
+ // Send a broadcast to Settings to update Key disabling when user changes
+ Intent intent = new Intent("com.cyanogenmod.action.UserChanged");
+ intent.setPackage("com.android.settings");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
+ }
+
+ private void forceAddNavigationBar() {
+ // If we have no Navbar view and we should have one, create it
+ if (mNavigationBarView != null) {
+ return;
+ }
+
+ mNavigationBarView =
+ (NavigationBarView) View.inflate(mContext, R.layout.navigation_bar, null);
+
+ mNavigationBarView.setDisabledFlags(mDisabled1);
+ mNavigationBarView.setBar(this);
+ addNavigationBar();
+ }
+
// ensure quick settings is disabled until the current user makes it through the setup wizard
private boolean mUserSetup = false;
private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
@@ -438,6 +623,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
private PorterDuffXfermode mSrcOverXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
+ private VisualizerView mVisualizerView;
+ private boolean mScreenOn;
+
private MediaSessionManager mMediaSessionManager;
private MediaController mMediaController;
private String mMediaNotificationKey;
@@ -453,6 +641,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
clearCurrentMediaNotification();
updateMediaMetaData(true);
}
+ mVisualizerView.setPlaying(state.getState() == PlaybackState.STATE_PLAYING);
}
}
@@ -611,6 +800,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mScrimSrcModeEnabled = mContext.getResources().getBoolean(
R.bool.config_status_bar_scrim_behind_use_src);
+ ThemeConfig currentTheme = mContext.getResources().getConfiguration().themeConfig;
+ if (currentTheme != null) {
+ mCurrentTheme = (ThemeConfig)currentTheme.clone();
+ } else {
+ mCurrentTheme = ThemeConfig.getBootTheme(mContext.getContentResolver());
+ }
+
+ mStatusBarWindow = new StatusBarWindowView(mContext, null);
+ mStatusBarWindow.setService(this);
+
super.start(); // calls createAndAddWindows()
mMediaSessionManager
@@ -620,9 +819,23 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
addNavigationBar();
+ // Developer options - Force Navigation bar
+ try {
+ boolean needsNav = mWindowManagerService.needsNavigationBar();
+ if (!needsNav) {
+ mDevForceNavbarObserver = new DevForceNavbarObserver(mHandler);
+ mDevForceNavbarObserver.observe();
+ }
+ } catch (RemoteException ex) {
+ // no window manager? good luck with that
+ }
+
+ SettingsObserver observer = new SettingsObserver(mHandler);
+ observer.observe();
+
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController,
- mUserInfoController, mBluetoothController);
+ mUserInfoController, mBluetoothController, mSuController);
mIconPolicy.setCurrentUserSetup(mUserSetup);
mSettingsObserver.onChange(false); // set up
@@ -635,6 +848,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
mHeadsUpObserver);
}
+
+ WallpaperManager wallpaperManager = (WallpaperManager) mContext.getSystemService(
+ Context.WALLPAPER_SERVICE);
+ mKeyguardWallpaper = wallpaperManager.getKeyguardBitmap();
+
mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
mUnlockMethodCache.addListener(this);
startKeyguard();
@@ -649,6 +867,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
notifyUserAboutHiddenNotifications();
mScreenPinningRequest = new ScreenPinningRequest(mContext);
+
+ updateCustomRecentsLongPressHandler(true);
+
+ mThemeService = IThemeService.Stub.asInterface(ServiceManager.getService(
+ CMContextConstants.CM_THEME_SERVICE));
}
// ================================================================================
@@ -659,13 +882,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Resources res = context.getResources();
+ mScreenWidth = (float) context.getResources().getDisplayMetrics().widthPixels;
+ mMinBrightness = context.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDim);
+
updateDisplaySize(); // populates mDisplayMetrics
- updateResources();
+ updateResources(null);
- mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
+ mStatusBarWindowContent = (FrameLayout) View.inflate(context,
R.layout.super_status_bar, null);
mStatusBarWindow.setService(this);
- mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
+ mStatusBarWindowContent.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event);
@@ -674,17 +901,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
animateCollapsePanels();
}
}
- return mStatusBarWindow.onTouchEvent(event);
+ return mStatusBarWindowContent.onTouchEvent(event);
}
});
- mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
+ mStatusBarView = (PhoneStatusBarView) mStatusBarWindowContent.findViewById(R.id.status_bar);
mStatusBarView.setBar(this);
- PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
+ PanelHolder holder = (PanelHolder) mStatusBarWindowContent.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
- mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
+ mNotificationPanel = (NotificationPanelView) mStatusBarWindowContent.findViewById(
R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
@@ -694,7 +921,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
R.color.notification_panel_solid_background)));
}
- mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
+ if (mHeadsUpManager == null) {
+ mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
+ }
mHeadsUpManager.setBar(this);
mHeadsUpManager.addListener(this);
mHeadsUpManager.addListener(mNotificationPanel);
@@ -710,9 +939,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
- if (showNav) {
+ if (showNav && !mRecreating) {
mNavigationBarView =
(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
+ mNavigationBarView.updateResources(getNavbarThemedResources());
mNavigationBarView.setDisabledFlags(mDisabled1);
mNavigationBarView.setBar(this);
@@ -737,12 +967,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// no window manager? good luck with that
}
- mAssistManager = new AssistManager(this, context);
+ if (mAssistManager == null) {
+ mAssistManager = new AssistManager(this, context);
+ }
+ if (mNavigationBarView == null) {
+ mAssistManager.onConfigurationChanged();
+ }
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
- mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
+ mStackScroller = (NotificationStackScrollLayout) mStatusBarWindowContent.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setPhoneStatusBar(this);
@@ -775,13 +1010,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStackScroller.setDismissView(mDismissView);
mExpandedContents = mStackScroller;
- mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
+ mBackdrop = (BackDropView) mStatusBarWindowContent.findViewById(R.id.backdrop);
mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
- ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
- ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
- View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
+ FrameLayout scrimView = (FrameLayout) mStatusBarWindowContent.findViewById(R.id.scrimview);
+ ScrimView scrimBehind = (ScrimView) scrimView.findViewById(R.id.scrim_behind);
+ ScrimView scrimInFront =
+ (ScrimView) mStatusBarWindowContent.findViewById(R.id.scrim_in_front);
+ View headsUpScrim = mStatusBarWindowContent.findViewById(R.id.heads_up_scrim);
mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim,
mScrimSrcModeEnabled);
mHeadsUpManager.addListener(mScrimController);
@@ -789,18 +1026,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mScrimController.setBackDropView(mBackdrop);
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context);
+ mVisualizerView = (VisualizerView) scrimView.findViewById(R.id.visualizerview);
- mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
+ mHeader = (StatusBarHeaderView) mStatusBarWindowContent.findViewById(R.id.header);
mHeader.setActivityStarter(this);
- mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
- mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindowContent.findViewById(R.id.keyguard_header);
+ mKeyguardStatusView = mStatusBarWindowContent.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
- (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+ (KeyguardBottomAreaView) mStatusBarWindowContent.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
- (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
- R.id.keyguard_indication_text),
+ (KeyguardIndicationTextView) mStatusBarWindowContent.findViewById(
+ R.id.keyguard_indication_text),
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
@@ -815,35 +1053,74 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mHandlerThread.start();
// Other icons
- mLocationController = new LocationControllerImpl(mContext,
- mHandlerThread.getLooper()); // will post a notification
- mBatteryController = new BatteryController(mContext);
- mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
- @Override
- public void onPowerSaveChanged() {
- mHandler.post(mCheckBarModes);
- if (mDozeServiceHost != null) {
- mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
+ if (mLocationController == null) {
+ mLocationController = new LocationControllerImpl(mContext,
+ mHandlerThread.getLooper()); // will post a notification
+ }
+ if (mBatteryManager == null) {
+ mBatteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE);
+ }
+ if (mBatteryController == null) {
+ mBatteryController = new BatteryController(mContext, mHandler);
+ mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
+ @Override
+ public void onPowerSaveChanged() {
+ mHandler.post(mCheckBarModes);
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
+ }
}
+
+ @Override
+ public void onBatteryLevelChanged(boolean present, int level,
+ boolean pluggedIn, boolean charging) {
+ // noop
+ }
+
+ @Override
+ public void onBatteryStyleChanged(int style, int percentMode) {
+ // noop
+ }
+ });
+ }
+ if (mBatteryManager.isDockBatterySupported()) {
+ if (mDockBatteryController == null) {
+ mDockBatteryController = new DockBatteryController(mContext, mHandler);
}
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- // noop
- }
- });
- mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
- mHotspotController = new HotspotControllerImpl(mContext);
- mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());
- mSecurityController = new SecurityControllerImpl(mContext);
+ }
+ if (mNetworkController == null) {
+ mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
+ }
+ if (mHotspotController == null) {
+ mHotspotController = new HotspotControllerImpl(mContext);
+ }
+ if (mBluetoothController == null) {
+ mBluetoothController = new BluetoothControllerImpl(mContext,
+ mHandlerThread.getLooper());
+ }
+ if (mSecurityController == null) {
+ mSecurityController = new SecurityControllerImpl(mContext);
+ }
if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
- mRotationLockController = new RotationLockControllerImpl(mContext);
+ if (mRotationLockController == null) {
+ mRotationLockController = new RotationLockControllerImpl(mContext);
+ }
+ }
+ if (mUserInfoController == null) {
+ mUserInfoController = new UserInfoController(mContext);
}
- mUserInfoController = new UserInfoController(mContext);
mVolumeComponent = getComponent(VolumeComponent.class);
if (mVolumeComponent != null) {
- mZenModeController = mVolumeComponent.getZenController();
+ if (mZenModeController == null) {
+ mZenModeController = mVolumeComponent.getZenController();
+ }
+ }
+ if (mCastController == null) {
+ mCastController = new CastControllerImpl(mContext);
+ }
+ if (mSuController == null) {
+ mSuController = new SuControllerImpl(mContext);
}
- mCastController = new CastControllerImpl(mContext);
final SignalClusterView signalCluster =
(SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
final SignalClusterView signalClusterKeyguard =
@@ -864,45 +1141,143 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mNetworkController.addEmergencyListener(mHeader);
}
- mFlashlightController = new FlashlightController(mContext);
+ if (mFlashlightController == null) {
+ mFlashlightController = new FlashlightController(mContext);
+ }
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
mKeyguardBottomArea.setPhoneStatusBar(this);
mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
- mAccessibilityController = new AccessibilityController(mContext);
+ if (mAccessibilityController == null) {
+ mAccessibilityController = new AccessibilityController(mContext);
+ }
mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
- mNextAlarmController = new NextAlarmController(mContext);
- mKeyguardMonitor = new KeyguardMonitor(mContext);
+ if (mNextAlarmController == null) {
+ mNextAlarmController = new NextAlarmController(mContext);
+ }
+ if (mKeyguardMonitor == null) {
+ mKeyguardMonitor = new KeyguardMonitor(mContext);
+ }
if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
- mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
- mHandler);
+ if (mUserSwitcherController == null) {
+ mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
+ mHandler);
+ }
+ }
+ if (mWeatherController == null) {
+ mWeatherController = new WeatherControllerImpl(mContext);
}
+
mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
- (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
+ (ViewStub) mStatusBarWindowContent.findViewById(R.id.keyguard_user_switcher),
mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController);
// Set up the quick settings tile panel
- mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
+ mQSPanel = (QSDragPanel) mStatusBarWindowContent.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
- final QSTileHost qsh = new QSTileHost(mContext, this,
- mBluetoothController, mLocationController, mRotationLockController,
- mNetworkController, mZenModeController, mHotspotController,
- mCastController, mFlashlightController,
- mUserSwitcherController, mKeyguardMonitor,
- mSecurityController);
- mQSPanel.setHost(qsh);
- mQSPanel.setTiles(qsh.getTiles());
- mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
+ if (mQSTileHost == null) {
+ mQSTileHost = new QSTileHost(mContext, this,
+ mBluetoothController, mLocationController, mRotationLockController,
+ mNetworkController, mZenModeController, mHotspotController,
+ mCastController, mFlashlightController,
+ mUserSwitcherController, mKeyguardMonitor,
+ mSecurityController);
+ }
+ mQSPanel.setHost(mQSTileHost);
+ if (mBrightnessMirrorController == null) {
+ mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindowContent);
+ }
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+ mQSPanel.setTiles(mQSTileHost.getTiles());
mHeader.setQSPanel(mQSPanel);
- qsh.setCallback(new QSTileHost.Callback() {
+ mQSTileHost.setCallback(new QSTileHost.Callback() {
@Override
public void onTilesChanged() {
- mQSPanel.setTiles(qsh.getTiles());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mQSPanel.setTiles(mQSTileHost.getTiles());
+ }
+ });
+ }
+
+ @Override
+ public void setEditing(final boolean editing) {
+ if (mState != StatusBarState.SHADE) {
+ return;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mQSPanel.setEditing(editing);
+ mHeader.setEditing(editing);
+ }
+ });
+ }
+
+ @Override
+ public boolean isEditing() {
+ return mQSPanel.isEditing();
+ }
+
+ @Override
+ public void goToSettingsPage() {
+ if (mState != StatusBarState.SHADE) {
+ return;
+ }
+ setEditing(true);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mQSPanel.goToSettingsPage();
+ }
+ }, 500);
+ }
+
+ @Override
+ public void resetTiles() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mQSPanel.setEditing(false);
+ mHeader.setEditing(false);
+
+ // unregister custom tile service while we reset to not get
+ // callbacks from custom tiles
+ try {
+ mCustomTileListenerService.unregisterAsSystemService();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to unregister custom tile listener", e);
+ }
+
+ mQSTileHost.resetTiles();
+
+ // reregister service
+ try {
+ mCustomTileListenerService.registerAsSystemService(mContext,
+ new ComponentName(mContext.getPackageName(),
+ PhoneStatusBar.this.getClass().getCanonicalName()),
+ UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to register custom tile listener", e);
+ }
+ }
+ });
}
});
}
+ // Set up the initial custom tile listener state.
+ try {
+ mCustomTileListenerService.registerAsSystemService(mContext,
+ new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
+ UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to register custom tile listener", e);
+ }
+
+ mQSPanel.getHost().setCustomTileListenerService(mCustomTileListenerService);
+
// User info. Trigger first load.
mHeader.setUserInfoController(mUserInfoController);
mKeyguardStatusBar.setUserInfoController(mUserInfoController);
@@ -910,10 +1285,39 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mUserInfoController.reloadUserInfo();
mHeader.setBatteryController(mBatteryController);
- ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
- mBatteryController);
+
+ BatteryMeterView batteryMeterView =
+ ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery));
+ batteryMeterView.setBatteryStateRegistar(mBatteryController);
+ batteryMeterView.setBatteryController(mBatteryController);
+ batteryMeterView.setAnimationsEnabled(false);
+ ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.battery_level_text))
+ .setBatteryStateRegistar(mBatteryController);
mKeyguardStatusBar.setBatteryController(mBatteryController);
+ mHeader.setDockBatteryController(mDockBatteryController);
+ mKeyguardStatusBar.setDockBatteryController(mDockBatteryController);
+ if (mDockBatteryController != null) {
+ DockBatteryMeterView dockBatteryMeterView =
+ ((DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery));
+ dockBatteryMeterView.setBatteryStateRegistar(mDockBatteryController);
+ ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text))
+ .setBatteryStateRegistar(mDockBatteryController);
+ } else {
+ DockBatteryMeterView dockBatteryMeterView =
+ (DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery);
+ if (dockBatteryMeterView != null) {
+ mStatusBarView.removeView(dockBatteryMeterView);
+ }
+ BatteryLevelTextView dockBatteryLevel =
+ (BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text);
+ if (dockBatteryLevel != null) {
+ mStatusBarView.removeView(dockBatteryLevel);
+ }
+ }
+
+ mVisualizerView.setKeyguardMonitor(mKeyguardMonitor);
mHeader.setNextAlarmController(mNextAlarmController);
+ mHeader.setWeatherController(mWeatherController);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastReceiver.onReceive(mContext,
@@ -927,6 +1331,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED);
+ filter.addAction(cyanogenmod.content.Intent.ACTION_SCREEN_CAMERA_GESTURE);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
IntentFilter demoFilter = new IntentFilter();
@@ -937,6 +1343,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
android.Manifest.permission.DUMP, null);
+ // receive broadcasts for packages
+ IntentFilter packageFilter = new IntentFilter();
+ packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ packageFilter.addDataScheme("package");
+ context.registerReceiver(mPackageBroadcastReceiver, packageFilter);
+
// listen for USER_SETUP_COMPLETE setting (per-user)
resetUserSetupObserver();
@@ -1062,6 +1477,41 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mNaturalBarHeight;
}
+ private final CustomTileListenerService mCustomTileListenerService =
+ new CustomTileListenerService() {
+ @Override
+ public void onListenerConnected() {
+ //Connected
+ }
+ @Override
+ public void onCustomTilePosted(final StatusBarPanelCustomTile sbc) {
+ if (DEBUG) Log.d(TAG, "onCustomTilePosted: " + sbc.getCustomTile());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ boolean isUpdate = mQSPanel.getHost().getCustomTileData()
+ .get(sbc.getKey()) != null;
+ if (isUpdate) {
+ mQSPanel.getHost().updateCustomTile(sbc);
+ } else {
+ mQSPanel.getHost().addCustomTile(sbc);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onCustomTileRemoved(final StatusBarPanelCustomTile sbc) {
+ if (DEBUG) Log.d(TAG, "onCustomTileRemoved: " + sbc.getCustomTile());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mQSPanel.getHost().removeCustomTileSysUi(sbc.getKey());
+ }
+ });
+ }
+ };
+
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
public void onClick(View v) {
awakenDreams();
@@ -1121,14 +1571,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
- mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
- mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
- mNavigationBarView.getRecentsButton().setLongClickable(true);
- mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
- mNavigationBarView.getBackButton().setLongClickable(true);
- mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
- mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
- mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener);
+ mNavigationBarView.setListeners(mRecentsClickListener, mRecentsPreloadOnTouchListener,
+ mLongPressBackRecentsListener, mHomeActionListener, mLongPressHomeListener);
mAssistManager.onConfigurationChanged();
}
@@ -1137,11 +1581,26 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
if (mNavigationBarView == null) return;
+ ThemeConfig newTheme = mContext.getResources().getConfiguration().themeConfig;
+ if (newTheme != null &&
+ (mCurrentTheme == null || !mCurrentTheme.equals(newTheme))) {
+ // Nevermind, this will be re-created
+ return;
+ }
+
prepareNavigationBarView();
mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
}
+ private void removeNavigationBar() {
+ if (DEBUG) Log.d(TAG, "removeNavigationBar: about to remove " + mNavigationBarView);
+ if (mNavigationBarView == null) return;
+
+ mWindowManager.removeView(mNavigationBarView);
+ mNavigationBarView = null;
+ }
+
private void repositionNavigationBar() {
if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return;
@@ -1176,6 +1635,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return lp;
}
+ private Resources getNavbarThemedResources() {
+ String pkgName = mCurrentTheme.getOverlayForNavBar();
+ Resources res = null;
+ try {
+ res = mContext.getPackageManager().getThemedResourcesForApplication(
+ mContext.getPackageName(), pkgName);
+ } catch (PackageManager.NameNotFoundException e) {
+ res = mContext.getResources();
+ }
+ return res;
+ }
+
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
mIconController.addSystemIcon(slot, index, viewIndex, icon);
}
@@ -1272,6 +1743,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mNavigationBarView != null) {
mNavigationBarView.setLayoutDirection(layoutDirection);
}
+ mIconController.refreshAllStatusBarIcons();
}
private void updateNotificationShade() {
@@ -1699,18 +2171,47 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
+ " state=" + mState);
}
- Bitmap artworkBitmap = null;
+ Bitmap backdropBitmap = null;
+
+ // apply any album artwork first
if (mMediaMetadata != null) {
- artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
- if (artworkBitmap == null) {
- artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+ backdropBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
+ if (backdropBitmap == null) {
+ backdropBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
// might still be null
}
}
- final boolean hasArtwork = artworkBitmap != null;
+ // HACK: Consider keyguard as visible if showing sim pin security screen
+ KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ boolean keyguardVisible = mState != StatusBarState.SHADE || updateMonitor.isSimPinSecure();
+
+ if (!mKeyguardFadingAway && keyguardVisible && backdropBitmap != null && mScreenOn) {
+ // if there's album art, ensure visualizer is visible
+ mVisualizerView.setVisible(true);
+ mVisualizerView.setPlaying(mMediaController != null
+ && mMediaController.getPlaybackState() != null
+ && mMediaController.getPlaybackState().getState()
+ == PlaybackState.STATE_PLAYING);
+ }
+
+ // apply user lockscreen image
+ if (backdropBitmap == null && !mNotificationPanel.hasExternalKeyguardView()) {
+ backdropBitmap = mKeyguardWallpaper;
+ }
+
+ if (keyguardVisible) {
+ // always use current backdrop to color eq
+ mVisualizerView.setBitmap(backdropBitmap);
+ }
- if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
+ final boolean hasBackdrop = backdropBitmap != null;
+ mKeyguardShowingMedia = hasBackdrop;
+ if (mStatusBarWindowManager != null) {
+ mStatusBarWindowManager.setShowingMedia(mKeyguardShowingMedia);
+ }
+
+ if ((hasBackdrop || DEBUG_MEDIA_FAKE_ARTWORK)
&& (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
&& mFingerprintUnlockController.getMode()
!= FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
@@ -1743,7 +2244,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mBackdropBack.setBackgroundColor(0xFFFFFFFF);
mBackdropBack.setImageDrawable(new ColorDrawable(c));
} else {
- mBackdropBack.setImageBitmap(artworkBitmap);
+ mBackdropBack.setImageBitmap(backdropBitmap);
}
if (mScrimSrcModeEnabled) {
mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode);
@@ -1947,6 +2448,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mLeaveOpenOnKeyguardHide;
}
+ public boolean isKeyguardShowingMedia() {
+ return mKeyguardShowingMedia;
+ }
+
public boolean isQsExpanded() {
return mNotificationPanel.isQsExpanded();
}
@@ -1955,6 +2460,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mWakeUpComingFromTouch;
}
+ void setBlur(float b){
+ mStatusBarWindowManager.setBlur(b);
+ }
+
public boolean isFalsingThresholdNeeded() {
return getBarState() == StatusBarState.KEYGUARD;
}
@@ -2295,6 +2804,98 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ private void adjustBrightness(int x) {
+ mBrightnessChanged = true;
+ float raw = ((float) x) / mScreenWidth;
+
+ // Add a padding to the brightness control on both sides to
+ // make it easier to reach min/max brightness
+ float padded = Math.min(1.0f - BRIGHTNESS_CONTROL_PADDING,
+ Math.max(BRIGHTNESS_CONTROL_PADDING, raw));
+ float value = (padded - BRIGHTNESS_CONTROL_PADDING) /
+ (1 - (2.0f * BRIGHTNESS_CONTROL_PADDING));
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ if (power != null) {
+ if (mAutomaticBrightness) {
+ float adj = (2 * value) - 1;
+ adj = Math.max(adj, -1);
+ adj = Math.min(adj, 1);
+ final float val = adj;
+ power.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(val);
+ AsyncTask.execute(new Runnable() {
+ public void run() {
+ Settings.System.putFloatForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, val,
+ UserHandle.USER_CURRENT);
+ }
+ });
+ } else {
+ int newBrightness = mMinBrightness + (int) Math.round(value *
+ (android.os.PowerManager.BRIGHTNESS_ON - mMinBrightness));
+ newBrightness = Math.min(newBrightness, android.os.PowerManager.BRIGHTNESS_ON);
+ newBrightness = Math.max(newBrightness, mMinBrightness);
+ final int val = newBrightness;
+ power.setTemporaryScreenBrightnessSettingOverride(val);
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, val,
+ UserHandle.USER_CURRENT);
+ }
+ });
+ }
+
+
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Setting Brightness failed: " + e);
+ }
+ }
+
+ private void brightnessControl(MotionEvent event) {
+ final int action = event.getAction();
+ final int x = (int) event.getRawX();
+ final int y = (int) event.getRawY();
+ if (action == MotionEvent.ACTION_DOWN) {
+ if (y < mStatusBarHeaderHeight) {
+ mLinger = 0;
+ mInitialTouchX = x;
+ mInitialTouchY = y;
+ mJustPeeked = true;
+ mHandler.removeCallbacks(mLongPressBrightnessChange);
+ mHandler.postDelayed(mLongPressBrightnessChange,
+ BRIGHTNESS_CONTROL_LONG_PRESS_TIMEOUT);
+ }
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ if (y < mStatusBarHeaderHeight && mJustPeeked) {
+ if (mLinger > BRIGHTNESS_CONTROL_LINGER_THRESHOLD) {
+ adjustBrightness(x);
+ } else {
+ final int xDiff = Math.abs(x - mInitialTouchX);
+ final int yDiff = Math.abs(y - mInitialTouchY);
+ final int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ if (xDiff > yDiff) {
+ mLinger++;
+ }
+ if (xDiff > touchSlop || yDiff > touchSlop) {
+ mHandler.removeCallbacks(mLongPressBrightnessChange);
+ }
+ }
+ } else {
+ if (y > mStatusBarHeaderHeight) {
+ mJustPeeked = false;
+ }
+ mHandler.removeCallbacks(mLongPressBrightnessChange);
+ }
+ } else if (action == MotionEvent.ACTION_UP
+ || action == MotionEvent.ACTION_CANCEL) {
+ mHandler.removeCallbacks(mLongPressBrightnessChange);
+ }
+ }
+
public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -2321,16 +2922,29 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mGestureRec.add(event);
}
+ if (mBrightnessControl) {
+ brightnessControl(event);
+ if ((mDisabled1 & StatusBarManager.DISABLE_EXPAND) != 0) {
+ return true;
+ }
+ }
+
+ final boolean upOrCancel =
+ event.getAction() == MotionEvent.ACTION_UP ||
+ event.getAction() == MotionEvent.ACTION_CANCEL;
if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
- final boolean upOrCancel =
- event.getAction() == MotionEvent.ACTION_UP ||
- event.getAction() == MotionEvent.ACTION_CANCEL;
if (upOrCancel && !mExpandedVisible) {
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
} else {
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
}
}
+ if (mBrightnessChanged && upOrCancel) {
+ mBrightnessChanged = false;
+ if (mJustPeeked && mExpandedVisible) {
+ mNotificationPanel.fling(10, false);
+ }
+ }
return false;
}
@@ -2771,6 +3385,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mBatteryController != null) {
mBatteryController.dump(fd, pw, args);
}
+ if (mDockBatteryController != null) {
+ mDockBatteryController.dump(fd, pw, args);
+ }
if (mNextAlarmController != null) {
mNextAlarmController.dump(fd, pw, args);
}
@@ -2813,7 +3430,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void addStatusBarWindow() {
makeStatusBarView();
- mStatusBarWindowManager = new StatusBarWindowManager(mContext);
+ mStatusBarWindow.addContent(mStatusBarWindowContent);
+ mStatusBarWindowManager = new StatusBarWindowManager(mContext, mKeyguardMonitor);
+ mStatusBarWindowManager.setShowingMedia(mKeyguardShowingMedia);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
@@ -2838,10 +3457,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
final boolean dismissShade, final Callback callback) {
- if (onlyProvisioned && !isDeviceProvisioned()) return;
-
final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, mCurrentUserId);
+ startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, afterKeyguardGone,
+ callback);
+ }
+
+ public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+ final boolean dismissShade, final boolean afterKeyguardGone, final Callback callback) {
+ if (onlyProvisioned && !isDeviceProvisioned()) return;
+
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Runnable runnable = new Runnable() {
public void run() {
@@ -2924,13 +3549,31 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ mScreenOn = false;
notifyNavigationBarScreenOn(false);
notifyHeadsUpScreenOff();
finishBarAnimations();
resetUserExpandedStates();
}
else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+ mScreenOn = true;
notifyNavigationBarScreenOn(true);
+ } else if (Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED.equals(action)) {
+ WallpaperManager wm = (WallpaperManager) mContext.getSystemService(
+ Context.WALLPAPER_SERVICE);
+ mKeyguardWallpaper = wm.getKeyguardBitmap();
+ updateMediaMetaData(true);
+ } else if (cyanogenmod.content.Intent.ACTION_SCREEN_CAMERA_GESTURE.equals(action)) {
+ boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
+ if (!userSetupComplete) {
+ if (DEBUG) Log.d(TAG, String.format(
+ "userSetupComplete = %s, ignoring camera launch gesture.",
+ userSetupComplete));
+ return;
+ }
+
+ onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE);
}
}
};
@@ -2955,6 +3598,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (DEBUG_MEDIA_FAKE_ARTWORK) {
updateMediaMetaData(true);
}
+ } else if (Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED.equals(action)) {
+ WallpaperManager wm = (WallpaperManager) mContext.getSystemService(
+ Context.WALLPAPER_SERVICE);
+ mKeyguardWallpaper = wm.getKeyguardBitmap();
+ updateMediaMetaData(true);
+ }
+ }
+ };
+
+ private BroadcastReceiver mPackageBroadcastReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.v(TAG, "onReceive: " + intent);
+ String action = intent.getAction();
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
+ Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
+ Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action) ||
+ Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ updateCustomRecentsLongPressHandler(true);
}
}
};
@@ -2995,7 +3656,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
updateDisplaySize(); // populates mDisplayMetrics
- updateResources();
+ updateResources(newConfig);
repositionNavigationBar();
updateRowStates();
mIconController.updateResources();
@@ -3007,12 +3668,23 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void userSwitched(int newUserId) {
super.userSwitched(newUserId);
if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
+ WallpaperManager wm = (WallpaperManager)
+ mContext.getSystemService(Context.WALLPAPER_SERVICE);
+ mKeyguardWallpaper = null;
+ wm.forgetLoadedKeyguardWallpaper();
+
animateCollapsePanels();
updatePublicMode();
updateNotifications();
resetUserSetupObserver();
setControllerUsers();
mAssistManager.onUserSwitched(newUserId);
+
+ mKeyguardWallpaper = wm.getKeyguardBitmap();
+ updateMediaMetaData(true);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.updateSettings();
+ }
}
private void setControllerUsers() {
@@ -3022,6 +3694,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mSecurityController != null) {
mSecurityController.onUserSwitched(mCurrentUserId);
}
+ if (mBatteryController != null) {
+ mBatteryController.setUserId(mCurrentUserId);
+ }
+ if (mDockBatteryController != null) {
+ mDockBatteryController.setUserId(mCurrentUserId);
+ }
}
private void resetUserSetupObserver() {
@@ -3032,6 +3710,154 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mUserSetupObserver, mCurrentUserId);
}
+ private static void copyNotifications(ArrayList<Pair<String, StatusBarNotification>> dest,
+ NotificationData source) {
+ int N = source.size();
+ for (int i = 0; i < N; i++) {
+ NotificationData.Entry entry = source.get(i);
+ dest.add(Pair.create(entry.key, entry.notification));
+ }
+ }
+
+ private void removeSignalCallbacks(NetworkController networkController) {
+ final SignalClusterView signalCluster =
+ (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
+ final SignalClusterView signalClusterKeyguard =
+ (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
+ final SignalClusterView signalClusterQs =
+ (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
+ networkController.removeSignalCallback(signalCluster);
+ networkController.removeSignalCallback(signalClusterKeyguard);
+ networkController.removeSignalCallback(signalClusterQs);
+
+ if (signalCluster != null) signalCluster.setSecurityController(null);
+ if (signalClusterKeyguard != null) signalClusterKeyguard.setSecurityController(null);
+ if (signalClusterQs != null) signalClusterQs.setSecurityController(null);
+ }
+
+ private void recreateStatusBar() {
+ mRecreating = true;
+
+ if (mNetworkController != null) {
+ removeSignalCallbacks(mNetworkController);
+ if (mNetworkController.hasVoiceCallingFeature()) {
+ mNetworkController.removeEmergencyListener(mHeader);
+ }
+ }
+ if (mHeadsUpManager != null) {
+ mHeadsUpManager.removeListener(mNotificationPanel);
+ mHeadsUpManager.removeListener(mScrimController);
+ }
+ if (mIconController != null) {
+ mIconController.cleanup();
+ }
+ if (mKeyguardIndicationController != null) {
+ mKeyguardIndicationController.cleanup();
+ }
+
+ mStatusBarWindow.removeContent(mStatusBarWindowContent);
+ mStatusBarWindow.clearDisappearingChildren();
+
+ // extract icons from the soon-to-be recreated viewgroup.
+ ViewGroup statusIcons = mIconController.getStatusIcons();
+ int nIcons = statusIcons != null ? statusIcons.getChildCount() : 0;
+ ArrayList<StatusBarIcon> icons = new ArrayList<StatusBarIcon>(nIcons);
+ ArrayList<String> iconSlots = new ArrayList<String>(nIcons);
+ for (int i = 0; i < nIcons; i++) {
+ StatusBarIconView iconView = (StatusBarIconView) statusIcons.getChildAt(i);
+ icons.add(iconView.getStatusBarIcon());
+ iconSlots.add(iconView.getStatusBarSlot());
+ }
+
+ removeAllViews(mStatusBarWindowContent);
+
+ // extract notifications.
+ RankingMap rankingMap = mNotificationData.getRankingMap();
+ int nNotifs = mNotificationData.size();
+ ArrayList<Pair<String, StatusBarNotification>> notifications = new ArrayList<>(nNotifs);
+ copyNotifications(notifications, mNotificationData);
+ // now remove all the notifications since we'll be re-creating these with the copied data
+ mNotificationData.clear();
+
+ if (mCustomTileListenerService != null) {
+ try {
+ mCustomTileListenerService.unregisterAsSystemService();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to unregister custom tile listener", e);
+ }
+ }
+
+ mQSPanel.getHost().setCustomTileListenerService(null);
+ mQSPanel.setListening(false);
+
+ makeStatusBarView();
+ repositionNavigationBar();
+
+ // re-add status icons
+ for (int i = 0; i < nIcons; i++) {
+ StatusBarIcon icon = icons.get(i);
+ String slot = iconSlots.get(i);
+ addIcon(slot, i, i, icon);
+ }
+
+ // recreate notifications.
+ for (int i = 0; i < nNotifs; i++) {
+ Pair<String, StatusBarNotification> notifData = notifications.get(i);
+ addNotificationViews(createNotificationViews(notifData.second), rankingMap);
+ }
+ mNotificationData.filterAndSort();
+
+ setAreThereNotifications();
+
+ mStatusBarWindow.addContent(mStatusBarWindowContent);
+
+ checkBarModes();
+
+ // Stop the command queue until the new status bar container settles and has a layout pass
+ mCommandQueue.pause();
+
+ // fix notification panel being shifted to the left by calling
+ // instantCollapseNotificationPanel()
+ instantCollapseNotificationPanel();
+
+ mStatusBarWindow.requestLayout();
+ mStatusBarWindow.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ mStatusBarWindow.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ mCommandQueue.resume();
+ mRecreating = false;
+ }
+ });
+ // restart the keyguard so it picks up the newly created ScrimController
+ startKeyguard();
+
+ // if the keyguard was showing while this change occurred we'll need to do some extra work
+ if (mState == StatusBarState.KEYGUARD) {
+ // this will make sure the keyguard is showing
+ showKeyguard();
+ }
+
+ // update mLastThemeChangeTime
+ try {
+ mLastThemeChangeTime = mThemeService.getLastThemeChangeTime();
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ }
+
+ private void removeAllViews(ViewGroup parent) {
+ int N = parent.getChildCount();
+ for (int i = 0; i < N; i++) {
+ View child = parent.getChildAt(i);
+ if (child instanceof ViewGroup) {
+ removeAllViews((ViewGroup) child);
+ }
+ }
+ parent.removeAllViews();
+ }
+
/**
* Reload some of our resources when the configuration changes.
*
@@ -3039,7 +3865,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
* should, but getting that smooth is tough. Someday we'll fix that. In the
* meantime, just update the things that we know change.
*/
- void updateResources() {
+ void updateResources(Configuration newConfig) {
+ // detect theme change.
+ ThemeConfig newTheme = newConfig != null ? newConfig.themeConfig : null;
+ final boolean updateStatusBar = shouldUpdateStatusbar(mCurrentTheme, newTheme);
+ final boolean updateNavBar = shouldUpdateNavbar(mCurrentTheme, newTheme);
+ if (newTheme != null) mCurrentTheme = (ThemeConfig) newTheme.clone();
+ if (updateStatusBar) {
+ recreateStatusBar();
+ } else {
+ loadDimens();
+ }
+
// Update the quick setting tiles
if (mQSPanel != null) {
mQSPanel.updateResources();
@@ -3053,6 +3890,66 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mBrightnessMirrorController != null) {
mBrightnessMirrorController.updateResources();
}
+
+ if (mNavigationBarView != null && updateNavBar) {
+ mNavigationBarView.updateResources(getNavbarThemedResources());
+ }
+ }
+
+ /**
+ * Determines if we need to recreate the status bar due to a theme change. We currently
+ * check if the overlay for the status bar, fonts, or icons, or last theme change time is
+ * greater than mLastThemeChangeTime
+ *
+ * @param oldTheme
+ * @param newTheme
+ * @return True if we should recreate the status bar
+ */
+ private boolean shouldUpdateStatusbar(ThemeConfig oldTheme, ThemeConfig newTheme) {
+ // no newTheme, so no need to update status bar
+ if (newTheme == null) return false;
+
+ final String overlay = newTheme.getOverlayForStatusBar();
+ final String icons = newTheme.getIconPackPkgName();
+ final String fonts = newTheme.getFontPkgName();
+ boolean isNewThemeChange = false;
+ try {
+ isNewThemeChange = mLastThemeChangeTime < mThemeService.getLastThemeChangeTime();
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+
+ return oldTheme == null ||
+ (overlay != null && !overlay.equals(oldTheme.getOverlayForStatusBar()) ||
+ (fonts != null && !fonts.equals(oldTheme.getFontPkgName())) ||
+ (icons != null && !icons.equals(oldTheme.getIconPackPkgName())) ||
+ isNewThemeChange);
+ }
+
+ /**
+ * Determines if we need to update the navbar resources due to a theme change. We currently
+ * check if the overlay for the navbar, or last theme change time is greater than
+ * mLastThemeChangeTime
+ *
+ * @param oldTheme
+ * @param newTheme
+ * @return True if we should update the navbar
+ */
+ private boolean shouldUpdateNavbar(ThemeConfig oldTheme, ThemeConfig newTheme) {
+ // no newTheme, so no need to update navbar
+ if (newTheme == null) return false;
+
+ final String overlay = newTheme.getOverlayForNavBar();
+ boolean isNewThemeChange = false;
+ try {
+ isNewThemeChange = mLastThemeChangeTime < mThemeService.getLastThemeChangeTime();
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+
+ return oldTheme == null ||
+ (overlay != null && !overlay.equals(oldTheme.getOverlayForNavBar()) ||
+ isNewThemeChange);
}
protected void loadDimens() {
@@ -3066,6 +3963,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardMaxNotificationCount = res.getInteger(R.integer.keyguard_max_notification_count);
+ mStatusBarHeaderHeight = res.getDimensionPixelSize(R.dimen.status_bar_header_height);
+
if (DEBUG) Log.v(TAG, "updateResources");
}
@@ -3207,7 +4106,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public boolean shouldDisableNavbarGestures() {
- return !isDeviceProvisioned() || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0;
+ return !isDeviceProvisioned() || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0
+ || (mNavigationBarView != null && mNavigationBarView.isInEditMode());
}
public void postStartActivityDismissingKeyguard(final PendingIntent intent) {
@@ -3327,6 +4227,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
if (modeChange || command.equals(COMMAND_BATTERY)) {
dispatchDemoCommandToView(command, args, R.id.battery);
+ dispatchDemoCommandToView(command, args, R.id.dock_battery);
}
if (modeChange || command.equals(COMMAND_STATUS)) {
mIconController.dispatchDemoCommand(command, args);
@@ -3407,6 +4308,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mDraggedDownRow = null;
}
mAssistManager.onLockscreenShown();
+ if (mNotificationPanel.hasExternalKeyguardView()) {
+ mNotificationPanel.getExternalKeyguardView().onKeyguardShowing(
+ mStatusBarKeyguardViewManager.isScreenTurnedOn());
+ }
}
private void onLaunchTransitionFadingEnded() {
@@ -3557,6 +4462,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mNotificationPanel.onAffordanceLaunchEnded();
mNotificationPanel.animate().cancel();
mNotificationPanel.setAlpha(1f);
+ if ( mNotificationPanel.getExternalKeyguardView() != null) {
+ mNotificationPanel.getExternalKeyguardView().onKeyguardDismissed();
+ }
return staying;
}
@@ -3566,6 +4474,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ boolean isSecure() {
+ return mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isSecure();
+ }
+
public long calculateGoingToFullShadeDelay() {
return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
}
@@ -3598,6 +4510,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
- StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */);
+ mVisualizerView.setVisible(false);
}
public boolean isKeyguardFadingAway() {
@@ -3662,12 +4575,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mDozeScrimController.setDozing(mDozing &&
mFingerprintUnlockController.getMode()
!= FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, animate);
+ mVisualizerView.setDozing(mDozing);
}
public void updateStackScrollerState(boolean goingToFullShade) {
if (mStackScroller == null) return;
boolean onKeyguard = mState == StatusBarState.KEYGUARD;
- mStackScroller.setHideSensitive(isLockscreenPublicMode(), goingToFullShade);
+ mStackScroller.setHideSensitive(isLockscreenPublicMode()
+ || (!userAllowsPrivateNotificationsInPublic(mCurrentUserId) && onKeyguard),
+ goingToFullShade);
mStackScroller.setDimmed(onKeyguard, false /* animate */);
mStackScroller.setExpandingEnabled(!onKeyguard);
ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild();
@@ -3726,13 +4642,30 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return false;
}
- private void showBouncer() {
- if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+ protected void showBouncer() {
+ if (!mRecreating &&
+ (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
mWaitingForKeyguardExit = mStatusBarKeyguardViewManager.isShowing();
mStatusBarKeyguardViewManager.dismiss();
}
}
+ protected void showBouncerOrFocusKeyguardExternalView() {
+ if (mNotificationPanel.hasExternalKeyguardView() && !isKeyguardShowingMedia() &&
+ mNotificationPanel.isExternalKeyguardViewInteractive()) {
+ focusKeyguardExternalView();
+ } else {
+ showBouncer();
+ }
+ }
+
+ protected void focusKeyguardExternalView() {
+ mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/,
+ 1.0f /* speedUpFactor */);
+ mStatusBarKeyguardViewManager.setKeyguardExternalViewFocus(true);
+ setBarState(StatusBarState.SHADE);
+ }
+
private void instantExpandNotificationsPanel() {
// Make our window larger and the panel expanded.
@@ -3800,23 +4733,23 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
}
- public void onCameraHintStarted() {
- mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
+ public void onCameraHintStarted(String hint) {
+ mKeyguardIndicationController.showTransientIndication(hint);
}
- public void onVoiceAssistHintStarted() {
- mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
- }
-
- public void onPhoneHintStarted() {
- mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
+ public void onLeftHintStarted(String hint) {
+ mKeyguardIndicationController.showTransientIndication(hint);
}
public void onTrackingStopped(boolean expand) {
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
- if (!expand && !mUnlockMethodCache.canSkipBouncer()) {
- showBouncer();
+ if (!expand && (!mUnlockMethodCache.canSkipBouncer() ||
+ mNotificationPanel.hasExternalKeyguardView())) {
+ showBouncerOrFocusKeyguardExternalView();
}
+ } else if (expand && mStatusBarWindowManager.keyguardExternalViewHasFocus()) {
+ mStatusBarKeyguardViewManager.setKeyguardExternalViewFocus(false);
+ setBarState(StatusBarState.KEYGUARD);
}
}
@@ -3938,6 +4871,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mWakeUpTouchLocation = null;
mStackScroller.setAnimationsEnabled(false);
updateVisibleToUser();
+ mVisualizerView.setVisible(false);
+ if (mQSTileHost.isEditing()) {
+ mQSTileHost.setEditing(false);
+ }
if (mLaunchCameraOnFinishedGoingToSleep) {
mLaunchCameraOnFinishedGoingToSleep = false;
@@ -3970,12 +4907,22 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void vibrateForCameraGesture() {
// Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
- mVibrator.vibrate(new long[] { 0, 750L }, -1 /* repeat */);
+ mVibrator.vibrate(new long[] { 0, 250L }, -1 /* repeat */);
}
public void onScreenTurnedOn() {
mScreenTurningOn = false;
mDozeScrimController.onScreenTurnedOn();
+ mVisualizerView.setVisible(true);
+ if (mNotificationPanel.hasExternalKeyguardView()) {
+ mNotificationPanel.getExternalKeyguardView().onScreenTurnedOn();
+ }
+ }
+
+ public void onScreenTurnedOff() {
+ if (mNotificationPanel.hasExternalKeyguardView()) {
+ mNotificationPanel.getExternalKeyguardView().onScreenTurnedOff();
+ }
}
/**
@@ -3994,6 +4941,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void handleLongPressBackRecents(View v) {
try {
boolean sendBackLongPress = false;
+ boolean hijackRecentsLongPress = false;
IActivityManager activityManager = ActivityManagerNative.getDefault();
boolean isAccessiblityEnabled = mAccessibilityManager.isEnabled();
if (activityManager.isInLockTaskMode() && !isAccessiblityEnabled) {
@@ -4004,17 +4952,23 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
activityManager.stopLockTaskModeOnCurrent();
// When exiting refresh disabled flags.
mNavigationBarView.setDisabledFlags(mDisabled1, true);
- } else if ((v.getId() == R.id.back)
+ } else if (NavbarEditor.NAVBAR_BACK.equals(v.getTag())
&& !mNavigationBarView.getRecentsButton().isPressed()) {
// If we aren't pressing recents right now then they presses
// won't be together, so send the standard long-press action.
sendBackLongPress = true;
+ } else if (NavbarEditor.NAVBAR_RECENT.equals(v.getTag())
+ && !activityManager.isInLockTaskMode()) {
+ hijackRecentsLongPress = true;
}
mLastLockToAppLongPress = time;
} else {
// If this is back still need to handle sending the long-press event.
- if (v.getId() == R.id.back) {
+ if (NavbarEditor.NAVBAR_BACK.equals(v.getTag())) {
sendBackLongPress = true;
+ } else if (NavbarEditor.NAVBAR_RECENT.equals(v.getTag())
+ && !activityManager.isInLockTaskMode()) {
+ hijackRecentsLongPress = true;
} else if (isAccessiblityEnabled && activityManager.isInLockTaskMode()) {
// When in accessibility mode a long press that is recents (not back)
// should stop lock task.
@@ -4028,11 +4982,201 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
}
+
+ if (hijackRecentsLongPress) {
+ // If there is a user-selected, registered handler for the
+ // recents long press, start the Intent. Otherwise,
+ // perform the default action, which is last app switching.
+
+ // Copy it so the value doesn't change between now and when the activity is started.
+ ComponentName customRecentsLongPressHandler = mCustomRecentsLongPressHandler;
+ if (customRecentsLongPressHandler != null) {
+ startCustomRecentsLongPressActivity(customRecentsLongPressHandler);
+ } else {
+ ActionUtils.switchToLastApp(mContext, mCurrentUserId);
+ }
+ }
} catch (RemoteException e) {
Log.d(TAG, "Unable to reach activity manager", e);
}
}
+ protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+
+ // Handle Document switcher
+ // Additional optimization when we have software system buttons - start loading the recent
+ // tasks on touch down
+ if (action == MotionEvent.ACTION_DOWN) {
+ preloadRecents();
+ } else if (action == MotionEvent.ACTION_CANCEL) {
+ cancelPreloadingRecents();
+ } else if (action == MotionEvent.ACTION_UP) {
+ if (!v.isPressed()) {
+ cancelPreloadingRecents();
+ }
+ }
+
+ // Handle custom recents long press
+ if (action == MotionEvent.ACTION_CANCEL ||
+ action == MotionEvent.ACTION_UP) {
+ cleanupCustomRecentsLongPressHandler();
+ }
+ return false;
+ }
+ };
+
+ /**
+ * If a custom Recents Long Press activity was dispatched, then the certain
+ * handlers need to be cleaned up after the event ends.
+ */
+ private void cleanupCustomRecentsLongPressHandler() {
+ if (mCustomRecentsLongPressed) {
+ mNavigationBarView.setSlippery(false);
+ }
+ mCustomRecentsLongPressed = false;
+ }
+
+ /**
+ * An ACTION_RECENTS_LONG_PRESS intent was received, and a custom handler is
+ * set and points to a valid app. Start this activity.
+ */
+ private void startCustomRecentsLongPressActivity(ComponentName customComponentName) {
+ Intent intent = new Intent(cyanogenmod.content.Intent.ACTION_RECENTS_LONG_PRESS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ // Include the package name of the app currently in the foreground
+ IActivityManager am = ActivityManagerNative.getDefault();
+ List<ActivityManager.RecentTaskInfo> recentTasks = null;
+ try {
+ recentTasks = am.getRecentTasks(
+ 1, ActivityManager.RECENT_WITH_EXCLUDED, UserHandle.myUserId());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot get recent tasks", e);
+ }
+ if (recentTasks != null && recentTasks.size() > 0) {
+ String pkgName = recentTasks.get(0).baseIntent.getComponent().getPackageName();
+ intent.putExtra(Intent.EXTRA_CURRENT_PACKAGE_NAME, pkgName);
+ }
+
+ intent.setComponent(customComponentName);
+ try {
+ // Allow the touch event to continue into the new activity.
+ mNavigationBarView.setSlippery(true);
+ mCustomRecentsLongPressed = true;
+
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Cannot start activity", e);
+
+ // If the activity failed to launch, clean up
+ cleanupCustomRecentsLongPressHandler();
+ }
+ }
+
+ /**
+ * Get component name for the recent long press setting. Null means default switch to last app.
+ *
+ * Note: every time packages changed, the setting must be re-evaluated. This is to check that the
+ * component was not uninstalled or disabled.
+ */
+ private void updateCustomRecentsLongPressHandler(boolean scanPackages) {
+ // scanPackages should be true when the PhoneStatusBar is starting for
+ // the first time, and when any package activity occurred.
+ if (scanPackages) {
+ updateCustomRecentsLongPressCandidates();
+ }
+
+ String componentString = CMSettings.Secure.getString(mContext.getContentResolver(),
+ CMSettings.Secure.RECENTS_LONG_PRESS_ACTIVITY);
+ if (componentString == null) {
+ mCustomRecentsLongPressHandler = null;
+ return;
+ }
+
+ ComponentName customComponentName = ComponentName.unflattenFromString(componentString);
+ synchronized (mCustomRecentsLongPressHandlerCandidates) {
+ for (ComponentName candidate : mCustomRecentsLongPressHandlerCandidates) {
+ if (candidate.equals(customComponentName)) {
+ // Found match
+ mCustomRecentsLongPressHandler = customComponentName;
+
+ return;
+ }
+ }
+
+ // Did not find match, probably because the selected application has
+ // now been uninstalled for some reason. Since user-selected app is
+ // still saved inside Settings, PhoneStatusBar should fall back to
+ // the default for now. (We will update this either when the
+ // package is reinstalled or when the user selects another Setting.)
+ mCustomRecentsLongPressHandler = null;
+ }
+ }
+
+ /**
+ * Updates the cache of Recents Long Press applications.
+ *
+ * These applications must:
+ * - handle the cyanogenmod.contentIntent.ACTION_RECENTS_LONG_PRESS
+ * (which is permissions protected); and
+ * - not be disabled by the user or the system.
+ *
+ * More than one handler can be a candidate. When the action is invoked,
+ * the user setting (stored in CMSettings.Secure) is consulted.
+ */
+ private void updateCustomRecentsLongPressCandidates() {
+ synchronized (mCustomRecentsLongPressHandlerCandidates) {
+ mCustomRecentsLongPressHandlerCandidates.clear();
+
+ PackageManager pm = mContext.getPackageManager();
+ Intent intent = new Intent(cyanogenmod.content.Intent.ACTION_RECENTS_LONG_PRESS);
+
+ // Search for all apps that can handle ACTION_RECENTS_LONG_PRESS
+ List<ResolveInfo> activities = pm.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo info : activities) {
+ // Only cache packages that are not disabled
+ int packageState = mContext.getPackageManager().getApplicationEnabledSetting(
+ info.activityInfo.packageName);
+
+ if (packageState != PackageManager.COMPONENT_ENABLED_STATE_DISABLED &&
+ packageState != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+
+ mCustomRecentsLongPressHandlerCandidates.add(
+ new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
+ }
+
+ }
+ }
+ }
+
+ private ActivityManager.RunningTaskInfo getLastTask(final ActivityManager am) {
+ final String defaultHomePackage = resolveCurrentLauncherPackage();
+ List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(5);
+
+ for (int i = 1; i < tasks.size(); i++) {
+ String packageName = tasks.get(i).topActivity.getPackageName();
+ if (!packageName.equals(defaultHomePackage)
+ && !packageName.equals(mContext.getPackageName())) {
+ return tasks.get(i);
+ }
+ }
+
+ return null;
+ }
+
+ private String resolveCurrentLauncherPackage() {
+ final Intent launcherIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME);
+ final PackageManager pm = mContext.getPackageManager();
+ final ResolveInfo launcherInfo = pm.resolveActivity(launcherIntent, 0);
+ return launcherInfo.activityInfo.packageName;
+ }
+
// Recents
@Override
@@ -4143,7 +5287,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE");
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
}
- vibrateForCameraGesture();
+ if (source != StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) {
+ vibrateForCameraGesture();
+ }
if (!mStatusBarKeyguardViewManager.isShowing()) {
startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
true /* dismissShade */);
@@ -4178,6 +5324,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
updateDozingState();
}
+ public VisualizerView getVisualizer() {
+ return mVisualizerView;
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index fa9c4bb..ed4880b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -20,18 +20,27 @@ import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
import android.app.IUserSwitchObserver;
+import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
+import android.graphics.Bitmap;
import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Binder;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.provider.Settings.Global;
import android.telecom.TelecomManager;
import android.util.Log;
@@ -46,6 +55,17 @@ import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.SuController;
+
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+import cyanogenmod.providers.CMSettings;
+
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
+
+import java.util.ArrayList;
/**
* This class contains all of the policy about which icons are installed in the status
@@ -64,6 +84,7 @@ public class PhoneStatusBarPolicy implements Callback {
private static final String SLOT_VOLUME = "volume";
private static final String SLOT_ALARM_CLOCK = "alarm_clock";
private static final String SLOT_MANAGED_PROFILE = "managed_profile";
+ private static final String SLOT_SU = "su";
private final Context mContext;
private final StatusBarManager mService;
@@ -72,6 +93,8 @@ public class PhoneStatusBarPolicy implements Callback {
private final HotspotController mHotspot;
private final AlarmManager mAlarmManager;
private final UserInfoController mUserInfoController;
+ private boolean mAlarmIconVisible;
+ private final SuController mSuController;
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
@@ -117,8 +140,15 @@ public class PhoneStatusBarPolicy implements Callback {
}
};
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ processQSChangedLocked();
+ }
+ };
+
public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot,
- UserInfoController userInfoController, BluetoothController bluetooth) {
+ UserInfoController userInfoController, BluetoothController bluetooth, SuController su) {
mContext = context;
mCast = cast;
mHotspot = hotspot;
@@ -127,6 +157,7 @@ public class PhoneStatusBarPolicy implements Callback {
mService = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mUserInfoController = userInfoController;
+ mSuController = su;
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -151,9 +182,16 @@ public class PhoneStatusBarPolicy implements Callback {
// bluetooth status
updateBluetooth();
+ //Update initial tty mode
+ updateTTYMode();
+
// Alarm clock
mService.setIcon(SLOT_ALARM_CLOCK, R.drawable.stat_sys_alarm, 0, null);
mService.setIconVisibility(SLOT_ALARM_CLOCK, false);
+ mAlarmIconObserver.onChange(true);
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.SHOW_ALARM_ICON),
+ false, mAlarmIconObserver);
// zen
mService.setIcon(SLOT_ZEN, R.drawable.stat_sys_zen_important, 0, null);
@@ -175,12 +213,33 @@ public class PhoneStatusBarPolicy implements Callback {
mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled());
mHotspot.addCallback(mHotspotCallback);
+ // su
+ mService.setIcon(SLOT_SU, R.drawable.stat_sys_su, 0, null);
+ mService.setIconVisibility(SLOT_SU, false);
+ mSuController.addCallback(mSuCallback);
+
// managed profile
mService.setIcon(SLOT_MANAGED_PROFILE, R.drawable.stat_sys_managed_profile_status, 0,
mContext.getString(R.string.accessibility_managed_profile));
mService.setIconVisibility(SLOT_MANAGED_PROFILE, false);
+
+ QSUtils.registerObserverForQSChanges(mContext, mQSListener);
}
+ private ContentObserver mAlarmIconObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ mAlarmIconVisible = CMSettings.System.getInt(mContext.getContentResolver(),
+ CMSettings.System.SHOW_ALARM_ICON, 1) == 1;
+ updateAlarm();
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ onChange(selfChange, null);
+ }
+ };
+
public void setZenMode(int zen) {
mZen = zen;
updateVolumeZen();
@@ -192,7 +251,7 @@ public class PhoneStatusBarPolicy implements Callback {
final boolean zenNone = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS;
mService.setIcon(SLOT_ALARM_CLOCK, zenNone ? R.drawable.stat_sys_alarm_dim
: R.drawable.stat_sys_alarm, 0, null);
- mService.setIconVisibility(SLOT_ALARM_CLOCK, mCurrentUserSetup && hasAlarm);
+ mService.setIconVisibility(SLOT_ALARM_CLOCK, mCurrentUserSetup && hasAlarm && mAlarmIconVisible);
}
private final void updateSimState(Intent intent) {
@@ -236,8 +295,17 @@ public class PhoneStatusBarPolicy implements Callback {
if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
zenVisible = mZen != Global.ZEN_MODE_OFF;
- zenIconId = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS
- ? R.drawable.stat_sys_dnd_total_silence : R.drawable.stat_sys_dnd;
+ switch(mZen) {
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ zenIconId = R.drawable.stat_sys_dnd_priority;
+ break;
+ case Global.ZEN_MODE_NO_INTERRUPTIONS:
+ zenIconId = R.drawable.stat_sys_dnd_total_silence;
+ break;
+ default:
+ zenIconId = R.drawable.stat_sys_dnd;
+ break;
+ }
zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
} else if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
zenVisible = true;
@@ -326,6 +394,29 @@ public class PhoneStatusBarPolicy implements Callback {
}
}
+ private boolean isWiredHeadsetOn() {
+ AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ return audioManager.isWiredHeadsetOn();
+ }
+
+ private final void updateTTYMode() {
+ int ttyMode = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF);
+ boolean enabled = ttyMode != TelecomManager.TTY_MODE_OFF;
+ if (DEBUG) Log.v(TAG, "updateTTYMode: enabled: " + enabled);
+ if (enabled && isWiredHeadsetOn()) {
+ // TTY is on
+ if (DEBUG) Log.v(TAG, "updateTTYMode: set TTY on");
+ mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0,
+ mContext.getString(R.string.accessibility_tty_enabled));
+ mService.setIconVisibility(SLOT_TTY, true);
+ } else {
+ // TTY is off
+ if (DEBUG) Log.v(TAG, "updateTTYMode: set TTY off");
+ mService.setIconVisibility(SLOT_TTY, false);
+ }
+ }
+
private void updateCast() {
boolean isCasting = false;
for (CastDevice device : mCast.getCastDevices()) {
@@ -404,6 +495,16 @@ public class PhoneStatusBarPolicy implements Callback {
}
};
+ private void updateSu() {
+ mService.setIconVisibility(SLOT_SU, mSuController.hasActiveSessions());
+ final int userId = UserHandle.myUserId();
+ if (isSuEnabledForUser(userId)) {
+ publishSuCustomTile();
+ } else {
+ unpublishSuCustomTile();
+ }
+ }
+
private final CastController.Callback mCastCallback = new CastController.Callback() {
@Override
public void onCastDevicesChanged() {
@@ -425,4 +526,118 @@ public class PhoneStatusBarPolicy implements Callback {
mCurrentUserSetup = userSetup;
updateAlarm();
}
+
+ private final SuController.Callback mSuCallback = new SuController.Callback() {
+ @Override
+ public void onSuSessionsChanged() {
+ updateSu();
+ }
+ };
+
+ private void publishSuCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = new UserHandle(userId);
+ final int icon = QSUtils.getDynamicQSTileResIconId(mContext, userId,
+ QSConstants.DYNAMIC_TILE_SU);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(mContext, userId,
+ QSConstants.DYNAMIC_TILE_SU);
+ final Context resourceContext = QSUtils.getQSTileContext(mContext, userId);
+
+ CustomTile.ListExpandedStyle style = new CustomTile.ListExpandedStyle();
+ ArrayList<CustomTile.ExpandedListItem> items = new ArrayList<>();
+ for (String pkg : mSuController.getPackageNamesWithActiveSuSessions()) {
+ CustomTile.ExpandedListItem item = new CustomTile.ExpandedListItem();
+ int appIconIdentifier = getActiveSuApkDrawableId(pkg);
+ if (appIconIdentifier != -1) {
+ item.setExpandedListItemDrawable(appIconIdentifier);
+ } else {
+ item.setExpandedListItemDrawable(icon);
+ }
+ item.setExpandedListItemTitle(getActiveSuApkLabel(pkg));
+ item.setExpandedListItemSummary(pkg);
+ item.setExpandedListItemOnClickIntent(getCustomTilePendingIntent(pkg));
+ items.add(item);
+ }
+ style.setListItems(items);
+
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(contentDesc)
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setOnSettingsClickIntent(getCustomTileSettingsIntent())
+ .setExpandedStyle(style)
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_SU,
+ PhoneStatusBarPolicy.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishSuCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_SU,
+ PhoneStatusBarPolicy.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private PendingIntent getCustomTilePendingIntent(String pkg) {
+ Intent i = new Intent(Intent.ACTION_MAIN);
+ i.setPackage(pkg);
+ i.addCategory(Intent.CATEGORY_LAUNCHER);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return PendingIntent.getActivity(mContext, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+ private Intent getCustomTileSettingsIntent() {
+ Intent i = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return i;
+ }
+
+ private String getActiveSuApkLabel(String pkg) {
+ final PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo ai = null;
+ try {
+ ai = pm.getApplicationInfo(pkg, 0);
+ } catch (final NameNotFoundException e) {
+ // Ignore
+ }
+ return (String) (ai != null ? pm.getApplicationLabel(ai) : pkg);
+ }
+
+ private int getActiveSuApkDrawableId(String pkg) {
+ final PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo ai;
+ try {
+ ai = pm.getApplicationInfo(pkg, 0);
+ } catch (final NameNotFoundException e) {
+ return -1;
+ }
+ return ai.icon;
+ }
+
+ private boolean isSuEnabledForUser(int userId) {
+ final boolean hasSuAccess = mSuController.hasActiveSessions();
+ return (userId == UserHandle.USER_OWNER) && hasSuAccess;
+ }
+
+ private void processQSChangedLocked() {
+ final int userId = UserHandle.myUserId();
+ if (isSuEnabledForUser(userId)) {
+ publishSuCustomTile();
+ } else {
+ unpublishSuCustomTile();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index fb1addf..bb3095e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -36,7 +36,10 @@ public final class PhoneStatusBarTransitions extends BarTransitions {
private Animator mCurrentAnimation;
public PhoneStatusBarTransitions(PhoneStatusBarView view) {
- super(view, R.drawable.status_background);
+ super(view, R.drawable.status_background, R.color.status_bar_background_opaque,
+ R.color.status_bar_background_semi_transparent,
+ R.color.status_bar_background_transparent,
+ com.android.internal.R.color.battery_saver_mode_color);
mView = view;
final Resources res = mView.getContext().getResources();
mIconAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index c0887ca..3b068d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -193,6 +193,7 @@ public class PhoneStatusBarView extends PanelBar {
super.panelExpansionChanged(panel, frac, expanded);
mPanelFraction = frac;
updateScrimFraction();
+ mBar.setBlur(frac);
}
private void updateScrimFraction() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index e66c63b..b776a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -16,29 +16,57 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManager;
import android.app.PendingIntent;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.logging.MetricsLogger;
+import android.widget.RemoteViews;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.tiles.AdbOverNetworkTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
+import com.android.systemui.qs.tiles.AmbientDisplayTile;
+import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
+import com.android.systemui.qs.tiles.CaffeineTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
+import com.android.systemui.qs.tiles.CompassTile;
+import com.android.systemui.qs.tiles.CustomQSTile;
import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.qs.tiles.EditTile;
import com.android.systemui.qs.tiles.FlashlightTile;
+import com.android.systemui.qs.tiles.HeadsUpTile;
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.IntentTile;
+import com.android.systemui.qs.tiles.LiveDisplayTile;
import com.android.systemui.qs.tiles.LocationTile;
+import com.android.systemui.qs.tiles.LockscreenToggleTile;
+import com.android.systemui.qs.tiles.NfcTile;
+import com.android.systemui.qs.tiles.PerfProfileTile;
+import com.android.systemui.qs.tiles.ProfilesTile;
import com.android.systemui.qs.tiles.RotationLockTile;
+import com.android.systemui.qs.tiles.ScreenTimeoutTile;
+import com.android.systemui.qs.tiles.SyncTile;
+import com.android.systemui.qs.tiles.UsbTetherTile;
+import com.android.systemui.qs.tiles.VolumeTile;
import com.android.systemui.qs.tiles.WifiTile;
+import com.android.systemui.statusbar.CustomTileData;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.FlashlightController;
@@ -53,6 +81,10 @@ import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import cyanogenmod.app.CustomTileListenerService;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import cyanogenmod.providers.CMSettings;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -65,7 +97,7 @@ public class QSTileHost implements QSTile.Host, Tunable {
private static final String TAG = "QSTileHost";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- protected static final String TILES_SETTING = "sysui_qs_tiles";
+ public static final int TILES_PER_PAGE = 8;
private final Context mContext;
private final PhoneStatusBar mStatusBar;
@@ -84,6 +116,9 @@ public class QSTileHost implements QSTile.Host, Tunable {
private final KeyguardMonitor mKeyguard;
private final SecurityController mSecurity;
+ private CustomTileData mCustomTileData;
+ private CustomTileListenerService mCustomTileListenerService;
+
private Callback mCallback;
public QSTileHost(Context context, PhoneStatusBar statusBar,
@@ -106,19 +141,35 @@ public class QSTileHost implements QSTile.Host, Tunable {
mUserSwitcherController = userSwitcher;
mKeyguard = keyguard;
mSecurity = security;
+ mCustomTileData = new CustomTileData();
final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
Process.THREAD_PRIORITY_BACKGROUND);
ht.start();
mLooper = ht.getLooper();
- TunerService.get(mContext).addTunable(this, TILES_SETTING);
+ TunerService.get(mContext).addTunableByProvider(this, CMSettings.Secure.QS_TILES, true);
}
public void destroy() {
TunerService.get(mContext).removeTunable(this);
}
+ public boolean isEditing() {
+ if (mCallback != null) {
+ return mCallback.isEditing();
+ }
+ return false;
+ }
+
+ public void setEditing(boolean editing) {
+ mCallback.setEditing(editing);
+ }
+
+ void setCustomTileListenerService(CustomTileListenerService customTileListenerService) {
+ mCustomTileListenerService = customTileListenerService;
+ }
+
@Override
public void setCallback(Callback callback) {
mCallback = callback;
@@ -129,12 +180,33 @@ public class QSTileHost implements QSTile.Host, Tunable {
return mTiles.values();
}
+ public List<String> getTileSpecs() {
+ return mTileSpecs;
+ }
+
+ public String getSpec(QSTile<?> tile) {
+ for (Map.Entry<String, QSTile<?>> entry : mTiles.entrySet()) {
+ if (entry.getValue() == tile) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
@Override
public void startActivityDismissingKeyguard(final Intent intent) {
mStatusBar.postStartActivityDismissingKeyguard(intent, 0);
}
@Override
+ public void removeCustomTile(StatusBarPanelCustomTile customTile) {
+ if (mCustomTileListenerService != null) {
+ mCustomTileListenerService.removeCustomTile(customTile.getPackage(),
+ customTile.getTag(), customTile.getId());
+ }
+ }
+
+ @Override
public void startActivityDismissingKeyguard(PendingIntent intent) {
mStatusBar.postStartActivityDismissingKeyguard(intent);
}
@@ -150,6 +222,11 @@ public class QSTileHost implements QSTile.Host, Tunable {
}
@Override
+ public RemoteViews.OnClickHandler getOnClickHandler() {
+ return mStatusBar.getOnClickHandler();
+ }
+
+ @Override
public Looper getLooper() {
return mLooper;
}
@@ -214,14 +291,14 @@ public class QSTileHost implements QSTile.Host, Tunable {
@Override
public void onTuningChanged(String key, String newValue) {
- if (!TILES_SETTING.equals(key)) {
+ if (!CMSettings.Secure.QS_TILES.equals(key)) {
return;
}
if (DEBUG) Log.d(TAG, "Recreating tiles");
final List<String> tileSpecs = loadTileSpecs(newValue);
if (tileSpecs.equals(mTileSpecs)) return;
for (Map.Entry<String, QSTile<?>> tile : mTiles.entrySet()) {
- if (!tileSpecs.contains(tile.getKey())) {
+ if (!tileSpecs.contains(tile.getKey()) && mCustomTileData.get(tile.getKey()) == null) {
if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey());
tile.getValue().destroy();
}
@@ -233,7 +310,12 @@ public class QSTileHost implements QSTile.Host, Tunable {
} else {
if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
try {
- newTiles.put(tileSpec, createTile(tileSpec));
+ if (mCustomTileData.get(tileSpec) != null) {
+ newTiles.put(tileSpec, new CustomQSTile(this,
+ mCustomTileData.get(tileSpec).sbc));
+ } else {
+ newTiles.put(tileSpec, createTile(tileSpec));
+ }
} catch (Throwable t) {
Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);
}
@@ -248,7 +330,14 @@ public class QSTileHost implements QSTile.Host, Tunable {
}
}
- protected QSTile<?> createTile(String tileSpec) {
+ @Override
+ public void goToSettingsPage() {
+ if (mCallback != null) {
+ mCallback.goToSettingsPage();
+ }
+ }
+
+ public QSTile<?> createTile(String tileSpec) {
if (tileSpec.equals("wifi")) return new WifiTile(this);
else if (tileSpec.equals("bt")) return new BluetoothTile(this);
else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
@@ -260,13 +349,30 @@ public class QSTileHost implements QSTile.Host, Tunable {
else if (tileSpec.equals("location")) return new LocationTile(this);
else if (tileSpec.equals("cast")) return new CastTile(this);
else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
+ else if (tileSpec.equals("edit")) return new EditTile(this);
+ else if (tileSpec.equals("adb_network")) return new AdbOverNetworkTile(this);
+ else if (tileSpec.equals("compass")) return new CompassTile(this);
+ else if (tileSpec.equals("nfc")) return new NfcTile(this);
+ else if (tileSpec.equals("profiles")) return new ProfilesTile(this);
+ else if (tileSpec.equals("sync")) return new SyncTile(this);
+ else if (tileSpec.equals("volume_panel")) return new VolumeTile(this);
+ else if (tileSpec.equals("usb_tether")) return new UsbTetherTile(this);
+ else if (tileSpec.equals("screen_timeout")) return new ScreenTimeoutTile(this);
+ else if (tileSpec.equals("performance")) return new PerfProfileTile(this);
+ else if (tileSpec.equals("lockscreen")) return new LockscreenToggleTile(this);
+ else if (tileSpec.equals("ambient_display")) return new AmbientDisplayTile(this);
+ else if (tileSpec.equals("live_display")) return new LiveDisplayTile(this);
+ else if (tileSpec.equals("heads_up")) return new HeadsUpTile(this);
+ else if (tileSpec.equals("battery_saver")) return new BatterySaverTile(this);
+ else if (tileSpec.equals("caffeine")) return new CaffeineTile(this);
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
else throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
}
protected List<String> loadTileSpecs(String tileList) {
final Resources res = mContext.getResources();
- final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
+ final String defaultTileList = res.getString(org.cyanogenmod.platform.internal.
+ R.string.config_defaultQuickSettingsTiles);
if (tileList == null) {
tileList = res.getString(R.string.quick_settings_tiles);
if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
@@ -287,6 +393,143 @@ public class QSTileHost implements QSTile.Host, Tunable {
tiles.add(tile);
}
}
+ // ensure edit tile is present
+ if (tiles.size() < TILES_PER_PAGE && !tiles.contains("edit")) {
+ tiles.add("edit");
+ } else if (tiles.size() > TILES_PER_PAGE && !tiles.contains("edit")) {
+ tiles.add((TILES_PER_PAGE - 1), "edit");
+ }
return tiles;
}
+
+ public void remove(String tile) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REMOVE, tile);
+ List<String> tiles = new ArrayList<>(mTileSpecs);
+ tiles.remove(tile);
+ setTiles(tiles);
+ }
+
+ public void setTiles(List<String> tiles) {
+ CMSettings.Secure.putStringForUser(getContext().getContentResolver(),
+ CMSettings.Secure.QS_TILES,
+ TextUtils.join(",", tiles), ActivityManager.getCurrentUser());
+ }
+
+ public void initiateReset() {
+ if (mCallback != null) {
+ mCallback.resetTiles();
+ }
+ }
+
+ @Override
+ public void resetTiles() {
+ CMSettings.Secure.putStringForUser(getContext().getContentResolver(),
+ CMSettings.Secure.QS_TILES, "default", ActivityManager.getCurrentUser());
+ }
+
+ public QSTile<?> getTile(String spec) {
+ return mTiles.get(spec);
+ }
+
+ public static int getLabelResource(String spec) {
+ if (spec.equals("wifi")) return R.string.quick_settings_wifi_label;
+ else if (spec.equals("bt")) return R.string.quick_settings_bluetooth_label;
+ else if (spec.equals("inversion")) return R.string.quick_settings_inversion_label;
+ else if (spec.equals("cell")) return R.string.quick_settings_cellular_detail_title;
+ else if (spec.equals("airplane")) return R.string.airplane_mode;
+ else if (spec.equals("dnd")) return R.string.quick_settings_dnd_label;
+ else if (spec.equals("rotation")) return R.string.quick_settings_rotation_locked_label;
+ else if (spec.equals("flashlight")) return R.string.quick_settings_flashlight_label;
+ else if (spec.equals("location")) return R.string.quick_settings_location_label;
+ else if (spec.equals("cast")) return R.string.quick_settings_cast_title;
+ else if (spec.equals("hotspot")) return R.string.quick_settings_hotspot_label;
+ else if (spec.equals("edit")) return R.string.quick_settings_edit_label;
+ else if (spec.equals("adb_network")) return R.string.quick_settings_network_adb_label;
+ else if (spec.equals("compass")) return R.string.quick_settings_compass_label;
+ else if (spec.equals("nfc")) return R.string.quick_settings_nfc_label;
+ else if (spec.equals("profiles")) return R.string.quick_settings_profiles;
+ else if (spec.equals("sync")) return R.string.quick_settings_sync_label;
+ else if (spec.equals("volume_panel")) return R.string.quick_settings_volume_panel_label;
+ else if (spec.equals("usb_tether")) return R.string.quick_settings_usb_tether_label;
+ else if (spec.equals("screen_timeout")) return R.string.quick_settings_screen_timeout_detail_title;
+ else if (spec.equals("performance")) return R.string.qs_tile_performance;
+ else if (spec.equals("lockscreen")) return R.string.quick_settings_lockscreen_label;
+ else if (spec.equals("ambient_display")) return R.string.quick_settings_ambient_display_label;
+ else if (spec.equals("live_display")) return R.string.live_display_title;
+ else if (spec.equals("heads_up")) return R.string.quick_settings_heads_up_label;
+ else if (spec.equals("battery_saver")) return R.string.quick_settings_battery_saver_label;
+ else if (spec.equals("caffeine")) return R.string.quick_settings_caffeine_label;
+ return 0;
+ }
+
+ public static int getIconResource(String spec) {
+ if (spec.equals("wifi")) return R.drawable.ic_qs_wifi_full_4;
+ else if (spec.equals("bt")) return R.drawable.ic_qs_bluetooth_on;
+ else if (spec.equals("inversion")) return R.drawable.ic_invert_colors_enable_animation;
+ else if (spec.equals("cell")) return R.drawable.ic_qs_signal_full_4;
+ else if (spec.equals("airplane")) return R.drawable.ic_signal_airplane_enable;
+ else if (spec.equals("dnd")) return R.drawable.ic_dnd;
+ else if (spec.equals("rotation")) return R.drawable.ic_portrait_from_auto_rotate;
+ else if (spec.equals("flashlight")) return R.drawable.ic_signal_flashlight_enable;
+ else if (spec.equals("location")) return R.drawable.ic_signal_location_enable;
+ else if (spec.equals("cast")) return R.drawable.ic_qs_cast_on;
+ else if (spec.equals("hotspot")) return R.drawable.ic_hotspot_enable;
+ else if (spec.equals("edit")) return R.drawable.ic_qs_edit_tiles;
+ else if (spec.equals("adb_network")) return R.drawable.ic_qs_network_adb_on;
+ else if (spec.equals("compass")) return R.drawable.ic_qs_compass_on;
+ else if (spec.equals("nfc")) return R.drawable.ic_qs_nfc_on;
+ else if (spec.equals("profiles")) return R.drawable.ic_qs_profiles_on;
+ else if (spec.equals("sync")) return R.drawable.ic_qs_sync_on;
+ else if (spec.equals("volume_panel")) return R.drawable.ic_qs_volume_panel;
+ else if (spec.equals("usb_tether")) return R.drawable.ic_qs_usb_tether_on;
+ else if (spec.equals("screen_timeout")) return R.drawable.ic_qs_screen_timeout_short_avd;
+ else if (spec.equals("performance")) return R.drawable.ic_qs_perf_profile;
+ else if (spec.equals("lockscreen")) return R.drawable.ic_qs_lock_screen_on;
+ else if (spec.equals("ambient_display")) return R.drawable.ic_qs_ambientdisplay_on;
+ else if (spec.equals("live_display")) return R.drawable.ic_livedisplay_auto;
+ else if (spec.equals("heads_up")) return R.drawable.ic_qs_heads_up_on;
+ else if (spec.equals("battery_saver")) return R.drawable.ic_qs_battery_saver_on;
+ else if (spec.equals("caffeine")) return R.drawable.ic_qs_caffeine_on;
+ return 0;
+ }
+
+ void updateCustomTile(StatusBarPanelCustomTile sbc) {
+ synchronized (mTiles) {
+ if (mTiles.containsKey(sbc.getKey())) {
+ QSTile<?> tile = mTiles.get(sbc.getKey());
+ if (tile instanceof CustomQSTile) {
+ CustomQSTile qsTile = (CustomQSTile) tile;
+ qsTile.update(sbc);
+ }
+ }
+ }
+ }
+
+ void addCustomTile(StatusBarPanelCustomTile sbc) {
+ synchronized (mTiles) {
+ mCustomTileData.add(new CustomTileData.Entry(sbc));
+ mTileSpecs.add(sbc.getKey());
+ mTiles.put(sbc.getKey(), new CustomQSTile(this, sbc));
+ if (mCallback != null) {
+ mCallback.onTilesChanged();
+ }
+ }
+ }
+
+ void removeCustomTileSysUi(String key) {
+ synchronized (mTiles) {
+ if (mTiles.containsKey(key)) {
+ mTileSpecs.remove(key);
+ mTiles.remove(key);
+ mCustomTileData.remove(key);
+ if (mCallback != null) {
+ mCallback.onTilesChanged();
+ }
+ }
+ }
+ }
+
+ public CustomTileData getCustomTileData() {
+ return mCustomTileData;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index 18db5b8..3e0aa18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -17,18 +17,18 @@ package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.graphics.drawable.RippleDrawable;
-import android.os.Handler;
-import android.os.Message;
import android.util.AttributeSet;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
import com.android.keyguard.AlphaOptimizedImageButton;
public class SettingsButton extends AlphaOptimizedImageButton {
@@ -56,6 +56,10 @@ public class SettingsButton extends AlphaOptimizedImageButton {
return mUpToSpeed;
}
+ public void consumeClick() {
+ mUpToSpeed = false;
+ }
+
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
@@ -78,6 +82,7 @@ public class SettingsButton extends AlphaOptimizedImageButton {
if ((x < -mSlop) || (y < -mSlop) || (x > getWidth() + mSlop)
|| (y > getHeight() + mSlop)) {
cancelLongClick();
+ startExitAnimation();
}
break;
}
@@ -99,32 +104,11 @@ public class SettingsButton extends AlphaOptimizedImageButton {
}
private void startExitAnimation() {
+ cancelAnimation();
animate()
- .translationX(((View) getParent().getParent()).getWidth() - getX())
- .alpha(0)
- .setDuration(RUN_DURATION)
- .setInterpolator(AnimationUtils.loadInterpolator(mContext,
- android.R.interpolator.accelerate_cubic))
- .setListener(new AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- setAlpha(1f);
- setTranslationX(0);
- cancelLongClick();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- }
- })
+ .rotation(0)
+ .setDuration(ACCEL_LENGTH)
+ .setInterpolator(new DecelerateInterpolator(4))
.start();
}
@@ -164,6 +148,8 @@ public class SettingsButton extends AlphaOptimizedImageButton {
mAnimator.setDuration(FULL_SPEED_LENGTH);
mAnimator.setRepeatCount(Animation.INFINITE);
mAnimator.start();
+
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
private final Runnable mLongPressCallback = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 971978d..339d469 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -16,18 +16,31 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
+import android.content.ContentUris;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.AlarmClock;
+import android.provider.CalendarContract;
+import android.provider.Settings;
+import android.net.Uri;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.MathUtils;
import android.util.TypedValue;
import android.view.View;
@@ -41,30 +54,41 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.keyguard.KeyguardStatusView;
+import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.BatteryMeterView;
+import com.android.systemui.DockBatteryMeterView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
+import com.android.systemui.qs.QSDragPanel;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DockBatteryController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.WeatherController;
+import com.android.systemui.statusbar.policy.WeatherControllerImpl;
import com.android.systemui.tuner.TunerService;
import java.text.NumberFormat;
+import cyanogenmod.app.StatusBarPanelCustomTile;
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.logging.CMMetricsLogger;
+
/**
* The view to manage the header area in the expanded status bar.
*/
public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener,
- BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback,
- EmergencyListener {
+ NextAlarmController.NextAlarmChangeCallback, WeatherController.Callback, EmergencyListener {
private boolean mExpanded;
private boolean mListening;
private ViewGroup mSystemIconsContainer;
+ private ViewGroup mWeatherContainer;
private View mSystemIconsSuperContainer;
private View mDateGroup;
private View mClock;
@@ -83,8 +107,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private Switch mQsDetailHeaderSwitch;
private ImageView mQsDetailHeaderProgress;
private TextView mEmergencyCallsOnly;
- private TextView mBatteryLevel;
+ private BatteryLevelTextView mBatteryLevel;
+ private BatteryLevelTextView mDockBatteryLevel;
private TextView mAlarmStatus;
+ private TextView mWeatherLine1, mWeatherLine2;
+ private TextView mEditTileDoneText;
private boolean mShowEmergencyCallsOnly;
private boolean mAlarmShowing;
@@ -112,9 +139,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private float mAvatarCollapsedScaleFactor;
private ActivityStarter mActivityStarter;
- private BatteryController mBatteryController;
private NextAlarmController mNextAlarmController;
- private QSPanel mQSPanel;
+ private WeatherController mWeatherController;
+ private QSDragPanel mQSPanel;
private final Rect mClipBounds = new Rect();
@@ -127,6 +154,14 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private float mCurrentT;
private boolean mShowingDetail;
private boolean mDetailTransitioning;
+ private SettingsObserver mSettingsObserver;
+ private boolean mShowWeather;
+ private boolean mShowBatteryTextExpanded;
+
+ private QSTile.DetailAdapter mEditingDetailAdapter;
+ private boolean mEditing;
+
+ private UserInfoController mUserInfoController;
public StatusBarHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -139,7 +174,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
mSystemIconsSuperContainer.setOnClickListener(this);
mDateGroup = findViewById(R.id.date_group);
+ mDateGroup.setOnClickListener(this);
mClock = findViewById(R.id.clock);
+ mClock.setOnClickListener(this);
mTime = (TextView) findViewById(R.id.time_view);
mAmPm = (TextView) findViewById(R.id.am_pm_view);
mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
@@ -155,11 +192,18 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
- mBatteryLevel = (TextView) findViewById(R.id.battery_level);
+ mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text);
+ mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text);
mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
mAlarmStatus.setOnClickListener(this);
mSignalCluster = findViewById(R.id.signal_cluster);
mSystemIcons = (LinearLayout) findViewById(R.id.system_icons);
+ mWeatherContainer = (LinearLayout) findViewById(R.id.weather_container);
+ mWeatherContainer.setOnClickListener(this);
+ mWeatherLine1 = (TextView) findViewById(R.id.weather_line_1);
+ mWeatherLine2 = (TextView) findViewById(R.id.weather_line_2);
+ mEditTileDoneText = (TextView) findViewById(R.id.done);
+ mSettingsObserver = new SettingsObserver(new Handler());
loadDimens();
updateVisibilities();
updateClockScale();
@@ -188,9 +232,18 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
// RenderThread is doing more harm than good when touching the header (to expand quick
// settings), so disable it for this view
- ((RippleDrawable) getBackground()).setForceSoftware(true);
- ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
- ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
+ Drawable d = getBackground();
+ if (d instanceof RippleDrawable) {
+ ((RippleDrawable) d).setForceSoftware(true);
+ }
+ d = mSettingsButton.getBackground();
+ if (d instanceof RippleDrawable) {
+ ((RippleDrawable) d).setForceSoftware(true);
+ }
+ d = mSystemIconsSuperContainer.getBackground();
+ if (d instanceof RippleDrawable) {
+ ((RippleDrawable) d).setForceSoftware(true);
+ }
}
@Override
@@ -211,7 +264,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- FontSizeUtils.updateFontSize(mBatteryLevel, R.dimen.battery_level_text_size);
FontSizeUtils.updateFontSize(mEmergencyCallsOnly,
R.dimen.qs_emergency_calls_only_text_size);
FontSizeUtils.updateFontSize(mDateCollapsed, R.dimen.qs_date_collapsed_size);
@@ -232,6 +284,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
updateClockCollapsedMargin();
}
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mUserInfoController != null) {
+ mUserInfoController.removeListener(mUserInfoChangedListener);
+ }
+ setListening(false);
+ }
+
private void updateClockCollapsedMargin() {
Resources res = getResources();
int padding = res.getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin);
@@ -274,17 +335,42 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
public void setActivityStarter(ActivityStarter activityStarter) {
mActivityStarter = activityStarter;
+ if (mMultiUserSwitch != null) {
+ mMultiUserSwitch.setActivityStarter(activityStarter);
+ }
}
public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
- ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
+ BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery));
+ v.setBatteryStateRegistar(batteryController);
+ v.setBatteryController(batteryController);
+ mBatteryLevel.setBatteryStateRegistar(batteryController);
+ }
+
+ public void setDockBatteryController(DockBatteryController dockBatteryController) {
+ DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery));
+ if (dockBatteryController != null) {
+ v.setBatteryStateRegistar(dockBatteryController);
+ mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController);
+ } else {
+ if (v != null) {
+ removeView(v);
+ }
+ if (mDockBatteryLevel != null) {
+ removeView(mDockBatteryLevel);
+ mDockBatteryLevel = null;
+ }
+ }
}
public void setNextAlarmController(NextAlarmController nextAlarmController) {
mNextAlarmController = nextAlarmController;
}
+ public void setWeatherController(WeatherController weatherController) {
+ mWeatherController = weatherController;
+ }
+
public int getCollapsedHeight() {
return mCollapsedHeight;
}
@@ -305,6 +391,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
boolean changed = expanded != mExpanded;
mExpanded = expanded;
if (changed) {
+ if (mShowingDetail && !expanded) {
+ mQsPanelCallback.onShowingDetail(null);
+ }
updateEverything();
}
}
@@ -335,14 +424,18 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
- mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
+ mWeatherContainer.setVisibility(mExpanded && mShowWeather ? View.VISIBLE : View.GONE);
+ mQsDetailHeader.setVisibility(mExpanded && mShowingDetail ? View.VISIBLE : View.INVISIBLE);
if (mSignalCluster != null) {
updateSignalClusterDetachment();
}
mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
- mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
- mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
- TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
+ mBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded);
+ mBatteryLevel.setVisibility(View.VISIBLE);
+ if (mDockBatteryLevel != null) {
+ mDockBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded);
+ mDockBatteryLevel.setVisibility(View.VISIBLE);
+ }
}
private void updateSignalClusterDetachment() {
@@ -375,11 +468,13 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private void updateListeners() {
if (mListening) {
- mBatteryController.addStateChangedCallback(this);
+ mSettingsObserver.observe();
mNextAlarmController.addStateChangedCallback(this);
+ mWeatherController.addCallback(this);
} else {
- mBatteryController.removeStateChangedCallback(this);
mNextAlarmController.removeStateChangedCallback(this);
+ mWeatherController.removeCallback(this);
+ mSettingsObserver.unobserve();
}
}
@@ -408,17 +503,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
- mBatteryLevel.setText(percentage);
- }
-
- @Override
- public void onPowerSaveChanged() {
- // could not care less
- }
-
- @Override
public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
mNextAlarm = nextAlarm;
if (nextAlarm != null) {
@@ -429,6 +513,19 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
requestCaptureValues();
}
+ @Override
+ public void onWeatherChanged(WeatherController.WeatherInfo info) {
+ if (info.temp == null || info.condition == null) {
+ mWeatherLine1.setText(null);
+ } else {
+ mWeatherLine1.setText(mContext.getString(
+ R.string.status_bar_expanded_header_weather_format,
+ info.temp,
+ info.condition));
+ }
+ mWeatherLine2.setText(info.city);
+ }
+
private void updateClickTargets() {
mMultiUserSwitch.setClickable(mExpanded);
mMultiUserSwitch.setFocusable(mExpanded);
@@ -496,33 +593,31 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
invalidateOutline();
}
+ private UserInfoController.OnUserInfoChangedListener mUserInfoChangedListener =
+ new UserInfoController.OnUserInfoChangedListener() {
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ mMultiUserAvatar.setImageDrawable(picture);
+ }
+ };
+
public void setUserInfoController(UserInfoController userInfoController) {
- userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture) {
- mMultiUserAvatar.setImageDrawable(picture);
- }
- });
+ mUserInfoController = userInfoController;
+ userInfoController.addListener(mUserInfoChangedListener);
+ if (mMultiUserSwitch != null) {
+ mMultiUserSwitch.setUserInfoController(mUserInfoController);
+ }
}
@Override
public void onClick(View v) {
if (v == mSettingsButton) {
if (mSettingsButton.isTunerClick()) {
- if (TunerService.isTunerEnabled(mContext)) {
- TunerService.showResetRequest(mContext, new Runnable() {
- @Override
- public void run() {
- // Relaunch settings so that the tuner disappears.
- startSettingsActivity();
- }
- });
- } else {
- Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
- TunerService.setTunerEnabled(mContext, true);
- }
+ mSettingsButton.consumeClick();
+ mQSPanel.getHost().setEditing(!mQSPanel.getHost().isEditing());
+ } else {
+ startSettingsActivity();
}
- startSettingsActivity();
} else if (v == mSystemIconsSuperContainer) {
startBatteryActivity();
} else if (v == mAlarmStatus && mNextAlarm != null) {
@@ -530,6 +625,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
if (showIntent != null) {
mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
}
+ } else if (v == mClock) {
+ startClockActivity();
+ } else if (v == mDateGroup) {
+ startDateActivity();
+ } else if (v == mWeatherContainer) {
+ startForecastActivity();
}
}
@@ -543,7 +644,27 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
true /* dismissShade */);
}
- public void setQSPanel(QSPanel qsp) {
+ private void startClockActivity() {
+ mActivityStarter.startActivity(new Intent(AlarmClock.ACTION_SHOW_ALARMS),
+ true /* dismissShade */);
+ }
+
+ private void startDateActivity() {
+ Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
+ builder.appendPath("time");
+ ContentUris.appendId(builder, System.currentTimeMillis());
+ Intent intent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
+ mActivityStarter.startActivity(intent, true /* dismissShade */);
+ }
+
+ private void startForecastActivity() {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setComponent(WeatherControllerImpl.COMPONENT_WEATHER_FORECAST);
+ mActivityStarter.startActivity(intent, true /* dismissShade */);
+ }
+
+ public void setQSPanel(QSDragPanel qsp) {
mQSPanel = qsp;
if (mQSPanel != null) {
mQSPanel.setCallback(mQsPanelCallback);
@@ -585,6 +706,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
target.avatarScale = mMultiUserAvatar.getScaleX();
target.avatarX = mMultiUserSwitch.getLeft() + mMultiUserAvatar.getLeft();
target.avatarY = mMultiUserSwitch.getTop() + mMultiUserAvatar.getTop();
+ target.weatherY = mClock.getBottom() - mWeatherLine1.getHeight();
if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
target.batteryX = mSystemIconsSuperContainer.getLeft()
+ mSystemIconsContainer.getRight();
@@ -623,6 +745,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mTime.setScaleY(values.timeScale);
mClock.setY(values.clockY - mClock.getHeight());
mDateGroup.setY(values.dateY);
+ mWeatherContainer.setY(values.weatherY);
mAlarmStatus.setY(values.dateY - mAlarmStatus.getPaddingTop());
mMultiUserAvatar.setScaleX(values.avatarScale);
mMultiUserAvatar.setScaleY(values.avatarScale);
@@ -662,7 +785,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
applyAlpha(mDateExpanded, values.dateExpandedAlpha);
applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
+ if (mDockBatteryLevel != null) {
+ applyAlpha(mDockBatteryLevel, values.batteryLevelAlpha);
+ }
applyAlpha(mSettingsContainer, values.settingsAlpha);
+ applyAlpha(mWeatherLine1, values.settingsAlpha);
+ applyAlpha(mWeatherLine2, values.settingsAlpha);
applyAlpha(mSignalCluster, values.signalClusterAlpha);
if (!mExpanded) {
mTime.setScaleX(1f);
@@ -671,6 +799,50 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
updateAmPmTranslation();
}
+ public void setEditing(boolean editing) {
+ mEditing = editing;
+ if (editing && mEditingDetailAdapter == null) {
+ mEditingDetailAdapter = new QSTile.DetailAdapter() {
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_edit_label;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ return null;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return null;
+ }
+
+ @Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return CMMetricsLogger.DONT_LOG;
+ }
+ };
+ }
+ mQsPanelCallback.onShowingDetail(mEditing ? mEditingDetailAdapter : null);
+ updateEverything();
+ }
+
/**
* Captures all layout values (position, visibility) for a certain state. This is used for
* animations.
@@ -690,10 +862,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
float batteryX;
float batteryY;
float batteryLevelAlpha;
+ float batteryLevelExpandedAlpha;
float settingsAlpha;
float settingsTranslation;
float signalClusterAlpha;
float settingsRotation;
+ float weatherY;
public void interpoloate(LayoutValues v1, LayoutValues v2, float t) {
timeScale = v1.timeScale * (1 - t) + v2.timeScale * t;
@@ -705,6 +879,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
batteryX = v1.batteryX * (1 - t) + v2.batteryX * t;
batteryY = v1.batteryY * (1 - t) + v2.batteryY * t;
settingsTranslation = v1.settingsTranslation * (1 - t) + v2.settingsTranslation * t;
+ weatherY = v1.weatherY * (1 - t) + v2.weatherY * t;
float t1 = Math.max(0, t - 0.5f) * 2;
settingsRotation = v1.settingsRotation * (1 - t1) + v2.settingsRotation * t1;
@@ -720,6 +895,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
dateExpandedAlpha = v1.dateExpandedAlpha * (1 - t3) + v2.dateExpandedAlpha * t3;
dateCollapsedAlpha = v1.dateCollapsedAlpha * (1 - t3) + v2.dateCollapsedAlpha * t3;
alarmStatusAlpha = v1.alarmStatusAlpha * (1 - t3) + v2.alarmStatusAlpha * t3;
+ batteryLevelExpandedAlpha =
+ v1.batteryLevelExpandedAlpha * (1 - t3) + v2.batteryLevelExpandedAlpha * t3;
}
}
@@ -742,7 +919,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
post(new Runnable() {
@Override
public void run() {
- handleShowingDetail(detail);
+ handleShowingDetail(mEditing && detail == null ? mEditingDetailAdapter : detail);
}
});
}
@@ -778,18 +955,33 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
final boolean showingDetail = detail != null;
transition(mClock, !showingDetail);
transition(mDateGroup, !showingDetail);
+ if (mShowWeather) {
+ transition(mWeatherContainer, !showingDetail);
+ }
if (mAlarmShowing) {
- transition(mAlarmStatus, !showingDetail);
+ transition(mAlarmStatus, !showingDetail && !mDetailTransitioning);
}
transition(mQsDetailHeader, showingDetail);
mShowingDetail = showingDetail;
if (showingDetail) {
mQsDetailHeaderTitle.setText(detail.getTitle());
final Boolean toggleState = detail.getToggleState();
- if (toggleState == null) {
+ if (detail.getTitle() == R.string.quick_settings_edit_label) {
+ mEditTileDoneText.setVisibility(View.VISIBLE);
mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
+ mQsDetailHeader.setClickable(true);
+ mQsDetailHeader.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mQSPanel.getHost().setEditing(false);
+ }
+ });
+ } else if (toggleState == null) {
+ mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
+ mEditTileDoneText.setVisibility(View.GONE);
mQsDetailHeader.setClickable(false);
} else {
+ mEditTileDoneText.setVisibility(View.GONE);
mQsDetailHeaderSwitch.setVisibility(VISIBLE);
mQsDetailHeaderSwitch.setChecked(toggleState);
mQsDetailHeader.setClickable(true);
@@ -829,4 +1021,58 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
.start();
}
};
+
+ class SettingsObserver extends UserContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void observe() {
+ super.observe();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_SHOW_WEATHER), false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_BATTERY_STYLE), false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT), false, this, UserHandle.USER_ALL);
+ update();
+ }
+
+ @Override
+ protected void unobserve() {
+ super.unobserve();
+
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void update() {
+
+ ContentResolver resolver = mContext.getContentResolver();
+ int currentUserId = ActivityManager.getCurrentUser();
+ int batteryStyle = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, currentUserId);
+ boolean showExpandedBatteryPercentage = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, currentUserId) == 0;
+
+ switch (batteryStyle) {
+ case 4: //BATTERY_METER_GONE
+ case 6: //BATTERY_METER_TEXT
+ showExpandedBatteryPercentage = false;
+ break;
+ default:
+ break;
+ }
+
+ mShowBatteryTextExpanded = showExpandedBatteryPercentage;
+ mShowWeather = CMSettings.System.getInt(
+ resolver, CMSettings.System.STATUS_BAR_SHOW_WEATHER, 1) == 1;
+ updateVisibilities();
+ requestCaptureValues();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 5de1c13..a7fa27d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -24,6 +24,7 @@ import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.view.View;
@@ -36,12 +37,14 @@ import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.BatteryLevelTextView;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -73,8 +76,10 @@ public class StatusBarIconController implements Tunable {
private IconMerger mNotificationIcons;
private View mNotificationIconArea;
private ImageView mMoreIcon;
+ private BatteryLevelTextView mBatteryLevelTextView;
private BatteryMeterView mBatteryMeterView;
- private TextView mClock;
+ private ClockController mClockController;
+ private View mCenterClockLayout;
private int mIconSize;
private int mIconHPadding;
@@ -117,8 +122,9 @@ public class StatusBarIconController implements Tunable {
mMoreIcon = (ImageView) statusBar.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
+ mBatteryLevelTextView =
+ (BatteryLevelTextView) statusBar.findViewById(R.id.battery_level_text);
mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
- mClock = (TextView) statusBar.findViewById(R.id.clock);
mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear_out_slow_in);
mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext,
@@ -126,6 +132,8 @@ public class StatusBarIconController implements Tunable {
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
mHandler = new Handler();
+ mClockController = new ClockController(statusBar, mNotificationIcons, mHandler);
+ mCenterClockLayout = statusBar.findViewById(R.id.center_clock_layout);
updateResources();
TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
@@ -158,7 +166,7 @@ public class StatusBarIconController implements Tunable {
com.android.internal.R.dimen.status_bar_icon_size);
mIconHPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_icon_padding);
- FontSizeUtils.updateFontSize(mClock, R.dimen.status_bar_clock_size);
+ mClockController.updateFontSize();
}
public void addSystemIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
@@ -247,22 +255,26 @@ public class StatusBarIconController implements Tunable {
public void hideSystemIconArea(boolean animate) {
animateHide(mSystemIconArea, animate);
+ animateHide(mCenterClockLayout, animate);
}
public void showSystemIconArea(boolean animate) {
animateShow(mSystemIconArea, animate);
+ animateShow(mCenterClockLayout, animate);
}
public void hideNotificationIconArea(boolean animate) {
animateHide(mNotificationIconArea, animate);
+ animateHide(mCenterClockLayout, animate);
}
public void showNotificationIconArea(boolean animate) {
animateShow(mNotificationIconArea, animate);
+ animateShow(mCenterClockLayout, animate);
}
public void setClockVisibility(boolean visible) {
- mClock.setVisibility(visible ? View.VISIBLE : View.GONE);
+ mClockController.setVisibility(visible);
}
public void dump(PrintWriter pw) {
@@ -392,8 +404,9 @@ public class StatusBarIconController implements Tunable {
}
mSignalCluster.setIconTint(mIconTint, mDarkIntensity);
mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
+ mBatteryLevelTextView.setTextColor(mIconTint);
mBatteryMeterView.setDarkIntensity(mDarkIntensity);
- mClock.setTextColor(mIconTint);
+ mClockController.setTextColor(mIconTint);
applyNotificationIconsTint();
}
@@ -462,4 +475,32 @@ public class StatusBarIconController implements Tunable {
}
return ret;
}
+
+ public void refreshAllStatusBarIcons() {
+ refreshAllIconsForLayout(mStatusIcons);
+ refreshAllIconsForLayout(mStatusIconsKeyguard);
+ refreshAllIconsForLayout(mNotificationIcons);
+ }
+
+ public LinearLayout getStatusIcons() {
+ return mStatusIcons;
+ }
+
+ public void cleanup() {
+ TunerService.get(mContext).removeTunable(this);
+ mClockController.cleanup();
+ if (mSignalCluster != null) {
+ mSignalCluster.setSecurityController(null);
+ }
+ }
+
+ private void refreshAllIconsForLayout(LinearLayout ll) {
+ final int count = ll.getChildCount();
+ for (int n = 0; n < count; n++) {
+ View child = ll.getChildAt(n);
+ if (child instanceof StatusBarIconView) {
+ ((StatusBarIconView) child).updateDrawable();
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 05f6e57..19f2b09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -18,17 +18,21 @@ package com.android.systemui.statusbar.phone;
import android.content.ComponentCallbacks2;
import android.content.Context;
+import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.Trace;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.statusbar.CommandQueue;
@@ -79,6 +83,8 @@ public class StatusBarKeyguardViewManager {
private boolean mDeviceWillWakeUp;
private boolean mDeferScrimFadeOut;
+ private View mUnlockFab;
+
public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils) {
mContext = context;
@@ -94,6 +100,7 @@ public class StatusBarKeyguardViewManager {
mContainer = container;
mStatusBarWindowManager = statusBarWindowManager;
mScrimController = scrimController;
+ if (mBouncer != null) mBouncer.removeView();
mFingerprintUnlockController = fingerprintUnlockController;
mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
mStatusBarWindowManager, container);
@@ -107,23 +114,38 @@ public class StatusBarKeyguardViewManager {
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
mScrimController.abortKeyguardFadingOut();
- reset();
+ reset(false);
}
/**
* Shows the notification keyguard or the bouncer depending on
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
*/
- private void showBouncerOrKeyguard() {
- if (mBouncer.needsFullscreenBouncer()) {
-
- // The keyguard might be showing (already). So we need to hide it.
- mPhoneStatusBar.hideKeyguard();
- mBouncer.show(true /* resetSecuritySelection */);
- } else {
- mPhoneStatusBar.showKeyguard();
- mBouncer.hide(false /* destroyView */);
- mBouncer.prepare();
+ private void showBouncerOrKeyguard(boolean isBackPressed) {
+ switch (mBouncer.needsFullscreenBouncer()) {
+ case KeyguardBouncer.UNLOCK_SEQUENCE_FORCE_BOUNCER:
+ // SIM PIN/PUK
+ // The keyguard might be showing (already). So we need to hide it.
+ mPhoneStatusBar.hideKeyguard();
+ mBouncer.show(true /* resetSecuritySelection */);
+ break;
+ case KeyguardBouncer.UNLOCK_SEQUENCE_BOUNCER_FIRST:
+ // Pattern/PIN/Password with "Directly pass to security view" enabled
+ if (isBackPressed) {
+ mPhoneStatusBar.showKeyguard();
+ mBouncer.hide(false /* destroyView */);
+ mBouncer.prepare();
+ } else {
+ // The keyguard might be showing (already). So we need to hide it.
+ mPhoneStatusBar.hideKeyguard();
+ mBouncer.show(true /* resetSecuritySelection */);
+ }
+ break;
+ case KeyguardBouncer.UNLOCK_SEQUENCE_DEFAULT:
+ mPhoneStatusBar.showKeyguard();
+ mBouncer.hide(false /* destroyView */);
+ mBouncer.prepare();
+ break;
}
}
@@ -150,14 +172,14 @@ public class StatusBarKeyguardViewManager {
/**
* Reset the state of the view.
*/
- public void reset() {
+ public void reset(boolean isBackPressed) {
if (mShowing) {
if (mOccluded) {
mPhoneStatusBar.hideKeyguard();
mPhoneStatusBar.stopWaitingForKeyguardExit();
mBouncer.hide(false /* destroyView */);
} else {
- showBouncerOrKeyguard();
+ showBouncerOrKeyguard(isBackPressed);
}
KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
updateStates();
@@ -197,10 +219,12 @@ public class StatusBarKeyguardViewManager {
updateStates();
}
mPhoneStatusBar.onScreenTurnedOn();
+ mStatusBarWindowManager.onKeyguardChanged();
}
public void onScreenTurnedOff() {
mScreenTurnedOn = false;
+ mPhoneStatusBar.onScreenTurnedOff();
}
public void notifyDeviceWakeUpRequested() {
@@ -224,7 +248,7 @@ public class StatusBarKeyguardViewManager {
@Override
public void run() {
mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
- reset();
+ reset(false);
}
});
return;
@@ -232,7 +256,11 @@ public class StatusBarKeyguardViewManager {
}
mOccluded = occluded;
mStatusBarWindowManager.setKeyguardOccluded(occluded);
- reset();
+ mPhoneStatusBar.getVisualizer().setOccluded(occluded);
+ if (mUnlockFab != null && mUnlockFab.isAttachedToWindow() && !occluded) {
+ hideUnlockFab();
+ }
+ reset(false);
}
public boolean isOccluded() {
@@ -359,6 +387,7 @@ public class StatusBarKeyguardViewManager {
private void executeAfterKeyguardGoneAction() {
if (mAfterKeyguardGoneAction != null) {
+ dismiss();
mAfterKeyguardGoneAction.onDismiss();
mAfterKeyguardGoneAction = null;
}
@@ -368,8 +397,16 @@ public class StatusBarKeyguardViewManager {
* Dismisses the keyguard by going to the next screen or making it gone.
*/
public void dismiss() {
- if (mDeviceInteractive || mDeviceWillWakeUp) {
+ dismiss(false);
+ }
+
+ public void dismiss(boolean focusKeyguardExternalView) {
+ if ((mDeviceInteractive || mDeviceWillWakeUp) && !focusKeyguardExternalView) {
showBouncer();
+ hideUnlockFab();
+ } else if (focusKeyguardExternalView) {
+ showUnlockFab();
+ mStatusBarWindowManager.setKeyguardExternalViewFocus(true);
}
}
@@ -395,7 +432,7 @@ public class StatusBarKeyguardViewManager {
public boolean onBackPressed() {
if (mBouncer.isShowing()) {
mPhoneStatusBar.endAffordanceLaunch();
- reset();
+ reset(true);
return true;
}
return false;
@@ -428,7 +465,8 @@ public class StatusBarKeyguardViewManager {
boolean showing = mShowing;
boolean occluded = mOccluded;
boolean bouncerShowing = mBouncer.isShowing();
- boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
+ boolean bouncerDismissible = (mBouncer.isFullscreenBouncer() !=
+ KeyguardBouncer.UNLOCK_SEQUENCE_FORCE_BOUNCER);
if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
|| mFirstUpdate) {
@@ -503,7 +541,8 @@ public class StatusBarKeyguardViewManager {
}
public boolean shouldDisableWindowAnimationsForUnlock() {
- return mPhoneStatusBar.isInLaunchTransition();
+ return mPhoneStatusBar.isInLaunchTransition() ||
+ mPhoneStatusBar.mNotificationPanel.hasExternalKeyguardView();
}
public boolean isGoingToNotificationShade() {
@@ -525,6 +564,10 @@ public class StatusBarKeyguardViewManager {
public void animateCollapsePanels(float speedUpFactor) {
mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
false /* delayed */, speedUpFactor);
+ if (mStatusBarWindowManager.keyguardExternalViewHasFocus()) {
+ mStatusBarWindowManager.setKeyguardExternalViewFocus(false);
+ dismiss(false);
+ }
}
/**
@@ -542,4 +585,56 @@ public class StatusBarKeyguardViewManager {
public ViewRootImpl getViewRootImpl() {
return mPhoneStatusBar.getStatusBarView().getViewRootImpl();
}
+
+ public boolean isKeyguardShowingMedia() {
+ return mPhoneStatusBar.isKeyguardShowingMedia();
+ }
+
+ public void setKeyguardExternalViewFocus(boolean hasFocus) {
+ if (hasFocus) {
+ showUnlockFab();
+ } else {
+ hideUnlockFab();
+ }
+ mStatusBarWindowManager.setKeyguardExternalViewFocus(hasFocus);
+ }
+
+ private void showUnlockFab() {
+ if (mUnlockFab == null) {
+ mUnlockFab = View.inflate(mContext, R.layout.unlock_fab, null);
+ }
+ if (!mUnlockFab.isAttachedToWindow()) {
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ PixelFormat.TRANSLUCENT);
+ lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+ lp.setTitle("UnlockFab");
+ lp.packageName = mContext.getPackageName();
+ lp.width = lp.height =
+ mContext.getResources().getDimensionPixelSize(R.dimen.unlock_fab_size);
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.addView(mUnlockFab, lp);
+ mUnlockFab.setOnClickListener(mUnlockFabClickListener);
+ }
+ }
+
+ private void hideUnlockFab() {
+ if (mUnlockFab != null && mUnlockFab.isAttachedToWindow()) {
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.removeViewImmediate(mUnlockFab);
+ }
+ }
+
+ private View.OnClickListener mUnlockFabClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mStatusBarWindowManager.setKeyguardExternalViewFocus(false);
+ dismiss(false);
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index ccfa0dd..9a991f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -19,18 +19,24 @@ package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.PixelFormat;
import android.os.SystemProperties;
+import android.util.Log;
import android.view.Gravity;
+import android.view.Display;
+import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup;
-import android.view.Window;
import android.view.WindowManager;
import com.android.keyguard.R;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.util.CmLockPatternUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -39,7 +45,7 @@ import java.lang.reflect.Field;
/**
* Encapsulates all logic for the status bar window state management.
*/
-public class StatusBarWindowManager {
+public class StatusBarWindowManager implements KeyguardMonitor.Callback {
private final Context mContext;
private final WindowManager mWindowManager;
@@ -49,14 +55,33 @@ public class StatusBarWindowManager {
private int mBarHeight;
private final boolean mKeyguardScreenRotation;
private final float mScreenBrightnessDoze;
+
+ private boolean mKeyguardBlurEnabled;
+ private boolean mShowingMedia;
+ private BlurLayer mKeyguardBlur;
+ private final SurfaceSession mFxSession;
+
+ private final KeyguardMonitor mKeyguardMonitor;
+
+ private static final int TYPE_LAYER_MULTIPLIER = 10000; // refer to WindowManagerService.TYPE_LAYER_MULTIPLIER
+ private static final int TYPE_LAYER_OFFSET = 1000; // refer to WindowManagerService.TYPE_LAYER_OFFSET
+
+ private static final int STATUS_BAR_LAYER = 16 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
+
private final State mCurrentState = new State();
- public StatusBarWindowManager(Context context) {
+ public StatusBarWindowManager(Context context, KeyguardMonitor kgm) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
mScreenBrightnessDoze = mContext.getResources().getInteger(
com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
+
+ mKeyguardMonitor = kgm;
+ mKeyguardMonitor.addCallback(this);
+ mKeyguardBlurEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_ui_blur_enabled);
+ mFxSession = new SurfaceSession();
}
private boolean shouldEnableKeyguardScreenRotation() {
@@ -72,7 +97,6 @@ public class StatusBarWindowManager {
* @param barHeight The height of the status bar in collapsed state.
*/
public void add(View statusBarView, int barHeight) {
-
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
@@ -96,15 +120,30 @@ public class StatusBarWindowManager {
mWindowManager.addView(mStatusBarView, mLp);
mLpChanged = new WindowManager.LayoutParams();
mLpChanged.copyFrom(mLp);
+
+ if (mKeyguardBlurEnabled) {
+ Display display = mWindowManager.getDefaultDisplay();
+ Point xy = new Point();
+ display.getRealSize(xy);
+ mKeyguardBlur = new BlurLayer(mFxSession, xy.x, xy.y, "KeyGuard");
+ if (mKeyguardBlur != null) {
+ mKeyguardBlur.setLayer(STATUS_BAR_LAYER - 2);
+ }
+ }
}
private void applyKeyguardFlags(State state) {
if (state.keyguardShowing) {
- mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ if (!mKeyguardBlurEnabled) {
+ mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ }
} else {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ if (mKeyguardBlurEnabled) {
+ mKeyguardBlur.hide();
+ }
}
}
@@ -217,13 +256,34 @@ public class StatusBarWindowManager {
}
}
+ private void applyKeyguardBlurShow(){
+ boolean isblur = false;
+ if (mCurrentState.keyguardShowing && mKeyguardBlurEnabled
+ && !mCurrentState.keyguardOccluded
+ && !mShowingMedia
+ && !isShowingLiveLockScreen()) {
+ isblur = true;
+ }
+ if (mKeyguardBlur != null) {
+ if (isblur) {
+ mKeyguardBlur.show();
+ } else {
+ mKeyguardBlur.hide();
+ }
+ }
+ }
+
public void setKeyguardShowing(boolean showing) {
mCurrentState.keyguardShowing = showing;
apply(mCurrentState);
}
public void setKeyguardOccluded(boolean occluded) {
+ final boolean oldOccluded = mCurrentState.keyguardOccluded;
mCurrentState.keyguardOccluded = occluded;
+ if (oldOccluded != occluded) {
+ applyKeyguardBlurShow();
+ }
apply(mCurrentState);
}
@@ -263,6 +323,29 @@ public class StatusBarWindowManager {
apply(mCurrentState);
}
+ void setBlur(float b){
+ if (mKeyguardBlurEnabled && mKeyguardBlur != null) {
+ float minBlur = mKeyguardMonitor.isSecure() ? 1.0f : 0.0f;
+ if (b < minBlur) {
+ b = minBlur;
+ } else if (b > 1.0f) {
+ b = 1.0f;
+ }
+ mKeyguardBlur.setBlur(b);
+ }
+ }
+
+ public void setShowingMedia(boolean showingMedia) {
+ mShowingMedia = showingMedia;
+ applyKeyguardBlurShow();
+ }
+
+ public void setKeyguardExternalViewFocus(boolean hasFocus) {
+ mCurrentState.keyguardExternalViewHasFocus = hasFocus;
+ // make the keyguard occluded so the external view gets full focus
+ setKeyguardOccluded(hasFocus);
+ }
+
/**
* @param state The {@link StatusBarState} of the status bar.
*/
@@ -300,11 +383,27 @@ public class StatusBarWindowManager {
apply(mCurrentState);
}
+ @Override
+ public void onKeyguardChanged() {
+ applyKeyguardBlurShow();
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("StatusBarWindowManager state:");
pw.println(mCurrentState);
}
+ public boolean keyguardExternalViewHasFocus() {
+ return mCurrentState.keyguardExternalViewHasFocus;
+ }
+
+ private boolean isShowingLiveLockScreen() {
+ CmLockPatternUtils lockPatternUtils = new CmLockPatternUtils(mContext);
+ return (CMSettings.Secure.getInt(mContext.getContentResolver(),
+ CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED, 0) == 1)
+ && lockPatternUtils.isThirdPartyKeyguardEnabled();
+ }
+
private static class State {
boolean keyguardShowing;
boolean keyguardOccluded;
@@ -319,6 +418,7 @@ public class StatusBarWindowManager {
boolean forceStatusBarVisible;
boolean forceCollapsed;
boolean forceDozeBrightness;
+ boolean keyguardExternalViewHasFocus;
/**
* The {@link BaseStatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 0e22aa8..56ced84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -17,29 +17,42 @@
package com.android.systemui.statusbar.phone;
import android.app.StatusBarManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.res.TypedArray;
+import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.media.session.MediaSessionLegacyHelper;
+import android.net.Uri;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.PowerManager;
+import android.provider.Settings;
import android.util.AttributeSet;
+import android.util.Log;
+import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
-
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import cyanogenmod.providers.CMSettings;
public class StatusBarWindowView extends FrameLayout {
@@ -51,76 +64,24 @@ public class StatusBarWindowView extends FrameLayout {
private NotificationPanelView mNotificationPanel;
private View mBrightnessMirror;
- private int mRightInset = 0;
-
private PhoneStatusBar mService;
private final Paint mTransparentSrcPaint = new Paint();
+ private int mStatusBarHeaderHeight;
+
+ private boolean mDoubleTapToSleepEnabled;
+ private GestureDetector mDoubleTapGesture;
+ private Handler mHandler = new Handler();
+ private SettingsObserver mSettingsObserver;
+
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
mTransparentSrcPaint.setColor(0);
mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- }
-
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- if (getFitsSystemWindows()) {
- boolean paddingChanged = insets.left != getPaddingLeft()
- || insets.top != getPaddingTop()
- || insets.bottom != getPaddingBottom();
-
- // Super-special right inset handling, because scrims and backdrop need to ignore it.
- if (insets.right != mRightInset) {
- mRightInset = insets.right;
- applyMargins();
- }
- // Drop top inset, apply left inset and pass through bottom inset.
- if (paddingChanged) {
- setPadding(insets.left, 0, 0, 0);
- }
- insets.left = 0;
- insets.top = 0;
- insets.right = 0;
- } else {
- if (mRightInset != 0) {
- mRightInset = 0;
- applyMargins();
- }
- boolean changed = getPaddingLeft() != 0
- || getPaddingRight() != 0
- || getPaddingTop() != 0
- || getPaddingBottom() != 0;
- if (changed) {
- setPadding(0, 0, 0, 0);
- }
- insets.top = 0;
- }
- return false;
- }
-
- private void applyMargins() {
- final int N = getChildCount();
- for (int i = 0; i < N; i++) {
- View child = getChildAt(i);
- if (child.getLayoutParams() instanceof LayoutParams) {
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (!lp.ignoreRightInset && lp.rightMargin != mRightInset) {
- lp.rightMargin = mRightInset;
- child.requestLayout();
- }
- }
- }
- }
-
- @Override
- public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ mStatusBarHeaderHeight = context
+ .getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
+ mSettingsObserver = new SettingsObserver(mHandler);
}
@Override
@@ -141,6 +102,21 @@ public class StatusBarWindowView extends FrameLayout {
protected void onAttachedToWindow () {
super.onAttachedToWindow();
+ mSettingsObserver.observe();
+ mDoubleTapGesture = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ Log.d(TAG, "Gesture!!");
+ if(pm != null)
+ pm.goToSleep(e.getEventTime());
+ else
+ Log.d(TAG, "getSystemService returned null PowerManager");
+
+ return true;
+ }
+ });
+
// We really need to be able to animate while window animations are going on
// so that activities may be started asynchronously from panel animations
final ViewRootImpl root = getViewRootImpl();
@@ -152,11 +128,13 @@ public class StatusBarWindowView extends FrameLayout {
// occur if our window is translucent. Since we are drawing the whole window anyway with
// the scrim, we don't need the window to be cleared in the beginning.
if (mService.isScrimSrcModeEnabled()) {
- IBinder windowToken = getWindowToken();
- WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
- lp.token = windowToken;
- setLayoutParams(lp);
- WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
+ if (getLayoutParams() instanceof WindowManager.LayoutParams) {
+ WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
+ IBinder windowToken = getWindowToken();
+ lp.token = windowToken;
+ setLayoutParams(lp);
+ WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
+ }
setWillNotDraw(false);
} else {
setWillNotDraw(!DEBUG);
@@ -164,6 +142,22 @@ public class StatusBarWindowView extends FrameLayout {
}
@Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mSettingsObserver.unobserve();
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ insets.bottom = 0;
+ insets.top = 0;
+ insets.right = 0;
+ insets.left = 0;
+ super.fitSystemWindows(insets);
+ return false;
+ }
+
+ @Override
public boolean dispatchKeyEvent(KeyEvent event) {
boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
switch (event.getKeyCode()) {
@@ -211,6 +205,11 @@ public class StatusBarWindowView extends FrameLayout {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
+ if (mDoubleTapToSleepEnabled
+ && ev.getY() < mStatusBarHeaderHeight) {
+ if (DEBUG) Log.w(TAG, "logging double tap gesture");
+ mDoubleTapGesture.onTouchEvent(ev);
+ }
if (mNotificationPanel.isFullyExpanded()
&& mStackScrollLayout.getVisibility() == View.VISIBLE
&& mService.getBarState() == StatusBarState.KEYGUARD
@@ -251,7 +250,7 @@ public class StatusBarWindowView extends FrameLayout {
}
@Override
- public void onDraw(Canvas canvas) {
+ protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mService.isScrimSrcModeEnabled()) {
// We need to ensure that our window is always drawn fully even when we have paddings,
@@ -288,21 +287,51 @@ public class StatusBarWindowView extends FrameLayout {
}
}
- public class LayoutParams extends FrameLayout.LayoutParams {
+ public void addContent(View content) {
+ addView(content);
+ mStackScrollLayout = (NotificationStackScrollLayout) content.findViewById(
+ R.id.notification_stack_scroller);
+ mNotificationPanel = (NotificationPanelView) content.findViewById(R.id.notification_panel);
+ mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
+ mBrightnessMirror = content.findViewById(R.id.brightness_mirror);
- public boolean ignoreRightInset;
+ }
- public LayoutParams(int width, int height) {
- super(width, height);
+ public void removeContent(View content) {
+ removeView(content);
+ }
+
+ class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
}
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE), false, this);
+ update();
+ }
+
+ void unobserve() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update();
+ }
- TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
- ignoreRightInset = a.getBoolean(
- R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
- a.recycle();
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mDoubleTapToSleepEnabled = CMSettings.System
+ .getInt(resolver, CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE, 1) == 1;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index d701b3c..9ebb79f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -33,12 +33,7 @@ public class SystemUIDialog extends AlertDialog {
super(context, R.style.Theme_SystemUI_Dialog);
mContext = context;
- getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
- WindowManager.LayoutParams attrs = getWindow().getAttributes();
- attrs.setTitle(getClass().getSimpleName());
- getWindow().setAttributes(attrs);
+ makeSystemUIDialog(this);
}
public void setShowForAllUsers(boolean show) {
@@ -62,4 +57,13 @@ public class SystemUIDialog extends AlertDialog {
public void setNegativeButton(int resId, OnClickListener onClick) {
setButton(BUTTON_NEGATIVE, mContext.getString(resId), onClick);
}
+
+ public static void makeSystemUIDialog(AlertDialog d) {
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+ d.getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ WindowManager.LayoutParams attrs = d.getWindow().getAttributes();
+ attrs.setTitle(SystemUIDialog.class.getClass().getSimpleName());
+ d.getWindow().setAttributes(attrs);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index d1b69ab..c59a0d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -17,10 +17,14 @@
package com.android.systemui.statusbar.policy;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
import android.os.BatteryManager;
+import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
@@ -28,20 +32,38 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-public class BatteryController extends BroadcastReceiver {
+import cyanogenmod.providers.CMSettings;
+
+public class BatteryController extends BroadcastReceiver implements BatteryStateRegistar {
private static final String TAG = "BatteryController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ public static final int STYLE_ICON_PORTRAIT = 0;
+ public static final int STYLE_CIRCLE = 2;
+ public static final int STYLE_GONE = 4;
+ public static final int STYLE_ICON_LANDSCAPE = 5;
+ public static final int STYLE_TEXT = 6;
+
+ public static final int PERCENTAGE_MODE_OFF = 0;
+ public static final int PERCENTAGE_MODE_INSIDE = 1;
+ public static final int PERCENTAGE_MODE_OUTSIDE = 2;
+
private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
private int mLevel;
+ private boolean mPresent;
private boolean mPluggedIn;
private boolean mCharging;
private boolean mCharged;
private boolean mPowerSave;
- public BatteryController(Context context) {
+ private int mStyle;
+ private int mPercentMode;
+ private int mUserId;
+ private SettingsObserver mObserver;
+
+ public BatteryController(Context context, Handler handler) {
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
IntentFilter filter = new IntentFilter();
@@ -51,22 +73,34 @@ public class BatteryController extends BroadcastReceiver {
context.registerReceiver(this, filter);
updatePowerSave();
+
+ mObserver = new SettingsObserver(context, handler);
+ mObserver.observe();
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ mObserver.observe();
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("BatteryController state:");
pw.print(" mLevel="); pw.println(mLevel);
+ pw.print(" mPresent="); pw.println(mPresent);
pw.print(" mPluggedIn="); pw.println(mPluggedIn);
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mCharged="); pw.println(mCharged);
pw.print(" mPowerSave="); pw.println(mPowerSave);
}
+ @Override
public void addStateChangedCallback(BatteryStateChangeCallback cb) {
mChangeCallbacks.add(cb);
- cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging);
+ cb.onBatteryStyleChanged(mStyle, mPercentMode);
}
+ @Override
public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
mChangeCallbacks.remove(cb);
}
@@ -77,6 +111,7 @@ public class BatteryController extends BroadcastReceiver {
mLevel = (int)(100f
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
/ intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
+ mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
@@ -110,7 +145,7 @@ public class BatteryController extends BroadcastReceiver {
private void fireBatteryLevelChanged() {
final int N = mChangeCallbacks.size();
for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging);
}
}
@@ -121,8 +156,50 @@ public class BatteryController extends BroadcastReceiver {
}
}
- public interface BatteryStateChangeCallback {
- void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
- void onPowerSaveChanged();
+ private void fireSettingsChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryStyleChanged(mStyle, mPercentMode);
+ }
}
+
+ private final class SettingsObserver extends ContentObserver {
+ private ContentResolver mResolver;
+ private boolean mRegistered;
+
+ private final Uri STYLE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_BATTERY_STYLE);
+ private final Uri PERCENT_URI =
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT);
+
+ public SettingsObserver(Context context, Handler handler) {
+ super(handler);
+ mResolver = context.getContentResolver();
+ }
+
+ public void observe() {
+ if (mRegistered) {
+ mResolver.unregisterContentObserver(this);
+ }
+ mResolver.registerContentObserver(STYLE_URI, false, this, mUserId);
+ mResolver.registerContentObserver(PERCENT_URI, false, this, mUserId);
+ mRegistered = true;
+
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update();
+ }
+
+ private void update() {
+ mStyle = CMSettings.System.getIntForUser(mResolver,
+ CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, mUserId);
+ mPercentMode = CMSettings.System.getIntForUser(mResolver,
+ CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUserId);
+
+ fireSettingsChanged();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java
new file mode 100644
index 0000000..9fe9bb4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+public interface BatteryStateRegistar {
+ interface BatteryStateChangeCallback {
+ void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, boolean charging);
+ void onPowerSaveChanged();
+ void onBatteryStyleChanged(int style, int percentMode);
+ }
+
+ public void addStateChangedCallback(BatteryStateChangeCallback cb);
+ public void removeStateChangedCallback(BatteryStateChangeCallback cb);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 0340984..1ccf80b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -38,7 +38,7 @@ public class BrightnessMirrorController {
private final View mPanelHolder;
private final int[] mInt2Cache = new int[2];
- public BrightnessMirrorController(StatusBarWindowView statusBarWindow) {
+ public BrightnessMirrorController(View statusBarWindow) {
mScrimBehind = (ScrimView) statusBarWindow.findViewById(R.id.scrim_behind);
mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
mPanelHolder = statusBarWindow.findViewById(R.id.panel_holder);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index e618cb8..e7f65b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -126,14 +126,15 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa
public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
final int statusType, final int qsType,final boolean activityIn,
final boolean activityOut, final String typeContentDescription,
- final String description, final boolean isWide, final int subId) {
+ final String description, final boolean isWide, final boolean showSeparateRoaming,
+ final int subId) {
post(new Runnable() {
@Override
public void run() {
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType,
activityIn, activityOut, typeContentDescription, description, isWide,
- subId);
+ showSeparateRoaming, subId);
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index e344954..4d3a49f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -164,7 +164,7 @@ public class CastControllerImpl implements CastController {
@Override
public void startCasting(CastDevice device) {
- if (device == null || device.tag == null) return;
+ if (device == null || !(device.tag instanceof RouteInfo)) return;
final RouteInfo route = (RouteInfo) device.tag;
if (DEBUG) Log.d(TAG, "startCasting: " + routeToString(route));
mMediaRouter.selectRoute(ROUTE_TYPE_REMOTE_DISPLAY, route);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 61986ad..0cc82dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -34,6 +34,7 @@ import android.widget.TextView;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
+import com.android.systemui.cm.UserContentObserver;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -52,11 +53,11 @@ public class Clock extends TextView implements DemoMode {
private SimpleDateFormat mClockFormat;
private Locale mLocale;
- private static final int AM_PM_STYLE_NORMAL = 0;
- private static final int AM_PM_STYLE_SMALL = 1;
- private static final int AM_PM_STYLE_GONE = 2;
+ public static final int AM_PM_STYLE_NORMAL = 0;
+ public static final int AM_PM_STYLE_SMALL = 1;
+ public static final int AM_PM_STYLE_GONE = 2;
- private final int mAmPmStyle;
+ private int mAmPmStyle = AM_PM_STYLE_GONE;
public Clock(Context context) {
this(context, null);
@@ -68,15 +69,6 @@ public class Clock extends TextView implements DemoMode {
public Clock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- TypedArray a = context.getTheme().obtainStyledAttributes(
- attrs,
- R.styleable.Clock,
- 0, 0);
- try {
- mAmPmStyle = a.getInt(R.styleable.Clock_amPmStyle, AM_PM_STYLE_GONE);
- } finally {
- a.recycle();
- }
}
@Override
@@ -138,7 +130,7 @@ public class Clock extends TextView implements DemoMode {
};
final void updateClock() {
- if (mDemoMode) return;
+ if (mDemoMode || mCalendar == null) return;
mCalendar.setTimeInMillis(System.currentTimeMillis());
setText(getSmallTime());
}
@@ -244,5 +236,11 @@ public class Clock extends TextView implements DemoMode {
setText(getSmallTime());
}
}
+
+ public void setAmPmStyle(int style) {
+ mAmPmStyle = style;
+ mClockFormatString = "";
+ updateClock();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 186005c..720ab44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -105,11 +108,19 @@ public class DateView extends TextView {
}
mCurrentTime.setTime(System.currentTimeMillis());
-
- final String text = mDateFormat.format(mCurrentTime);
+ final String text = getDateFormat();
if (!text.equals(mLastText)) {
setText(text);
mLastText = text;
}
}
+
+ private String getDateFormat() {
+ if (getContext().getResources().getBoolean(
+ com.android.internal.R.bool.def_custom_dateformat)) {
+ return DateFormat.getDateFormat(getContext()).format(mCurrentTime);
+ } else {
+ return mDateFormat.format(mCurrentTime);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 6eb88be..9864a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -46,6 +46,7 @@ public class DeadZone extends View {
// mHold ms, then move back over the course of mDecay ms
private int mHold, mDecay;
private boolean mVertical;
+ private boolean mStartFromRight;
private long mLastPokeTime;
private final Runnable mDebugFlash = new Runnable() {
@@ -73,6 +74,7 @@ public class DeadZone extends View {
int index = a.getInt(R.styleable.DeadZone_orientation, -1);
mVertical = (index == VERTICAL);
+ mStartFromRight = false; // Assume deadzone is starting from the left side of the zone
if (DEBUG)
Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
@@ -100,6 +102,7 @@ public class DeadZone extends View {
mShouldFlash = dbg;
mFlashFrac = 0f;
postInvalidate();
+ mFlashFrac = dbg ? 1f : 0f;
}
// I made you a touch event...
@@ -117,7 +120,19 @@ public class DeadZone extends View {
Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
}
int size = (int) getSize(event.getEventTime());
- if ((mVertical && event.getX() < size) || event.getY() < size) {
+ boolean isCaptured;
+ if (mVertical && mStartFromRight) {
+ // Landscape on the left side of the screen
+ float pixelsFromRight = getWidth() - event.getX();
+ isCaptured = 0 <= pixelsFromRight && pixelsFromRight < size;
+ } else if (mVertical) {
+ // Landscape
+ isCaptured = event.getX() < size;
+ } else {
+ // Portrait
+ isCaptured = event.getY() < size;
+ }
+ if (isCaptured) {
if (CHATTY) {
Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
}
@@ -147,6 +162,11 @@ public class DeadZone extends View {
return mFlashFrac;
}
+ public void setStartFromRight(boolean startFromRight) {
+ mStartFromRight = startFromRight;
+ if (mShouldFlash) postInvalidate();
+ }
+
@Override
public void onDraw(Canvas can) {
if (!mShouldFlash || mFlashFrac <= 0f) {
@@ -154,7 +174,17 @@ public class DeadZone extends View {
}
final int size = (int) getSize(SystemClock.uptimeMillis());
- can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size);
+ if (mVertical && mStartFromRight) {
+ // Landscape on the left side of the screen
+ can.clipRect(can.getWidth() - size, 0, can.getWidth(), can.getHeight());
+ } else if (mVertical) {
+ // Landscape
+ can.clipRect(0, 0, size, can.getHeight());
+ } else {
+ // Portrait
+ can.clipRect(0, 0, can.getWidth(), size);
+ }
+
final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac;
can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java
new file mode 100644
index 0000000..3faf7d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.provider.Settings;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import cyanogenmod.providers.CMSettings;
+
+public class DockBatteryController extends BroadcastReceiver implements BatteryStateRegistar {
+
+ private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+
+ private int mLevel;
+ private boolean mPresent;
+ private boolean mPluggedIn;
+ private boolean mCharging;
+ private boolean mCharged;
+ private boolean mPowerSave;
+
+ private int mStyle;
+ private int mPercentMode;
+ private int mUserId;
+ private SettingsObserver mObserver;
+
+ public DockBatteryController(Context context, Handler handler) {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ context.registerReceiver(this, filter);
+
+ mObserver = new SettingsObserver(context, handler);
+ mObserver.observe();
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ mObserver.observe();
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("BatteryController state:");
+ pw.print(" mLevel="); pw.println(mLevel);
+ pw.print(" mPresent="); pw.println(mPresent);
+ pw.print(" mPluggedIn="); pw.println(mPluggedIn);
+ pw.print(" mCharging="); pw.println(mCharging);
+ pw.print(" mCharged="); pw.println(mCharged);
+ pw.print(" mPowerSave="); pw.println(mPowerSave);
+ }
+
+ @Override
+ public void addStateChangedCallback(BatteryStateChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+ cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging);
+ cb.onBatteryStyleChanged(mStyle, mPercentMode);
+ }
+
+ @Override
+ public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ mLevel = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100));
+ mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false);
+ mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0) != 0;
+
+ final int status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
+ mCharging = mPluggedIn && (mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING);
+
+ fireBatteryLevelChanged();
+ }
+ }
+
+ private void fireBatteryLevelChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPresent, mCharging);
+ }
+ }
+
+ private void fireSettingsChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryStyleChanged(mStyle, mPercentMode);
+ }
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private ContentResolver mResolver;
+ private boolean mRegistered;
+
+ private final Uri STYLE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_BATTERY_STYLE);
+ private final Uri PERCENT_URI =
+ CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT);
+
+ public SettingsObserver(Context context, Handler handler) {
+ super(handler);
+ mResolver = context.getContentResolver();
+ }
+
+ public void observe() {
+ if (mRegistered) {
+ mResolver.unregisterContentObserver(this);
+ }
+ mResolver.registerContentObserver(STYLE_URI, false, this, mUserId);
+ mResolver.registerContentObserver(PERCENT_URI, false, this, mUserId);
+ mRegistered = true;
+
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update();
+ }
+
+ private void update() {
+ mStyle = CMSettings.System.getIntForUser(mResolver,
+ CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, mUserId);
+ mPercentMode = CMSettings.System.getIntForUser(mResolver,
+ CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUserId);
+
+ fireSettingsChanged();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 29a8f67..52a2825 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -16,16 +16,26 @@
package com.android.systemui.statusbar.policy;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
import android.text.TextUtils;
import android.util.Log;
+import com.android.systemui.R;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -41,6 +51,12 @@ public class FlashlightController {
private static final int DISPATCH_CHANGED = 1;
private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
+ private static boolean mUseWakeLock;
+
+ private static final String ACTION_TURN_FLASHLIGHT_OFF =
+ "com.android.systemui.action.TURN_FLASHLIGHT_OFF";
+
+ private Context mContext;
private final CameraManager mCameraManager;
/** Call {@link #ensureHandler()} before using */
private Handler mHandler;
@@ -54,7 +70,28 @@ public class FlashlightController {
private final String mCameraId;
private boolean mTorchAvailable;
+ private WakeLock mWakeLock;
+
+ private Notification mNotification = null;
+ private boolean mReceiverRegistered;
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_TURN_FLASHLIGHT_OFF.equals(intent.getAction())) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ setFlashlight(false);
+ }
+ });
+ } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
+ setNotificationShown(true);
+ }
+ }
+ };
+
public FlashlightController(Context mContext) {
+ this.mContext = mContext;
mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
String cameraId = null;
@@ -67,6 +104,11 @@ public class FlashlightController {
mCameraId = cameraId;
}
+ mUseWakeLock = mContext.getResources().getBoolean(R.bool.flashlight_use_wakelock);
+
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
if (mCameraId != null) {
ensureHandler();
mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
@@ -78,12 +120,25 @@ public class FlashlightController {
synchronized (this) {
if (mFlashlightEnabled != enabled) {
mFlashlightEnabled = enabled;
+
+ if (mUseWakeLock) {
+ if (enabled) {
+ if (!mWakeLock.isHeld()) mWakeLock.acquire();
+ } else {
+ if (mWakeLock.isHeld()) mWakeLock.release();
+ }
+ }
+
try {
mCameraManager.setTorchMode(mCameraId, enabled);
} catch (CameraAccessException e) {
Log.e(TAG, "Couldn't set torch mode", e);
mFlashlightEnabled = false;
pendingError = true;
+
+ if (mUseWakeLock && mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
}
}
}
@@ -93,6 +148,56 @@ public class FlashlightController {
}
}
+ private void setNotificationShown(boolean showNotification) {
+ NotificationManager nm = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (showNotification) {
+ nm.notify(R.string.quick_settings_tile_flashlight_not_title, buildNotification());
+ } else {
+ nm.cancel(R.string.quick_settings_tile_flashlight_not_title);
+ mNotification = null;
+ }
+ }
+
+ private void setListenForScreenOff(boolean listen) {
+ if (listen && !mReceiverRegistered) {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_TURN_FLASHLIGHT_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ mContext.registerReceiver(mReceiver, filter);
+ mReceiverRegistered = true;
+ } else if (!listen) {
+ if (mReceiverRegistered) {
+ mContext.unregisterReceiver(mReceiver);
+ mReceiverRegistered = false;
+ }
+ setNotificationShown(false);
+ }
+ }
+
+ private Notification buildNotification() {
+ if (mNotification == null) {
+ Intent fireMe = new Intent(ACTION_TURN_FLASHLIGHT_OFF);
+ fireMe.addFlags(Intent.FLAG_FROM_BACKGROUND);
+ fireMe.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ fireMe.setPackage(mContext.getPackageName());
+
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, fireMe, 0);
+ mNotification = new Notification.Builder(mContext)
+ .setContentTitle(
+ mContext.getString(R.string.quick_settings_tile_flashlight_not_title))
+ .setContentText(
+ mContext.getString(R.string.quick_settings_tile_flashlight_not_summary))
+ .setAutoCancel(false)
+ .setOngoing(true)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setSmallIcon(R.drawable.ic_signal_flashlight_disable)
+ .setContentIntent(pendingIntent)
+ .build();
+ }
+ return mNotification;
+ }
+
public synchronized boolean isEnabled() {
return mFlashlightEnabled;
}
@@ -188,6 +293,7 @@ public class FlashlightController {
public void onTorchModeUnavailable(String cameraId) {
if (TextUtils.equals(cameraId, mCameraId)) {
setCameraAvailable(false);
+ setListenForScreenOff(false);
}
}
@@ -196,6 +302,7 @@ public class FlashlightController {
if (TextUtils.equals(cameraId, mCameraId)) {
setCameraAvailable(true);
setTorchMode(enabled);
+ setListenForScreenOff(enabled);
}
}
@@ -204,6 +311,11 @@ public class FlashlightController {
synchronized (FlashlightController.this) {
changed = mTorchAvailable != available;
mTorchAvailable = available;
+
+ if (mUseWakeLock && !available) {
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ }
}
if (changed) {
if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
@@ -216,6 +328,11 @@ public class FlashlightController {
synchronized (FlashlightController.this) {
changed = mFlashlightEnabled != enabled;
mFlashlightEnabled = enabled;
+
+ if (mUseWakeLock && !enabled) {
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ }
}
if (changed) {
if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 53c47dd..3d1212b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -160,6 +160,10 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
mListeners.add(listener);
}
+ public void removeListener(OnHeadsUpChangedListener listener) {
+ mListeners.remove(listener);
+ }
+
public PhoneStatusBar getBar() {
return mBar;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 3f63b5f..ed41121 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -66,16 +66,19 @@ public class KeyButtonRipple extends Drawable {
private final HashSet<Animator> mRunningAnimations = new HashSet<>();
private final ArrayList<Animator> mTmpArray = new ArrayList<>();
+ private int mRippleColor;
+
public KeyButtonRipple(Context ctx, View targetView) {
mMaxWidth = ctx.getResources().getDimensionPixelSize(R.dimen.key_button_ripple_max_width);
mTargetView = targetView;
+ mRippleColor = ctx.getResources().getColor(R.color.navbutton_ripple_color);
}
private Paint getRipplePaint() {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
mRipplePaint.setAntiAlias(true);
- mRipplePaint.setColor(0xffffffff);
+ mRipplePaint.setColor(mRippleColor);
}
return mRipplePaint;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 4d268ce..6fef3d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -18,6 +18,9 @@ package com.android.systemui.statusbar.policy;
import android.app.ActivityManager;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.ThemeConfig;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.hardware.input.InputManager;
@@ -39,28 +42,46 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.NavbarEditor;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
+import cyanogenmod.power.PerformanceManager;
+
public class KeyButtonView extends ImageView {
+ public static final int CURSOR_REPEAT_FLAGS = KeyEvent.FLAG_SOFT_KEYBOARD
+ | KeyEvent.FLAG_KEEP_TOUCH_MODE;
+
private int mContentDescriptionRes;
private long mDownTime;
private int mCode;
+ private boolean mIsSmall;
private int mTouchSlop;
private boolean mSupportsLongpress = true;
+ private boolean mInEditMode;
private AudioManager mAudioManager;
private boolean mGestureAborted;
+ private boolean mPerformedLongClick;
+
+ private PerformanceManager mPerf;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
if (isPressed()) {
// Log.d("KeyButtonView", "longpressed: " + this);
- if (isLongClickable()) {
+ if (mCode == KeyEvent.KEYCODE_DPAD_LEFT || mCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+ sendEvent(KeyEvent.ACTION_UP, CURSOR_REPEAT_FLAGS,
+ System.currentTimeMillis(), false);
+ sendEvent(KeyEvent.ACTION_DOWN, CURSOR_REPEAT_FLAGS,
+ System.currentTimeMillis(), false);
+ postDelayed(mCheckLongPress, ViewConfiguration.getKeyRepeatDelay());
+ } else if (isLongClickable()) {
// Just an old-fashioned ImageView
+ mPerformedLongClick = true;
performLongClick();
- } else if (mSupportsLongpress) {
+ } else {
sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
}
@@ -94,6 +115,7 @@ public class KeyButtonView extends ImageView {
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
setBackground(new KeyButtonRipple(context, this));
+ mPerf = PerformanceManager.getInstance(context);
}
@Override
@@ -142,7 +164,83 @@ public class KeyButtonView extends ImageView {
return super.performAccessibilityActionInternal(action, arguments);
}
+ @Override
+ public Resources getResources() {
+ ThemeConfig themeConfig = mContext.getResources().getConfiguration().themeConfig;
+ Resources res = null;
+ if (themeConfig != null) {
+ try {
+ final String navbarThemePkgName = themeConfig.getOverlayForNavBar();
+ final String sysuiThemePkgName = themeConfig.getOverlayForStatusBar();
+ // Check if the same theme is applied for systemui, if so we can skip this
+ if (navbarThemePkgName != null && !navbarThemePkgName.equals(sysuiThemePkgName)) {
+ res = mContext.getPackageManager().getThemedResourcesForApplication(
+ mContext.getPackageName(), navbarThemePkgName);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // don't care since we'll handle res being null below
+ }
+ }
+
+ return res != null ? res : super.getResources();
+ }
+
+ public void setEditMode(boolean editMode) {
+ mInEditMode = editMode;
+ updateVisibility();
+ }
+
+ public void setInfo(NavbarEditor.ButtonInfo item, boolean isVertical, boolean isSmall) {
+ final Resources res = getResources();
+ setInfo(item, isVertical, isSmall, res);
+ }
+
+ public void setInfo(NavbarEditor.ButtonInfo item, boolean isVertical, boolean isSmall,
+ Resources res) {
+ final int keyDrawableResId;
+
+ setTag(item);
+ setContentDescription(res.getString(item.contentDescription));
+ mCode = item.keyCode;
+ mIsSmall = isSmall;
+
+ if (isSmall) {
+ keyDrawableResId = item.sideResource;
+ } else if (!isVertical) {
+ keyDrawableResId = item.portResource;
+ } else {
+ keyDrawableResId = item.landResource;
+ }
+ // The reason for setImageDrawable vs setImageResource is because setImageResource calls
+ // relayout() w/o any checks. setImageDrawable performs size checks and only calls relayout
+ // if necessary. We rely on this because otherwise the setX/setY attributes which are post
+ // layout cause it to mess up the layout.
+ setImageDrawable(res.getDrawable(keyDrawableResId));
+ updateVisibility();
+ }
+
+ private void updateVisibility() {
+ if (mInEditMode) {
+ setVisibility(View.VISIBLE);
+ return;
+ }
+
+ NavbarEditor.ButtonInfo info = (NavbarEditor.ButtonInfo) getTag();
+ if (info == NavbarEditor.NAVBAR_EMPTY) {
+ setVisibility(mIsSmall ? View.INVISIBLE : View.GONE);
+ } else if (info == NavbarEditor.NAVBAR_CONDITIONAL_MENU) {
+ setVisibility(View.INVISIBLE);
+ }
+ }
+
+ private boolean supportsLongPress() {
+ return mSupportsLongpress;
+ }
+
public boolean onTouchEvent(MotionEvent ev) {
+ if (mInEditMode) {
+ return false;
+ }
final int action = ev.getAction();
int x, y;
if (action == MotionEvent.ACTION_DOWN) {
@@ -152,22 +250,32 @@ public class KeyButtonView extends ImageView {
return false;
}
+ // A lot of stuff is about to happen. Lets get ready.
+ mPerf.cpuBoost(750000);
+
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownTime = SystemClock.uptimeMillis();
setPressed(true);
- if (mCode != 0) {
+ if (mCode == KeyEvent.KEYCODE_DPAD_LEFT || mCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+ sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_VIRTUAL_HARD_KEY
+ | KeyEvent.FLAG_KEEP_TOUCH_MODE, mDownTime, false);
+ } else if (mCode != 0) {
sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
} else {
// Provide the same haptic feedback that the system offers for virtual keys.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
- removeCallbacks(mCheckLongPress);
- postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
+
+ if (supportsLongPress()) {
+ removeCallbacks(mCheckLongPress);
+ postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
+ }
+
break;
case MotionEvent.ACTION_MOVE:
- x = (int)ev.getX();
- y = (int)ev.getY();
+ x = (int) ev.getX();
+ y = (int) ev.getY();
setPressed(x >= -mTouchSlop
&& x < getWidth() + mTouchSlop
&& y >= -mTouchSlop
@@ -178,7 +286,13 @@ public class KeyButtonView extends ImageView {
if (mCode != 0) {
sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
}
+
removeCallbacks(mCheckLongPress);
+
+ if (supportsLongPress()) {
+ removeCallbacks(mCheckLongPress);
+ }
+
break;
case MotionEvent.ACTION_UP:
final boolean doIt = isPressed();
@@ -193,11 +307,17 @@ public class KeyButtonView extends ImageView {
}
} else {
// no key code, just a regular ImageView
- if (doIt) {
+ if (doIt && !mPerformedLongClick) {
performClick();
}
}
+
removeCallbacks(mCheckLongPress);
+
+ if (supportsLongPress()) {
+ removeCallbacks(mCheckLongPress);
+ }
+ mPerformedLongClick = false;
break;
}
@@ -213,10 +333,17 @@ public class KeyButtonView extends ImageView {
}
void sendEvent(int action, int flags, long when) {
+ sendEvent(action, flags, when, true);
+ }
+
+ void sendEvent(int action, int flags, long when, boolean applyDefaultFlags) {
final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
+ if (applyDefaultFlags) {
+ flags |= KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY;
+ }
final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
- flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ flags,
InputDevice.SOURCE_KEYBOARD);
InputManager.getInstance().injectInputEvent(ev,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 29a8981..a88f22d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -19,6 +19,9 @@ package com.android.systemui.statusbar.policy;
public interface LocationController {
boolean isLocationEnabled();
boolean setLocationEnabled(boolean enabled);
+ boolean setLocationMode(int mode);
+ int getLocationCurrentState();
+ boolean isAdvancedSettingsEnabled();
void addSettingsChangedCallback(LocationSettingsChangeCallback cb);
void removeSettingsChangedCallback(LocationSettingsChangeCallback cb);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 93a8fd8..e7867b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -37,6 +37,8 @@ import com.android.systemui.R;
import java.util.ArrayList;
import java.util.List;
+import cyanogenmod.providers.CMSettings;
+
/**
* A controller to manage changes of location related states and update the views accordingly.
*/
@@ -55,6 +57,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
private StatusBarManager mStatusBarManager;
private boolean mAreActiveLocationRequests;
+ private int mLastActiveMode;
private ArrayList<LocationSettingsChangeCallback> mSettingsChangeCallbacks =
new ArrayList<LocationSettingsChangeCallback>();
@@ -63,6 +66,11 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
public LocationControllerImpl(Context context, Looper bgLooper) {
mContext = context;
+ // Initialize last active mode. If state was off use the default high accuracy mode
+ mLastActiveMode = getLocationCurrentState();
+ if(mLastActiveMode == Settings.Secure.LOCATION_MODE_OFF)
+ mLastActiveMode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
+
// Register to listen for changes in location settings.
IntentFilter filter = new IntentFilter();
filter.addAction(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
@@ -107,10 +115,17 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
return false;
}
final ContentResolver cr = mContext.getContentResolver();
+
+ // Store last active mode if we are switching off
+ // so we can restore it at the next enable
+ if(!enabled) {
+ mLastActiveMode = getLocationCurrentState();
+ }
+
// When enabling location, a user consent dialog will pop up, and the
// setting won't be fully enabled until the user accepts the agreement.
int mode = enabled
- ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY : Settings.Secure.LOCATION_MODE_OFF;
+ ? mLastActiveMode : Settings.Secure.LOCATION_MODE_OFF;
// QuickSettings always runs as the owner, so specifically set the settings
// for the current foreground user.
return Settings.Secure
@@ -118,6 +133,44 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
}
/**
+ * Enable or disable location in settings to a specific mode.
+ *
+ * <p>This will attempt to enable/disable every type of location setting
+ * (e.g. high and balanced power).
+ *
+ * <p>If enabling, a user consent dialog will pop up prompting the user to accept.
+ * If the user doesn't accept, network location won't be enabled.
+ *
+ * @return true if attempt to change setting was successful.
+ */
+ public boolean setLocationMode(int mode) {
+ int currentUserId = ActivityManager.getCurrentUser();
+ if (isUserLocationRestricted(currentUserId)) {
+ return false;
+ }
+ final ContentResolver cr = mContext.getContentResolver();
+ // When enabling location, a user consent dialog will pop up, and the
+ // setting won't be fully enabled until the user accepts the agreement.
+ // QuickSettings always runs as the owner, so specifically set the settings
+ // for the current foreground user.
+ return Settings.Secure.putIntForUser(cr, Settings.Secure.LOCATION_MODE,
+ mode, currentUserId);
+ }
+
+ /**
+ * Returns int corresponding to current location mode in settings.
+ */
+ public int getLocationCurrentState() {
+ int currentUserId = ActivityManager.getCurrentUser();
+ if (isUserLocationRestricted(currentUserId)) {
+ return Settings.Secure.LOCATION_MODE_OFF;
+ }
+ final ContentResolver cr = mContext.getContentResolver();
+ return Settings.Secure.getIntForUser(cr, Settings.Secure.LOCATION_MODE,
+ Settings.Secure.LOCATION_MODE_OFF, currentUserId);
+ }
+
+ /**
* Returns true if location isn't disabled in settings.
*/
public boolean isLocationEnabled() {
@@ -130,6 +183,14 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
}
/**
+ * Check if advanced location tile is enabled in settings
+ */
+ public boolean isAdvancedSettingsEnabled() {
+ return CMSettings.Secure.getIntForUser(mContext.getContentResolver(),
+ CMSettings.Secure.QS_LOCATION_ADVANCED, 0, ActivityManager.getCurrentUser()) == 1;
+ }
+
+ /**
* Returns true if the current user is restricted from using location.
*/
private boolean isUserLocationRestricted(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ad8e3bd..b60b6c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -19,6 +19,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.NetworkCapabilities;
import android.os.Looper;
+import android.os.SystemProperties;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -159,6 +160,7 @@ public class MobileSignalController extends SignalController<
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_TD_SCDMA, TelephonyIcons.THREE_G);
if (!mConfig.showAtLeast3G) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
@@ -187,12 +189,18 @@ public class MobileSignalController extends SignalController<
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
+ if (mConfig.hspaDataDistinguishable) {
+ hGroup = TelephonyIcons.HP;
+ }
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
if (mConfig.show4gForLte) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
+ TelephonyIcons.FOUR_G_PLUS);
} else {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE);
}
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
}
@@ -231,6 +239,7 @@ public class MobileSignalController extends SignalController<
int typeIcon = showDataIcon ? icons.mDataType : 0;
mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
+ mCurrentState.showSeparateRoaming,
mSubscriptionInfo.getSubscriptionId());
}
@@ -371,6 +380,13 @@ public class MobileSignalController extends SignalController<
mCurrentState.level = mSignalStrength.getCdmaLevel();
} else {
mCurrentState.level = mSignalStrength.getLevel();
+ if (mConfig.showRsrpSignalLevelforLTE) {
+ int dataType = mServiceState.getDataNetworkType();
+ if (dataType == TelephonyManager.NETWORK_TYPE_LTE ||
+ dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
+ mCurrentState.level = getAlternateLteLevel(mSignalStrength);
+ }
+ }
}
}
if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
@@ -384,7 +400,12 @@ public class MobileSignalController extends SignalController<
if (isCarrierNetworkChangeActive()) {
mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
} else if (isRoaming()) {
- mCurrentState.iconGroup = TelephonyIcons.ROAMING;
+ mCurrentState.showSeparateRoaming = false;
+ if (SystemProperties.getBoolean("ro.config.always_show_roaming", false)) {
+ mCurrentState.showSeparateRoaming = true;
+ } else {
+ mCurrentState.iconGroup = TelephonyIcons.ROAMING;
+ }
}
if (isEmergencyOnly() != mCurrentState.isEmergency) {
mCurrentState.isEmergency = isEmergencyOnly();
@@ -399,6 +420,21 @@ public class MobileSignalController extends SignalController<
notifyListenersIfNecessary();
}
+ private int getAlternateLteLevel(SignalStrength signalStrength) {
+ int lteRsrp = signalStrength.getLteDbm();
+ int rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ if (lteRsrp > -44) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ else if (lteRsrp >= -97) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_GREAT;
+ else if (lteRsrp >= -105) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_GOOD;
+ else if (lteRsrp >= -113) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_MODERATE;
+ else if (lteRsrp >= -120) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_POOR;
+ else if (lteRsrp >= -140) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ if (DEBUG) {
+ Log.d(mTag, "getAlternateLteLevel lteRsrp:" + lteRsrp + " rsrpLevel = " + rsrpLevel);
+ }
+ return rsrpLevel;
+ }
+
@VisibleForTesting
void setActivity(int activity) {
mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
@@ -502,6 +538,7 @@ public class MobileSignalController extends SignalController<
boolean airplaneMode;
boolean carrierNetworkChangeMode;
boolean isDefault;
+ boolean showSeparateRoaming;
@Override
public void copyFrom(State s) {
@@ -515,6 +552,7 @@ public class MobileSignalController extends SignalController<
isEmergency = state.isEmergency;
airplaneMode = state.airplaneMode;
carrierNetworkChangeMode = state.carrierNetworkChangeMode;
+ showSeparateRoaming = state.showSeparateRoaming;
}
@Override
@@ -529,6 +567,7 @@ public class MobileSignalController extends SignalController<
builder.append("isEmergency=").append(isEmergency).append(',');
builder.append("airplaneMode=").append(airplaneMode).append(',');
builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode);
+ builder.append("showSeparateRoaming=").append(showSeparateRoaming);
}
@Override
@@ -541,7 +580,8 @@ public class MobileSignalController extends SignalController<
&& ((MobileState) o).isEmergency == isEmergency
&& ((MobileState) o).airplaneMode == airplaneMode
&& ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
- && ((MobileState) o).isDefault == isDefault;
+ && ((MobileState) o).isDefault == isDefault
+ && ((MobileState) o).showSeparateRoaming == showSeparateRoaming;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 38656ee..57b0dba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -40,7 +40,7 @@ public interface NetworkController {
void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
- String description, boolean isWide, int subId);
+ String description, boolean isWide, boolean showSeparateRoaming, int subId);
void setSubs(List<SubscriptionInfo> subs);
void setNoSims(boolean show);
@@ -82,7 +82,7 @@ public interface NetworkController {
public interface AccessPointCallback {
void onAccessPointsChanged(List<AccessPoint> accessPoints);
- void onSettingsActivityTriggered(Intent settingsIntent);
+ void onSettingsActivityTriggered(Intent intent);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 2996808..7e1bf05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -245,6 +245,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
}
+ public void removeEmergencyListener(EmergencyListener listener) {
+ mCallbackHandler.setListening(listener, false);
+ }
+
public boolean hasMobileDataFeature() {
return mHasMobileDataFeature;
}
@@ -751,9 +755,11 @@ public class NetworkControllerImpl extends BroadcastReceiver
datatype.equals("1x") ? TelephonyIcons.ONE_X :
datatype.equals("3g") ? TelephonyIcons.THREE_G :
datatype.equals("4g") ? TelephonyIcons.FOUR_G :
+ datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
+ datatype.equals("h+") ? TelephonyIcons.HP :
datatype.equals("lte") ? TelephonyIcons.LTE :
datatype.equals("roam") ? TelephonyIcons.ROAMING :
TelephonyIcons.UNKNOWN;
@@ -780,7 +786,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
- null, 0, 0, "");
+ null, 0, 0, "", 0);
mMobileSignalControllers.put(id, new MobileSignalController(mContext,
mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
mSubDefaults, mReceiverHandler.getLooper()));
@@ -825,6 +831,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
boolean alwaysShowCdmaRssi = false;
boolean show4gForLte = false;
boolean hspaDataDistinguishable;
+ boolean showRsrpSignalLevelforLTE;
static Config readConfig(Context context) {
Config config = new Config();
@@ -836,6 +843,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
config.hspaDataDistinguishable =
res.getBoolean(R.bool.config_hspa_data_distinguishable);
+ config.showRsrpSignalLevelforLTE =
+ res.getBoolean(R.bool.config_showRsrpSignalLevelforLTE);
return config;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
index c3bcd94..e54df32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
@@ -64,7 +64,7 @@ public final class RotationLockControllerImpl implements RotationLockController
}
public boolean isRotationLockAffordanceVisible() {
- return RotationPolicy.isRotationLockToggleVisible(mContext);
+ return RotationPolicy.isRotationSupported(mContext);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java
index dce889f..f13ef9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java
@@ -37,7 +37,7 @@ public class SignalCallbackAdapter implements SignalCallback {
@Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
- String description, boolean isWide, int subId) {
+ String description, boolean isWide, boolean showSeparateRoaming, int subId) {
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 5e9447e..72e3a06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -256,6 +256,7 @@ public abstract class SignalController<T extends SignalController.State,
IconGroup iconGroup;
int inetCondition;
int rssi; // Only for logging.
+ boolean showSeparateRoaming;
// Not used for comparison, just used for logging.
long time;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SuController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SuController.java
new file mode 100644
index 0000000..de67261
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SuController.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import java.util.List;
+
+public interface SuController {
+ void addCallback(Callback callback);
+ void removeCallback(Callback callback);
+ boolean hasActiveSessions();
+ List<String> getPackageNamesWithActiveSuSessions();
+
+ public interface Callback {
+ void onSuSessionsChanged();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SuControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SuControllerImpl.java
new file mode 100644
index 0000000..c663bab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SuControllerImpl.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.AppOpsManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A controller to manage changes to superuser-related states and update the views accordingly.
+ */
+public class SuControllerImpl implements SuController {
+ private static final String TAG = "SuControllerImpl";
+
+ private static final int[] mSuOpArray = new int[] {AppOpsManager.OP_SU};
+
+ private ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+
+ private AppOpsManager mAppOpsManager;
+
+ private List<String> mActiveSuSessions = new ArrayList<>();
+
+ public SuControllerImpl(Context context) {
+ mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(AppOpsManager.ACTION_SU_SESSION_CHANGED);
+ context.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Got change");
+ String action = intent.getAction();
+ if (AppOpsManager.ACTION_SU_SESSION_CHANGED.equals(action)) {
+ updateActiveSuSessions();
+ }
+ }
+ }, UserHandle.ALL, intentFilter, null, new Handler());
+
+ updateActiveSuSessions();
+ }
+
+ @Override
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ fireCallback(callback);
+ }
+
+ @Override
+ public void removeCallback(Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
+ @Override
+ public boolean hasActiveSessions() {
+ synchronized (mActiveSuSessions) {
+ return mActiveSuSessions.size() > 0;
+ }
+ }
+
+ private void fireCallback(Callback callback) {
+ callback.onSuSessionsChanged();
+ }
+
+ private void fireCallbacks() {
+ for (Callback callback : mCallbacks) {
+ callback.onSuSessionsChanged();
+ }
+ }
+
+ // Return the list of package names that currently have an active su session
+ @Override
+ public List<String> getPackageNamesWithActiveSuSessions() {
+ List<String> packageNames = new ArrayList<>();
+ List<AppOpsManager.PackageOps> packages
+ = mAppOpsManager.getPackagesForOps(mSuOpArray);
+ // AppOpsManager can return null when there is no requested data.
+ if (packages != null) {
+ final int numPackages = packages.size();
+ for (int packageInd = 0; packageInd < numPackages; packageInd++) {
+ AppOpsManager.PackageOps packageOp = packages.get(packageInd);
+ List<AppOpsManager.OpEntry> opEntries = packageOp.getOps();
+ if (opEntries != null) {
+ final int numOps = opEntries.size();
+ for (int opInd = 0; opInd < numOps; opInd++) {
+ AppOpsManager.OpEntry opEntry = opEntries.get(opInd);
+ if (opEntry.getOp() == AppOpsManager.OP_SU) {
+ if (opEntry.isRunning()) {
+ packageNames.add(packageOp.getPackageName());
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return packageNames;
+ }
+
+ private synchronized void updateActiveSuSessions() {
+ List<String> newList = getPackageNamesWithActiveSuSessions();
+ synchronized (mActiveSuSessions) {
+ if (!newList.equals(mActiveSuSessions)) {
+ mActiveSuSessions.clear();
+ mActiveSuSessions.addAll(newList);
+ fireCallbacks();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 83e0446..d770681 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -153,6 +153,20 @@ class TelephonyIcons {
static final int QS_DATA_H = R.drawable.ic_qs_signal_h;
+ //HSPA+
+ static final int[][] DATA_HP = {
+ { R.drawable.stat_sys_data_fully_connected_hp,
+ R.drawable.stat_sys_data_fully_connected_hp,
+ R.drawable.stat_sys_data_fully_connected_hp,
+ R.drawable.stat_sys_data_fully_connected_hp },
+ { R.drawable.stat_sys_data_fully_connected_hp,
+ R.drawable.stat_sys_data_fully_connected_hp,
+ R.drawable.stat_sys_data_fully_connected_hp,
+ R.drawable.stat_sys_data_fully_connected_hp }
+ };
+
+ static final int QS_DATA_HP = R.drawable.ic_qs_signal_hp;
+
//CDMA
// Use 3G icons for EVDO data and 1x icons for 1XRTT data
static final int[][] DATA_1X = {
@@ -182,6 +196,19 @@ class TelephonyIcons {
static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
+ static final int[][] DATA_4G_PLUS = {
+ { R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus },
+ { R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus }
+ };
+
+ static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
+
// LTE branded "LTE"
static final int[][] DATA_LTE = {
{ R.drawable.stat_sys_data_fully_connected_lte,
@@ -202,8 +229,10 @@ class TelephonyIcons {
static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
+ static final int ICON_HP = R.drawable.stat_sys_data_fully_connected_hp;
static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
+ static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
static final int ICON_CARRIER_NETWORK_CHANGE =
R.drawable.stat_sys_signal_carrier_network_change_animation;
@@ -211,6 +240,7 @@ class TelephonyIcons {
static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
+ static final int QS_ICON_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
static final int QS_ICON_CARRIER_NETWORK_CHANGE =
R.drawable.ic_qs_signal_carrier_network_change_animation;
@@ -323,12 +353,27 @@ class TelephonyIcons {
TelephonyIcons.TELEPHONY_NO_NETWORK,
TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- R.string.accessibility_data_connection_3_5g,
+ R.string.accessibility_data_connection_hspa,
TelephonyIcons.ICON_H,
false,
TelephonyIcons.QS_DATA_H
);
+ static final MobileIconGroup HP = new MobileIconGroup(
+ "HP",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_hspap,
+ TelephonyIcons.ICON_HP,
+ false,
+ TelephonyIcons.QS_DATA_HP
+ );
+
static final MobileIconGroup FOUR_G = new MobileIconGroup(
"4G",
TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
@@ -344,6 +389,21 @@ class TelephonyIcons {
TelephonyIcons.QS_DATA_4G
);
+ static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
+ "4G+",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0,0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_4g_plus,
+ TelephonyIcons.ICON_4G_PLUS,
+ true,
+ TelephonyIcons.QS_DATA_4G_PLUS
+ );
+
static final MobileIconGroup LTE = new MobileIconGroup(
"LTE",
TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
index a8d4f13..58168e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -54,6 +54,7 @@ public final class UserInfoController {
private boolean mUseDefaultAvatar;
private String mUserName;
private Drawable mUserDrawable;
+ private boolean mProfileSetup;
public UserInfoController(Context context) {
mContext = context;
@@ -73,6 +74,10 @@ public final class UserInfoController {
mCallbacks.add(callback);
}
+ public void removeListener (OnUserInfoChangedListener callback) {
+ mCallbacks.remove(callback);
+ }
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -158,24 +163,23 @@ public final class UserInfoController {
mUseDefaultAvatar = true;
}
- // If it's a single-user device, get the profile name, since the nickname is not
- // usually valid
- if (um.getUsers().size() <= 1) {
- // Try and read the display name from the local profile
- final Cursor cursor = context.getContentResolver().query(
- ContactsContract.Profile.CONTENT_URI, new String[] {
- ContactsContract.CommonDataKinds.Phone._ID,
- ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
- }, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- name = cursor.getString(cursor.getColumnIndex(
- ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
- }
- } finally {
- cursor.close();
+ mProfileSetup = false;
+
+ // Try and read the display name from the local profile
+ final Cursor cursor = context.getContentResolver().query(
+ ContactsContract.Profile.CONTENT_URI, new String[] {
+ ContactsContract.CommonDataKinds.Phone._ID,
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
+ }, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ mProfileSetup = true;
+ name = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
}
+ } finally {
+ cursor.close();
}
}
return new Pair<String, Drawable>(name, avatar);
@@ -198,6 +202,10 @@ public final class UserInfoController {
}
}
+ public boolean isProfileSetup() {
+ return mProfileSetup;
+ }
+
public interface OnUserInfoChangedListener {
public void onUserInfoChanged(String name, Drawable picture);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 3e8d4e9..38fb275 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -53,6 +53,7 @@ import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import cyanogenmod.app.StatusBarPanelCustomTile;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -587,6 +588,11 @@ public class UserSwitcherController {
}
@Override
+ public StatusBarPanelCustomTile getCustomTile() {
+ return null;
+ }
+
+ @Override
public Boolean getToggleState() {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java
new file mode 100644
index 0000000..1fa4956
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+public interface WeatherController {
+ void addCallback(Callback callback);
+ void removeCallback(Callback callback);
+ WeatherInfo getWeatherInfo();
+
+ public interface Callback {
+ void onWeatherChanged(WeatherInfo temp);
+ }
+ public static class WeatherInfo {
+ public String temp = null;
+ public String city = null;
+ public String condition = null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java
new file mode 100644
index 0000000..288bc7e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class WeatherControllerImpl implements WeatherController {
+
+ private static final String TAG = WeatherController.class.getSimpleName();
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ public static final ComponentName COMPONENT_WEATHER_FORECAST = new ComponentName(
+ "com.cyanogenmod.lockclock", "com.cyanogenmod.lockclock.weather.ForecastActivity");
+ public static final String ACTION_UPDATE_FINISHED
+ = "com.cyanogenmod.lockclock.action.WEATHER_UPDATE_FINISHED";
+ public static final String EXTRA_UPDATE_CANCELLED = "update_cancelled";
+ public static final String ACTION_FORCE_WEATHER_UPDATE
+ = "com.cyanogenmod.lockclock.action.FORCE_WEATHER_UPDATE";
+ public static final Uri CURRENT_WEATHER_URI
+ = Uri.parse("content://com.cyanogenmod.lockclock.weather.provider/weather/current");
+ public static final String[] WEATHER_PROJECTION = new String[]{
+ "temperature",
+ "city",
+ "condition"
+ };
+
+ private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+ private final Receiver mReceiver = new Receiver();
+ private final Context mContext;
+
+ private WeatherInfo mCachedInfo = new WeatherInfo();
+
+ public WeatherControllerImpl(Context context) {
+ mContext = context;
+ mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ queryWeather();
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_UPDATE_FINISHED);
+ mContext.registerReceiver(mReceiver, filter);
+ }
+
+ public void addCallback(Callback callback) {
+ if (callback == null || mCallbacks.contains(callback)) return;
+ if (DEBUG) Log.d(TAG, "addCallback " + callback);
+ mCallbacks.add(callback);
+ callback.onWeatherChanged(mCachedInfo); // immediately update with current values
+ }
+
+ public void removeCallback(Callback callback) {
+ if (callback == null) return;
+ if (DEBUG) Log.d(TAG, "removeCallback " + callback);
+ mCallbacks.remove(callback);
+ }
+
+ @Override
+ public WeatherInfo getWeatherInfo() {
+ return mCachedInfo;
+ }
+
+ private void queryWeather() {
+ Cursor c = mContext.getContentResolver().query(CURRENT_WEATHER_URI, WEATHER_PROJECTION,
+ null, null, null);
+ if (c == null) {
+ if(DEBUG) Log.e(TAG, "cursor was null for temperature, forcing weather update");
+ mContext.sendBroadcast(new Intent(ACTION_FORCE_WEATHER_UPDATE));
+ } else {
+ try {
+ c.moveToFirst();
+ mCachedInfo.temp = c.getString(0);
+ mCachedInfo.city = c.getString(1);
+ mCachedInfo.condition = c.getString(2);
+ } finally {
+ c.close();
+ }
+ }
+ }
+
+ private void fireCallback() {
+ for (Callback callback : mCallbacks) {
+ callback.onWeatherChanged(mCachedInfo);
+ }
+ }
+
+ private final class Receiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
+ if (intent.hasExtra(EXTRA_UPDATE_CANCELLED)) {
+ if (intent.getBooleanExtra(EXTRA_UPDATE_CANCELLED, false)) {
+ // no update
+ return;
+ }
+ }
+ queryWeather();
+ fireCallback();
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index af38f5f..2f04b42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -53,6 +53,8 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ScrollAdapter;
+import cyanogenmod.power.PerformanceManager;
+
import java.util.ArrayList;
import java.util.HashSet;
@@ -208,6 +210,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private boolean mDelegateToScrollView;
private boolean mDisallowScrollingInThisMotion;
private long mGoToFullShadeDelay;
+
private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -839,6 +842,7 @@ public class NotificationStackScrollLayout extends ViewGroup
&& !mOnlyScrollingInThisMotion) {
horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
}
+
return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index cf696a1..93995f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -42,6 +42,8 @@ public class StackScrollAlgorithm {
private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
private static final int MAX_ITEMS_IN_TOP_STACK = 3;
+ private static final int DEFAULT_CORNER_RADIUS = 2;
+
public static final float DIMMED_SCALE = 0.95f;
private int mPaddingBetweenElements;
@@ -72,6 +74,7 @@ public class StackScrollAlgorithm {
private int mMaxNotificationHeight;
private boolean mScaleDimmed;
private HeadsUpManager mHeadsUpManager;
+ private boolean mPerformClipping;
public StackScrollAlgorithm(Context context) {
initConstants(context);
@@ -128,6 +131,12 @@ public class StackScrollAlgorithm {
R.dimen.notification_collapse_second_card_padding);
mScaleDimmed = context.getResources().getDisplayMetrics().densityDpi
>= DisplayMetrics.DENSITY_420;
+
+ // We don't want to clip the notification if a theme overrides the corner radius with
+ // a value larger than the default.
+ mPerformClipping = context.getResources()
+ .getDimension(R.dimen.notification_material_rounded_rect_radius) <=
+ DEFAULT_CORNER_RADIUS * context.getResources().getDisplayMetrics().density;
}
public boolean shouldScaleDimmed() {
@@ -228,8 +237,7 @@ public class StackScrollAlgorithm {
// In the unlocked shade we have to clip a little bit higher because of the rounded
// corners of the notifications, but only if we are not fully overlapped by
// the top card.
- float clippingCorrection = state.dimmed
- ? 0
+ float clippingCorrection = state.dimmed ? (mPerformClipping ? 0 : newHeight)
: mRoundedRectCornerRadius * state.scale;
clipHeight += clippingCorrection;
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index 37ac098..9d63d08 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -15,14 +15,23 @@
*/
package com.android.systemui.tuner;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.Context;
import android.content.DialogInterface;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings.Secure;
+import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.Log;
import android.view.DragEvent;
@@ -30,11 +39,9 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnDragListener;
-import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
@@ -42,6 +49,8 @@ import android.widget.ScrollView;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
+import com.android.systemui.qs.QSDragPanel;
+import com.android.systemui.qs.QSPage;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTile.Host.Callback;
@@ -52,6 +61,7 @@ import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.policy.SecurityController;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class QsTuner extends Fragment implements Callback {
@@ -59,16 +69,13 @@ public class QsTuner extends Fragment implements Callback {
private static final String TAG = "QsTuner";
private static final int MENU_RESET = Menu.FIRST;
+ private static final int MENU_EDIT = Menu.FIRST + 1;
private DraggableQsPanel mQsPanel;
private CustomHost mTileHost;
- private FrameLayout mDropTarget;
-
private ScrollView mScrollRoot;
- private FrameLayout mAddTarget;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -78,6 +85,7 @@ public class QsTuner extends Fragment implements Callback {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_RESET, 0, com.android.internal.R.string.reset);
+ menu.add(0, MENU_EDIT, 0, "toggle edit");
}
public void onResume() {
@@ -93,8 +101,11 @@ public class QsTuner extends Fragment implements Callback {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
+ case MENU_EDIT:
+ mQsPanel.setEditing(!mQsPanel.isEditing());
+ break;
case MENU_RESET:
- mTileHost.reset();
+ mTileHost.resetTiles();
break;
case android.R.id.home:
getFragmentManager().popBackStack();
@@ -105,7 +116,7 @@ public class QsTuner extends Fragment implements Callback {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ Bundle savedInstanceState) {
mScrollRoot = (ScrollView) inflater.inflate(R.layout.tuner_qs, container, false);
mQsPanel = new DraggableQsPanel(getContext());
@@ -116,10 +127,6 @@ public class QsTuner extends Fragment implements Callback {
mQsPanel.refreshAllTiles();
((ViewGroup) mScrollRoot.findViewById(R.id.all_details)).addView(mQsPanel, 0);
- mDropTarget = (FrameLayout) mScrollRoot.findViewById(R.id.remove_target);
- setupDropTarget();
- mAddTarget = (FrameLayout) mScrollRoot.findViewById(R.id.add_target);
- setupAddTarget();
return mScrollRoot;
}
@@ -129,78 +136,27 @@ public class QsTuner extends Fragment implements Callback {
super.onDestroyView();
}
- private void setupDropTarget() {
- QSTileView tileView = new QSTileView(getContext());
- QSTile.State state = new QSTile.State();
- state.visible = true;
- state.icon = ResourceIcon.get(R.drawable.ic_delete);
- state.label = getString(com.android.internal.R.string.delete);
- tileView.onStateChanged(state);
- mDropTarget.addView(tileView);
- mDropTarget.setVisibility(View.GONE);
- new DragHelper(tileView, new DropListener() {
- @Override
- public void onDrop(String sourceText) {
- mTileHost.remove(sourceText);
- }
- });
- }
-
- private void setupAddTarget() {
- QSTileView tileView = new QSTileView(getContext());
- QSTile.State state = new QSTile.State();
- state.visible = true;
- state.icon = ResourceIcon.get(R.drawable.ic_add_circle_qs);
- state.label = getString(R.string.add_tile);
- tileView.onStateChanged(state);
- mAddTarget.addView(tileView);
- tileView.setClickable(true);
- tileView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mTileHost.showAddDialog();
- }
- });
+ @Override
+ public void onTilesChanged() {
+ mQsPanel.setTiles(mTileHost.getTiles());
}
- public void onStartDrag() {
- mDropTarget.post(new Runnable() {
- @Override
- public void run() {
- mDropTarget.setVisibility(View.VISIBLE);
- mAddTarget.setVisibility(View.GONE);
- }
- });
+ @Override
+ public void setEditing(boolean editing) {
+ mQsPanel.setEditing(editing);
}
- public void stopDrag() {
- mDropTarget.post(new Runnable() {
- @Override
- public void run() {
- mDropTarget.setVisibility(View.GONE);
- mAddTarget.setVisibility(View.VISIBLE);
- }
- });
+ @Override
+ public boolean isEditing() {
+ return mTileHost.isEditing();
}
@Override
- public void onTilesChanged() {
- mQsPanel.setTiles(mTileHost.getTiles());
+ public void goToSettingsPage() {
}
- private static int getLabelResource(String spec) {
- if (spec.equals("wifi")) return R.string.quick_settings_wifi_label;
- else if (spec.equals("bt")) return R.string.quick_settings_bluetooth_label;
- else if (spec.equals("inversion")) return R.string.quick_settings_inversion_label;
- else if (spec.equals("cell")) return R.string.quick_settings_cellular_detail_title;
- else if (spec.equals("airplane")) return R.string.airplane_mode;
- else if (spec.equals("dnd")) return R.string.quick_settings_dnd_label;
- else if (spec.equals("rotation")) return R.string.quick_settings_rotation_locked_label;
- else if (spec.equals("flashlight")) return R.string.quick_settings_flashlight_label;
- else if (spec.equals("location")) return R.string.quick_settings_location_label;
- else if (spec.equals("cast")) return R.string.quick_settings_cast_title;
- else if (spec.equals("hotspot")) return R.string.quick_settings_hotspot_label;
- return 0;
+ @Override
+ public void resetTiles() {
}
private static class CustomHost extends QSTileHost {
@@ -211,7 +167,7 @@ public class QsTuner extends Fragment implements Callback {
}
@Override
- protected QSTile<?> createTile(String tileSpec) {
+ public QSTile<?> createTile(String tileSpec) {
return new DraggableTile(this, tileSpec);
}
@@ -232,97 +188,6 @@ public class QsTuner extends Fragment implements Callback {
setTiles(order);
}
- public void remove(String tile) {
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REMOVE, tile);
- List<String> tiles = new ArrayList<>(mTileSpecs);
- tiles.remove(tile);
- setTiles(tiles);
- }
-
- public void add(String tile) {
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_ADD, tile);
- List<String> tiles = new ArrayList<>(mTileSpecs);
- tiles.add(tile);
- setTiles(tiles);
- }
-
- public void reset() {
- Secure.putStringForUser(getContext().getContentResolver(),
- TILES_SETTING, "default", ActivityManager.getCurrentUser());
- }
-
- private void setTiles(List<String> tiles) {
- Secure.putStringForUser(getContext().getContentResolver(), TILES_SETTING,
- TextUtils.join(",", tiles), ActivityManager.getCurrentUser());
- }
-
- public void showAddDialog() {
- List<String> tiles = mTileSpecs;
- int numBroadcast = 0;
- for (int i = 0; i < tiles.size(); i++) {
- if (tiles.get(i).startsWith(IntentTile.PREFIX)) {
- numBroadcast++;
- }
- }
- String[] defaults =
- getContext().getString(R.string.quick_settings_tiles_default).split(",");
- final String[] available = new String[defaults.length + 1
- - (tiles.size() - numBroadcast)];
- final String[] availableTiles = new String[available.length];
- int index = 0;
- for (int i = 0; i < defaults.length; i++) {
- if (tiles.contains(defaults[i])) {
- continue;
- }
- int resource = getLabelResource(defaults[i]);
- if (resource != 0) {
- availableTiles[index] = defaults[i];
- available[index++] = getContext().getString(resource);
- } else {
- availableTiles[index] = defaults[i];
- available[index++] = defaults[i];
- }
- }
- available[index++] = getContext().getString(R.string.broadcast_tile);
- new AlertDialog.Builder(getContext())
- .setTitle(R.string.add_tile)
- .setItems(available, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (which < available.length - 1) {
- add(availableTiles[which]);
- } else {
- showBroadcastTileDialog();
- }
- }
- }).show();
- }
-
- public void showBroadcastTileDialog() {
- final EditText editText = new EditText(getContext());
- new AlertDialog.Builder(getContext())
- .setTitle(R.string.broadcast_tile)
- .setView(editText)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- String action = editText.getText().toString();
- if (isValid(action)) {
- add(IntentTile.PREFIX + action + ')');
- }
- }
- }).show();
- }
-
- private boolean isValid(String action) {
- for (int i = 0; i < action.length(); i++) {
- char c = action.charAt(i);
- if (!Character.isAlphabetic(c) && !Character.isDigit(c) && c != '.') {
- return false;
- }
- }
- return true;
- }
-
private static class BlankSecurityController implements SecurityController {
@Override
public boolean hasDeviceOwner() {
@@ -373,8 +238,7 @@ public class QsTuner extends Fragment implements Callback {
}
}
- private static class DraggableTile extends QSTile<QSTile.State>
- implements DropListener {
+ public static class DraggableTile extends QSTile<QSTile.State> {
private String mSpec;
private QSTileView mView;
@@ -391,7 +255,7 @@ public class QsTuner extends Fragment implements Callback {
}
@Override
- public boolean supportsDualTargets() {
+ public boolean hasDualTargetsDetails() {
return "wifi".equals(mSpec) || "bt".equals(mSpec);
}
@@ -416,7 +280,7 @@ public class QsTuner extends Fragment implements Callback {
}
private String getLabel() {
- int resource = getLabelResource(mSpec);
+ int resource = QSTileHost.getLabelResource(mSpec);
if (resource != 0) {
return mContext.getString(resource);
}
@@ -443,6 +307,7 @@ public class QsTuner extends Fragment implements Callback {
else if (mSpec.equals("location")) return R.drawable.ic_signal_location_enable;
else if (mSpec.equals("cast")) return R.drawable.ic_qs_cast_on;
else if (mSpec.equals("hotspot")) return R.drawable.ic_hotspot_enable;
+ else if (mSpec.equals("adb_network")) return R.drawable.ic_qs_network_adb_on;
return R.drawable.android;
}
@@ -460,81 +325,19 @@ public class QsTuner extends Fragment implements Callback {
}
@Override
- public void onDrop(String sourceText) {
- ((CustomHost) mHost).replace(mSpec, sourceText);
- }
-
- }
-
- private class DragHelper implements OnDragListener {
-
- private final View mView;
- private final DropListener mListener;
-
- public DragHelper(View view, DropListener dropListener) {
- mView = view;
- mListener = dropListener;
- mView.setOnDragListener(this);
- }
-
- @Override
- public boolean onDrag(View v, DragEvent event) {
- switch (event.getAction()) {
- case DragEvent.ACTION_DRAG_ENTERED:
- mView.setBackgroundColor(0x77ffffff);
- break;
- case DragEvent.ACTION_DRAG_ENDED:
- stopDrag();
- case DragEvent.ACTION_DRAG_EXITED:
- mView.setBackgroundColor(0x0);
- break;
- case DragEvent.ACTION_DROP:
- stopDrag();
- String text = event.getClipData().getItemAt(0).getText().toString();
- mListener.onDrop(text);
- break;
- }
- return true;
+ public String toString() {
+ return mSpec;
}
-
}
- public interface DropListener {
- void onDrop(String sourceText);
- }
+ private class DraggableQsPanel extends QSDragPanel {
- private class DraggableQsPanel extends QSPanel implements OnTouchListener {
public DraggableQsPanel(Context context) {
super(context);
- mBrightnessView.setVisibility(View.GONE);
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- for (TileRecord r : mRecords) {
- new DragHelper(r.tileView, (DraggableTile) r.tile);
- r.tileView.setTag(r.tile);
- r.tileView.setOnTouchListener(this);
-
- for (int i = 0; i < r.tileView.getChildCount(); i++) {
- r.tileView.getChildAt(i).setClickable(false);
- }
- }
+ setEditing(true);
}
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- String tileSpec = (String) ((DraggableTile) v.getTag()).mSpec;
- ClipData data = ClipData.newPlainText(tileSpec, tileSpec);
- v.startDrag(data, new View.DragShadowBuilder(v), null, 0);
- onStartDrag();
- return true;
- }
- return false;
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java
new file mode 100644
index 0000000..c339541
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.tuner;
+
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+
+import android.preference.PreferenceGroup;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+
+public class StatusBarIconBlacklistFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.tuner_statusbar_icons);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ registerPrefs(getPreferenceScreen());
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ unregisterPrefs(getPreferenceScreen());
+ }
+
+ private void registerPrefs(PreferenceGroup group) {
+ TunerService tunerService = TunerService.get(getContext());
+ final int N = group.getPreferenceCount();
+ for (int i = 0; i < N; i++) {
+ Preference pref = group.getPreference(i);
+ if (pref instanceof StatusBarSwitch) {
+ tunerService.addTunable((TunerService.Tunable) pref, StatusBarIconController.ICON_BLACKLIST);
+ } else if (pref instanceof PreferenceGroup) {
+ registerPrefs((PreferenceGroup) pref);
+ }
+ }
+ }
+
+ private void unregisterPrefs(PreferenceGroup group) {
+ TunerService tunerService = TunerService.get(getContext());
+ final int N = group.getPreferenceCount();
+ for (int i = 0; i < N; i++) {
+ Preference pref = group.getPreference(i);
+ if (pref instanceof TunerService.Tunable) {
+ tunerService.removeTunable((TunerService.Tunable) pref);
+ } else if (pref instanceof PreferenceGroup) {
+ registerPrefs((PreferenceGroup) pref);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index c84f618..401fb0e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -16,7 +16,9 @@
package com.android.systemui.tuner;
import android.app.Activity;
+import android.app.Fragment;
import android.os.Bundle;
+import android.view.MenuItem;
public class TunerActivity extends Activity {
@@ -27,4 +29,43 @@ public class TunerActivity extends Activity {
.commit();
}
+ /**
+ * Base class for direct entry points into
+ * tuner fragments
+ */
+ private static abstract class FragmentTunerActivityBase extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ getFragmentManager().beginTransaction().replace(android.R.id.content,
+ getFragment()).commit();
+ }
+
+ protected abstract Fragment getFragment();
+
+ @Override
+ public final boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ public static final class DemoModeActivity extends FragmentTunerActivityBase {
+ @Override
+ protected Fragment getFragment() {
+ return new DemoModeFragment();
+ }
+ }
+
+ public static final class StatusBarIconActivity extends FragmentTunerActivityBase {
+ @Override
+ protected Fragment getFragment() {
+ return new StatusBarIconBlacklistFragment();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 71b5de5..0bc663b 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.tuner;
-import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
-
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
@@ -46,18 +44,13 @@ public class TunerFragment extends PreferenceFragment {
private static final String TAG = "TunerFragment";
- private static final String KEY_QS_TUNER = "qs_tuner";
+ private static final String KEY_STATUSBAR_BLACKLIST = "statusbar_icon_blacklist";
private static final String KEY_DEMO_MODE = "demo_mode";
- private static final String KEY_BATTERY_PCT = "battery_pct";
public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning";
private static final int MENU_REMOVE = Menu.FIRST + 1;
- private final SettingObserver mSettingObserver = new SettingObserver();
-
- private SwitchPreference mBatteryPct;
-
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -65,11 +58,12 @@ public class TunerFragment extends PreferenceFragment {
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
setHasOptionsMenu(true);
- findPreference(KEY_QS_TUNER).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ findPreference(KEY_STATUSBAR_BLACKLIST).setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.replace(android.R.id.content, new QsTuner(), "QsTuner");
+ ft.replace(android.R.id.content, new StatusBarIconBlacklistFragment(),
+ "StatusBarBlacklist");
ft.addToBackStack(null);
ft.commit();
return true;
@@ -85,7 +79,6 @@ public class TunerFragment extends PreferenceFragment {
return true;
}
});
- mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT);
if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
0) == 0) {
new AlertDialog.Builder(getContext())
@@ -104,9 +97,6 @@ public class TunerFragment extends PreferenceFragment {
@Override
public void onResume() {
super.onResume();
- updateBatteryPct();
- getContext().getContentResolver().registerContentObserver(
- System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
registerPrefs(getPreferenceScreen());
MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true);
@@ -115,7 +105,6 @@ public class TunerFragment extends PreferenceFragment {
@Override
public void onPause() {
super.onPause();
- getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
unregisterPrefs(getPreferenceScreen());
MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
@@ -169,33 +158,4 @@ public class TunerFragment extends PreferenceFragment {
}
return super.onOptionsItemSelected(item);
}
-
- private void updateBatteryPct() {
- mBatteryPct.setOnPreferenceChangeListener(null);
- mBatteryPct.setChecked(System.getInt(getContext().getContentResolver(),
- SHOW_PERCENT_SETTING, 0) != 0);
- mBatteryPct.setOnPreferenceChangeListener(mBatteryPctChange);
- }
-
- private final class SettingObserver extends ContentObserver {
- public SettingObserver() {
- super(new Handler());
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- super.onChange(selfChange, uri, userId);
- updateBatteryPct();
- }
- }
-
- private final OnPreferenceChangeListener mBatteryPctChange = new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean v = (Boolean) newValue;
- MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v);
- System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0);
- return true;
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 50234b2..b2c90be 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -31,6 +31,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArrayMap;
import com.android.systemui.BatteryMeterView;
@@ -40,6 +41,7 @@ import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import cyanogenmod.providers.CMSettings;
import java.util.ArrayList;
import java.util.HashMap;
@@ -84,17 +86,31 @@ public class TunerService extends SystemUI {
}
private void addTunable(Tunable tunable, String key) {
+ addTunableByProvider(tunable, key, false);
+ }
+
+ public void addTunableByProvider(Tunable tunable, String key, boolean cm) {
if (!mTunableLookup.containsKey(key)) {
mTunableLookup.put(key, new ArrayList<Tunable>());
}
mTunableLookup.get(key).add(tunable);
- Uri uri = Settings.Secure.getUriFor(key);
+ Uri uri;
+ if (!cm) {
+ uri = Settings.Secure.getUriFor(key);
+ } else {
+ uri = CMSettings.Secure.getUriFor(key);
+ }
if (!mListeningUris.containsKey(uri)) {
mListeningUris.put(uri, key);
mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
}
// Send the first state.
- String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ String value;
+ if (cm) {
+ value = CMSettings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ } else {
+ value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ }
tunable.onTuningChanged(key, value);
}
@@ -116,7 +132,12 @@ public class TunerService extends SystemUI {
public void reloadSetting(Uri uri) {
String key = mListeningUris.get(uri);
- String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ String value;
+ if (uri.getAuthority().equals(CMSettings.AUTHORITY)) {
+ value = CMSettings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ } else {
+ value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ }
for (Tunable tunable : mTunableLookup.get(key)) {
tunable.onTuningChanged(key, value);
}
@@ -124,8 +145,14 @@ public class TunerService extends SystemUI {
private void reloadAll() {
for (String key : mTunableLookup.keySet()) {
- String value = Settings.Secure.getStringForUser(mContentResolver, key,
- mCurrentUser);
+ String value;
+ Uri uri = CMSettings.Secure.getUriFor(key);
+ if (uri.getAuthority() != null && uri.getAuthority().equals(CMSettings.AUTHORITY)) {
+ value = CMSettings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ } else {
+ value = Settings.Secure.getStringForUser(mContentResolver, key,
+ mCurrentUser);
+ }
for (Tunable tunable : mTunableLookup.get(key)) {
tunable.onTuningChanged(key, value);
}
@@ -135,13 +162,17 @@ public class TunerService extends SystemUI {
public void clearAll() {
// A couple special cases.
Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
- Settings.System.putString(mContentResolver, BatteryMeterView.SHOW_PERCENT_SETTING, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
mContext.sendBroadcast(intent);
for (String key : mTunableLookup.keySet()) {
- Settings.Secure.putString(mContentResolver, key, null);
+ Uri uri = CMSettings.Secure.getUriFor(key);
+ if (uri.getAuthority() != null && uri.getAuthority().equals(CMSettings.AUTHORITY)) {
+ CMSettings.Secure.putString(mContentResolver, key, null);
+ } else {
+ Settings.Secure.putString(mContentResolver, key, null);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 180d918..7d34cdc 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -256,6 +256,11 @@ public class StorageNotification extends SystemUI {
}
private void onPublicVolumeStateChangedInternal(VolumeInfo vol) {
+ // Do not notify for volumes on non-removable disks
+ if (vol.disk.isNonRemovable()) {
+ return;
+ }
+
Log.d(TAG, "Notifying about public volume: " + vol.toString());
final Notification notif;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index e9f1095..27c6601 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -31,6 +31,7 @@ import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.ColorDrawable;
@@ -42,6 +43,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -128,9 +130,10 @@ public class VolumeDialog {
private boolean mPendingStateChanged;
private boolean mPendingRecheckAll;
private long mCollapseTime;
+ private int mLastActiveStream;
public VolumeDialog(Context context, int windowType, VolumeDialogController controller,
- ZenModeController zenModeController, Callback callback) {
+ ZenModeController zenModeController, Callback callback) {
mContext = context;
mController = controller;
mCallback = callback;
@@ -163,7 +166,7 @@ public class VolumeDialog {
window.setAttributes(lp);
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
- mActiveSliderTint = loadColorStateList(R.color.system_accent_color);
+ mActiveSliderTint = loadColorStateList(R.color.volume_slider_active);
mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
mDialog.setContentView(R.layout.volume_dialog);
mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
@@ -177,19 +180,19 @@ public class VolumeDialog {
mDialogContentView.setLayoutTransition(mLayoutTransition);
mMotion = new VolumeDialogMotion(mDialog, mDialogView, mDialogContentView, mExpandButton,
new VolumeDialogMotion.Callback() {
- @Override
- public void onAnimatingChanged(boolean animating) {
- if (animating) return;
- if (mPendingStateChanged) {
- mHandler.sendEmptyMessage(H.STATE_CHANGED);
- mPendingStateChanged = false;
- }
- if (mPendingRecheckAll) {
- mHandler.sendEmptyMessage(H.RECHECK_ALL);
- mPendingRecheckAll = false;
- }
- }
- });
+ @Override
+ public void onAnimatingChanged(boolean animating) {
+ if (animating) return;
+ if (mPendingStateChanged) {
+ mHandler.sendEmptyMessage(H.STATE_CHANGED);
+ mPendingStateChanged = false;
+ }
+ if (mPendingRecheckAll) {
+ mHandler.sendEmptyMessage(H.RECHECK_ALL);
+ mPendingRecheckAll = false;
+ }
+ }
+ });
addRow(AudioManager.STREAM_RING,
R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true);
@@ -272,11 +275,15 @@ public class VolumeDialog {
row.settingsButton.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- final boolean moved = oldLeft != left || oldTop != top;
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ final boolean moved = mLastActiveStream != mActiveStream ||
+ oldLeft != left || oldTop != top;
if (D.BUG) Log.d(TAG, "onLayoutChange moved=" + moved
+ " old=" + new Rect(oldLeft, oldTop, oldRight, oldBottom).toShortString()
- + " new=" + new Rect(left,top,right,bottom).toShortString());
+ + "," + mLastActiveStream
+ + " new=" + new Rect(left,top,right,bottom).toShortString()
+ + "," + mActiveStream);
+ mLastActiveStream = mActiveStream;
if (moved) {
for (int i = 0; i < mDialogContentView.getChildCount(); i++) {
final View c = mDialogContentView.getChildAt(i);
@@ -362,6 +369,8 @@ public class VolumeDialog {
row.header = (TextView) row.view.findViewById(R.id.volume_row_header);
mSpTexts.add(row.header);
row.slider = (SeekBar) row.view.findViewById(R.id.volume_row_slider);
+ row.slider.setProgressTintMode(PorterDuff.Mode.SRC_ATOP);
+ row.slider.setThumbTintMode(PorterDuff.Mode.SRC_ATOP);
row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
// forward events above the slider into the slider
@@ -597,13 +606,17 @@ public class VolumeDialog {
final VolumeRow row = mRows.get(i);
if (row.ss == null || !row.ss.dynamic) continue;
if (!mDynamic.get(row.stream)) {
- mRows.remove(i);
- mDialogContentView.removeView(row.view);
- mDialogContentView.removeView(row.space);
+ removeRow(row);
}
}
}
+ private void removeRow(VolumeRow volumeRow) {
+ mRows.remove(volumeRow);
+ mDialogContentView.removeView(volumeRow.view);
+ mDialogContentView.removeView(volumeRow.space);
+ }
+
private void onStateChangedH(State state) {
final boolean animating = mMotion.isAnimating();
if (D.BUG) Log.d(TAG, "onStateChangedH animating=" + animating);
@@ -624,6 +637,8 @@ public class VolumeDialog {
}
}
+ updateNotificationRowH();
+
if (mActiveStream != state.activeStream) {
mActiveStream = state.activeStream;
updateRowsH();
@@ -635,6 +650,19 @@ public class VolumeDialog {
updateFooterH();
}
+ private void updateNotificationRowH() {
+ VolumeRow notificationRow = findRow(AudioManager.STREAM_NOTIFICATION);
+ if (notificationRow != null) {
+ if (mState.linkedNotification) {
+ removeRow(notificationRow);
+ }
+ } else if (!mState.linkedNotification) {
+ addRow(AudioManager.STREAM_NOTIFICATION,
+ R.drawable.ic_volume_notification, R.drawable.ic_volume_notification_mute,
+ true);
+ }
+ }
+
private void updateFooterH() {
if (D.BUG) Log.d(TAG, "updateFooterH");
final boolean wasVisible = mZenFooter.getVisibility() == View.VISIBLE;
@@ -663,8 +691,9 @@ public class VolumeDialog {
final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC;
- final boolean isRingVibrate = isRingStream
- && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
+ final boolean isNotificationStream = row.stream == AudioManager.STREAM_NOTIFICATION;
+ final boolean isVibrate = mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
+ final boolean isRingVibrate = isRingStream && isVibrate;
final boolean isRingSilent = isRingStream
&& mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
@@ -672,8 +701,9 @@ public class VolumeDialog {
final boolean isZenPriority = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
final boolean isRingZenNone = (isRingStream || isSystemStream) && isZenNone;
final boolean isRingLimited = isRingStream && isZenPriority;
- final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
- : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream)
+ final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream || isNotificationStream)
+ : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream || isNotificationStream)
+ : isVibrate ? (isNotificationStream)
: false;
// update slider max
@@ -708,12 +738,12 @@ public class VolumeDialog {
row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
final int iconRes =
isRingVibrate ? R.drawable.ic_volume_ringer_vibrate
- : isRingSilent || zenMuted ? row.cachedIconRes
- : ss.routedToBluetooth ?
+ : isRingSilent || zenMuted ? row.cachedIconRes
+ : ss.routedToBluetooth ?
(ss.muted ? R.drawable.ic_volume_media_bt_mute
: R.drawable.ic_volume_media_bt)
- : mAutomute && ss.level == 0 ? row.iconMuteRes
- : (ss.muted ? row.iconMuteRes : row.iconRes);
+ : mAutomute && ss.level == 0 ? row.iconMuteRes
+ : (ss.muted ? row.iconMuteRes : row.iconRes);
if (iconRes != row.cachedIconRes) {
if (row.cachedIconRes != 0 && isRingVibrate) {
mController.vibrate();
@@ -723,11 +753,11 @@ public class VolumeDialog {
}
row.iconState =
iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
- : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
+ : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
? Events.ICON_STATE_MUTE
- : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes)
+ : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes)
? Events.ICON_STATE_UNMUTE
- : Events.ICON_STATE_UNKNOWN;
+ : Events.ICON_STATE_UNKNOWN;
row.icon.setContentDescription(ss.name);
// update slider
@@ -934,6 +964,12 @@ public class VolumeDialog {
}
};
+ public void cleanup() {
+ mController.removeCallback(mControllerCallbackH);
+ mZenFooter.cleanup();
+ mAccessibility.cleanup();
+ }
+
private final class H extends Handler {
private static final int SHOW = 1;
private static final int DISMISS = 2;
@@ -1056,36 +1092,21 @@ public class VolumeDialog {
public void init() {
mMgr = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- mDialogView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
- @Override
- public void onViewDetachedFromWindow(View v) {
- if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow");
- // noop
- }
-
- @Override
- public void onViewAttachedToWindow(View v) {
- if (D.BUG) Log.d(TAG, "onViewAttachedToWindow");
- updateFeedbackEnabled();
- }
- });
- mDialogView.setAccessibilityDelegate(this);
- mMgr.addAccessibilityStateChangeListener(new AccessibilityStateChangeListener() {
- @Override
- public void onAccessibilityStateChanged(boolean enabled) {
- updateFeedbackEnabled();
- }
- });
+ mDialogView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
updateFeedbackEnabled();
}
@Override
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
- AccessibilityEvent event) {
+ AccessibilityEvent event) {
rescheduleTimeoutH();
return super.onRequestSendAccessibilityEvent(host, child, event);
}
+ public void cleanup() {
+ mDialogView.removeOnAttachStateChangeListener(mOnAttachStateChangeListener);
+ }
+
private void updateFeedbackEnabled() {
mFeedbackEnabled = computeFeedbackEnabled();
}
@@ -1101,6 +1122,21 @@ public class VolumeDialog {
}
return false;
}
+
+ private OnAttachStateChangeListener mOnAttachStateChangeListener =
+ new OnAttachStateChangeListener() {
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow");
+ // noop
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (D.BUG) Log.d(TAG, "onViewAttachedToWindow");
+ updateFeedbackEnabled();
+ }
+ };
}
private static class VolumeRow {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 1083f40..742b18b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -43,7 +43,7 @@ public class VolumeDialogComponent implements VolumeComponent {
private final Context mContext;
private final VolumeDialogController mController;
private final ZenModeController mZenModeController;
- private final VolumeDialog mDialog;
+ private VolumeDialog mDialog;
private final VolumePolicy mVolumePolicy = new VolumePolicy(
true, // volumeDownToEnterSilent
true, // volumeUpToExitSilent
@@ -138,4 +138,11 @@ public class VolumeDialogComponent implements VolumeComponent {
}
};
+ public void recreateDialog() {
+ if (mDialog != null) mDialog.cleanup();
+
+ mDialog = new VolumeDialog(mContext, WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY,
+ mController, mZenModeController, mVolumeDialogCallback);
+ applyConfiguration();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
index 32d6805..7279d1f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -29,6 +29,7 @@ import android.database.ContentObserver;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IVolumeController;
+import android.media.ToneGenerator;
import android.media.VolumePolicy;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession.Token;
@@ -54,6 +55,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
+import cyanogenmod.providers.CMSettings;
+
/**
* Source of truth for all state / events related to the volume dialog. No presentation.
*
@@ -67,6 +70,9 @@ public class VolumeDialogController {
private static final int DYNAMIC_STREAM_START_INDEX = 100;
private static final int VIBRATE_HINT_DURATION = 50;
+ private static final int FREE_DELAY = 10000;
+ private static final int BEEP_DURATION = 150;
+
private static final int[] STREAMS = {
AudioSystem.STREAM_ALARM,
AudioSystem.STREAM_BLUETOOTH_SCO,
@@ -102,10 +108,13 @@ public class VolumeDialogController {
private VolumePolicy mVolumePolicy;
private boolean mShowDndTile = true;
+ private ToneGenerator mToneGenerators[];
+
public VolumeDialogController(Context context, ComponentName component) {
mContext = context.getApplicationContext();
Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED);
mComponent = component;
+ mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName());
mWorkerThread.start();
mWorker = new W(mWorkerThread.getLooper());
@@ -289,6 +298,7 @@ public class VolumeDialogController {
final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0;
+ final boolean playSound = (flags & AudioManager.FLAG_PLAY_SOUND) != 0;
boolean changed = false;
if (showUI) {
changed |= updateActiveStreamW(stream);
@@ -308,6 +318,19 @@ public class VolumeDialogController {
if (showSilentHint) {
mCallbacks.onShowSilentHint();
}
+ if (playSound) {
+ if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
+ mWorker.removeMessages(W.PLAY_SOUND);
+ mWorker.sendMessageDelayed(mWorker.obtainMessage(W.PLAY_SOUND, stream, flags),
+ AudioSystem.PLAY_SOUND_DELAY);
+ }
+
+ if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) {
+ mWorker.removeMessages(W.PLAY_SOUND);
+ onStopSoundsW();
+ }
+
+ }
if (changed && fromKey) {
Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume);
}
@@ -400,6 +423,16 @@ public class VolumeDialogController {
return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
}
+ private boolean updateLinkNotificationConfigW() {
+ boolean linkNotificationWithVolume = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1;
+ if (mState.linkedNotification == linkNotificationWithVolume) {
+ return false;
+ }
+ mState.linkedNotification = linkNotificationWithVolume;
+ return true;
+ }
+
private boolean updateZenModeConfigW() {
final ZenModeConfig zenModeConfig = getZenModeConfig();
if (Objects.equals(mState.zenModeConfig, zenModeConfig)) return false;
@@ -556,6 +589,9 @@ public class VolumeDialogController {
private static final int NOTIFY_VISIBLE = 12;
private static final int USER_ACTIVITY = 13;
private static final int SHOW_SAFETY_WARNING = 14;
+ private static final int PLAY_SOUND = 15;
+ private static final int STOP_SOUNDS = 16;
+ private static final int FREE_RESOURCES = 17;
W(Looper looper) {
super(looper);
@@ -578,6 +614,9 @@ public class VolumeDialogController {
case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break;
case USER_ACTIVITY: onUserActivityW(); break;
case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
+ case PLAY_SOUND: onPlaySoundW(msg.arg1, msg.arg2); break;
+ case STOP_SOUNDS: onStopSoundsW(); break;
+ case FREE_RESOURCES: onFreeResourcesW(); break;
}
}
}
@@ -707,6 +746,66 @@ public class VolumeDialogController {
}
+ protected void onPlaySoundW(int streamType, int flags) {
+
+ // If preference is no sound - just exit here
+ if (CMSettings.System.getInt(mContext.getContentResolver(),
+ CMSettings.System.VOLUME_ADJUST_SOUNDS_ENABLED, 1) == 0) {
+ return;
+ }
+
+ if (mWorker.hasMessages(W.STOP_SOUNDS)) {
+ mWorker.removeMessages(W.STOP_SOUNDS);
+ // Force stop right now
+ onStopSoundsW();
+ }
+
+ ToneGenerator toneGen = getOrCreateToneGeneratorW(streamType);
+ if (toneGen != null) {
+ toneGen.startTone(ToneGenerator.TONE_PROP_BEEP);
+ mWorker.sendMessageDelayed(mWorker.obtainMessage(W.STOP_SOUNDS), BEEP_DURATION);
+ }
+
+ mWorker.removeMessages(W.FREE_RESOURCES);
+ mWorker.sendMessageDelayed(mWorker.obtainMessage(W.FREE_RESOURCES), FREE_DELAY);
+ }
+
+ protected void onStopSoundsW() {
+ int numStreamTypes = AudioSystem.getNumStreamTypes();
+ for (int i = numStreamTypes - 1; i >= 0; i--) {
+ ToneGenerator toneGen = mToneGenerators[i];
+ if (toneGen != null) {
+ toneGen.stopTone();
+ }
+ }
+ }
+
+ private ToneGenerator getOrCreateToneGeneratorW(int streamType) {
+ if (mToneGenerators[streamType] == null) {
+ try {
+ mToneGenerators[streamType] = new ToneGenerator(streamType,
+ ToneGenerator.MAX_VOLUME);
+ } catch (RuntimeException e) {
+ if (false) {
+ Log.d(TAG, "ToneGenerator constructor failed with "
+ + "RuntimeException: " + e);
+ }
+ }
+ }
+ return mToneGenerators[streamType];
+ }
+
+ protected void onFreeResourcesW() {
+ synchronized (this) {
+ for (int i = mToneGenerators.length - 1; i >= 0; i--) {
+ if (mToneGenerators[i] != null) {
+ mToneGenerators[i].release();
+ }
+ mToneGenerators[i] = null;
+ }
+ }
+ }
+
private final class SettingObserver extends ContentObserver {
private final Uri SERVICE_URI = Settings.Secure.getUriFor(
Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
@@ -714,6 +813,8 @@ public class VolumeDialogController {
Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
private final Uri ZEN_MODE_CONFIG_URI =
Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG);
+ private final Uri VOLUME_LINK_NOTIFICATION_URI =
+ Settings.Secure.getUriFor(Settings.Secure.VOLUME_LINK_NOTIFICATION);
public SettingObserver(Handler handler) {
super(handler);
@@ -723,6 +824,8 @@ public class VolumeDialogController {
mContext.getContentResolver().registerContentObserver(SERVICE_URI, false, this);
mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_URI, false, this);
+ mContext.getContentResolver().registerContentObserver(VOLUME_LINK_NOTIFICATION_URI,
+ false, this);
onChange(true, SERVICE_URI);
}
@@ -750,6 +853,9 @@ public class VolumeDialogController {
if (ZEN_MODE_CONFIG_URI.equals(uri)) {
changed = updateZenModeConfigW();
}
+ if (VOLUME_LINK_NOTIFICATION_URI.equals(uri)) {
+ changed = updateLinkNotificationConfigW();
+ }
if (changed) {
mCallbacks.onStateChanged(mState);
}
@@ -947,6 +1053,7 @@ public class VolumeDialogController {
public String effectsSuppressorName;
public ZenModeConfig zenModeConfig;
public int activeStream = NO_ACTIVE_STREAM;
+ public boolean linkedNotification;
public State copy() {
final State rt = new State();
@@ -960,6 +1067,7 @@ public class VolumeDialogController {
rt.effectsSuppressorName = effectsSuppressorName;
if (zenModeConfig != null) rt.zenModeConfig = zenModeConfig.copy();
rt.activeStream = activeStream;
+ rt.linkedNotification = linkedNotification;
return rt;
}
@@ -989,6 +1097,7 @@ public class VolumeDialogController {
sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName);
sep(sb, indent); sb.append("zenModeConfig:").append(zenModeConfig);
sep(sb, indent); sb.append("activeStream:").append(activeStream);
+ sep(sb, indent); sb.append("linkedNotification:").append(linkedNotification);
if (indent > 0) sep(sb, indent);
return sb.append('}').toString();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 2688813..fa0de7d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -27,6 +27,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.media.session.MediaSessionManager;
@@ -63,6 +64,8 @@ public class VolumeUI extends SystemUI {
private VolumeDialogComponent mVolumeComponent;
+ private Configuration mConfiguration;
+
@Override
public void start() {
mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
@@ -80,6 +83,7 @@ public class VolumeUI extends SystemUI {
mContext, Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT,
new ServiceMonitorCallbacks());
mVolumeControllerService.start();
+ mConfiguration = new Configuration(mContext.getResources().getConfiguration());
}
private VolumeComponent getVolumeComponent() {
@@ -91,6 +95,20 @@ public class VolumeUI extends SystemUI {
super.onConfigurationChanged(newConfig);
if (!mEnabled) return;
getVolumeComponent().onConfigurationChanged(newConfig);
+
+ if (isThemeChange(newConfig)) {
+ mContext.recreateTheme();
+ mVolumeComponent.recreateDialog();
+ }
+ mConfiguration.setTo(newConfig);
+ }
+
+ private boolean isThemeChange(Configuration newConfig) {
+ if (mConfiguration != null) {
+ int changes = mConfiguration.updateFrom(newConfig);
+ return (changes & ActivityInfo.CONFIG_THEME_RESOURCE) != 0;
+ }
+ return false;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index af7ee08..0fb80c0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -69,17 +69,19 @@ public class ZenFooter extends LinearLayout {
mSpTexts.add(mEndNowButton);
}
+ private ZenModeController.Callback mZenModeCallback = new ZenModeController.Callback() {
+ @Override
+ public void onZenChanged(int zen) {
+ setZen(zen);
+ }
+ @Override
+ public void onConfigChanged(ZenModeConfig config) {
+ setConfig(config);
+ }
+ };
+
public void init(final ZenModeController controller) {
- controller.addCallback(new ZenModeController.Callback() {
- @Override
- public void onZenChanged(int zen) {
- setZen(zen);
- }
- @Override
- public void onConfigChanged(ZenModeConfig config) {
- setConfig(config);
- }
- });
+ controller.addCallback(mZenModeCallback);
mEndNowButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -142,4 +144,8 @@ public class ZenFooter extends LinearLayout {
mSpTexts.update();
}
+ public void cleanup() {
+ mController.removeCallback(mZenModeCallback);
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 01d2ca0..ddf623a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -419,8 +419,13 @@ public class ZenModePanel extends LinearLayout {
mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE);
}
final String warning = computeAlarmWarningText(zenNone);
- mZenAlarmWarning.setVisibility(warning != null ? VISIBLE : GONE);
+ final int oldVis = mZenAlarmWarning.getVisibility();
+ final int newVis = warning != null ? VISIBLE : GONE;
+ mZenAlarmWarning.setVisibility(newVis);
mZenAlarmWarning.setText(warning);
+ if (newVis != oldVis) {
+ requestLayout();
+ }
}
private String computeAlarmWarningText(boolean zenNone) {
diff --git a/packages/SystemUI/src/com/viewpagerindicator/CirclePageIndicator.java b/packages/SystemUI/src/com/viewpagerindicator/CirclePageIndicator.java
new file mode 100644
index 0000000..4286983
--- /dev/null
+++ b/packages/SystemUI/src/com/viewpagerindicator/CirclePageIndicator.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2011 Patrik Akerfeldt
+ * Copyright (C) 2011 Jake Wharton
+ *
+ * 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.viewpagerindicator;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.drawable.Drawable;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.ViewConfigurationCompat;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import com.android.systemui.R;
+
+import static android.graphics.Paint.ANTI_ALIAS_FLAG;
+import static android.widget.LinearLayout.HORIZONTAL;
+import static android.widget.LinearLayout.VERTICAL;
+
+/**
+ * Draws circles (one for each view). The current view position is filled and
+ * others are only stroked.
+ */
+public class CirclePageIndicator extends View implements PageIndicator {
+ private static final int INVALID_POINTER = -1;
+
+ private float mRadius;
+ private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG);
+ private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG);
+ private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG);
+ private ViewPager mViewPager;
+ private ViewPager.OnPageChangeListener mListener;
+ private int mCurrentPage;
+ private int mSnapPage;
+ private float mPageOffset;
+ private int mScrollState;
+ private int mOrientation;
+ private boolean mCentered;
+ private boolean mSnap;
+
+ private int mTouchSlop;
+ private float mLastMotionX = -1;
+ private int mActivePointerId = INVALID_POINTER;
+ private boolean mIsDragging;
+
+ private Bitmap mSettingsIcon;
+ private boolean mEditing;
+
+ public CirclePageIndicator(Context context) {
+ this(context, null);
+ }
+
+ public CirclePageIndicator(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ if (isInEditMode()) return;
+
+ //Load defaults from resources
+ final Resources res = getResources();
+ final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color);
+ final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color);
+ final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation);
+ final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color);
+ final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width);
+ final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius);
+ final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered);
+ final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap);
+
+ //Retrieve styles attributes
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0);
+
+ mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered);
+ mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation);
+ mPaintPageFill.setStyle(Style.FILL);
+ mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor));
+ mPaintStroke.setStyle(Style.STROKE);
+ mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor));
+ mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth));
+ mPaintFill.setStyle(Style.FILL);
+ mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_indicatorFillColor, defaultFillColor));
+ mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius);
+ mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap);
+
+ Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background);
+ if (background != null) {
+ setBackgroundDrawable(background);
+ }
+
+ a.recycle();
+
+ final ViewConfiguration configuration = ViewConfiguration.get(context);
+ mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
+
+ mSettingsIcon = BitmapFactory.decodeResource(res, R.drawable.ic_mini_settings);
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ public void setCentered(boolean centered) {
+ mCentered = centered;
+ invalidate();
+ }
+
+ public boolean isCentered() {
+ return mCentered;
+ }
+
+ public void setPageColor(int pageColor) {
+ mPaintPageFill.setColor(pageColor);
+ invalidate();
+ }
+
+ public int getPageColor() {
+ return mPaintPageFill.getColor();
+ }
+
+ public void setFillColor(int fillColor) {
+ mPaintFill.setColor(fillColor);
+ invalidate();
+ }
+
+ public int getFillColor() {
+ return mPaintFill.getColor();
+ }
+
+ public void setOrientation(int orientation) {
+ switch (orientation) {
+ case HORIZONTAL:
+ case VERTICAL:
+ mOrientation = orientation;
+ requestLayout();
+ break;
+
+ default:
+ throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL.");
+ }
+ }
+
+ public int getOrientation() {
+ return mOrientation;
+ }
+
+ public void setStrokeColor(int strokeColor) {
+ mPaintStroke.setColor(strokeColor);
+ invalidate();
+ }
+
+ public int getStrokeColor() {
+ return mPaintStroke.getColor();
+ }
+
+ public void setStrokeWidth(float strokeWidth) {
+ mPaintStroke.setStrokeWidth(strokeWidth);
+ invalidate();
+ }
+
+ public float getStrokeWidth() {
+ return mPaintStroke.getStrokeWidth();
+ }
+
+ public void setRadius(float radius) {
+ mRadius = radius;
+ invalidate();
+ }
+
+ public float getRadius() {
+ return mRadius;
+ }
+
+ public void setSnap(boolean snap) {
+ mSnap = snap;
+ invalidate();
+ }
+
+ public boolean isSnap() {
+ return mSnap;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mViewPager == null) {
+ return;
+ }
+ final int count = mViewPager.getAdapter().getCount();
+ if (count == 0) {
+ return;
+ }
+
+ if (mCurrentPage >= count) {
+ setCurrentItem(count - 1);
+ return;
+ }
+
+ int longSize;
+ int longPaddingBefore;
+ int longPaddingAfter;
+ int shortPaddingBefore;
+ if (mOrientation == HORIZONTAL) {
+ longSize = getWidth();
+ longPaddingBefore = getPaddingLeft();
+ longPaddingAfter = getPaddingRight();
+ shortPaddingBefore = getPaddingTop();
+ } else {
+ longSize = getHeight();
+ longPaddingBefore = getPaddingTop();
+ longPaddingAfter = getPaddingBottom();
+ shortPaddingBefore = getPaddingLeft();
+ }
+
+ final float threeRadius = mRadius * 3;
+ final float shortOffset = shortPaddingBefore + mRadius;
+ float longOffset = longPaddingBefore + mRadius;
+ if (mCentered) {
+ longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f);
+ }
+
+ float dX;
+ float dY;
+
+ float pageFillRadius = mRadius;
+ if (mPaintStroke.getStrokeWidth() > 0) {
+ pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f;
+ }
+
+ //Draw stroked circles
+ for (int iLoop = 0; iLoop < count; iLoop++) {
+ float drawLong = longOffset + (iLoop * threeRadius);
+ if (mOrientation == HORIZONTAL) {
+ dX = drawLong;
+ dY = shortOffset;
+ } else {
+ dX = shortOffset;
+ dY = drawLong;
+ }
+ // Only paint fill if not completely transparent
+ if (mPaintPageFill.getAlpha() > 0) {
+ if (mEditing && iLoop == 0) {
+ canvas.drawBitmap(mSettingsIcon,
+ (int) (dX - mRadius),
+ (int) (dY - mRadius),
+ mPaintPageFill);
+ } else {
+ canvas.drawCircle(dX, dY, (float) (pageFillRadius / 1.5f), mPaintPageFill);
+ }
+ }
+
+ // Only paint stroke if a stroke width was non-zero
+ if (pageFillRadius != mRadius) {
+ canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
+ }
+ }
+
+ //Draw the filled circle according to the current scroll
+ float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius;
+ if (!mSnap) {
+ cx += mPageOffset * threeRadius;
+ }
+ if (mOrientation == HORIZONTAL) {
+ dX = longOffset + cx;
+ dY = shortOffset;
+ } else {
+ dX = shortOffset;
+ dY = longOffset + cx;
+ }
+ canvas.drawCircle(dX, dY, mRadius, mPaintFill);
+ }
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (super.onTouchEvent(ev)) {
+ return true;
+ }
+ if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
+ return false;
+ }
+
+ final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
+ mLastMotionX = ev.getX();
+ break;
+
+ case MotionEvent.ACTION_MOVE: {
+ final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
+ final float x = MotionEventCompat.getX(ev, activePointerIndex);
+ final float deltaX = x - mLastMotionX;
+
+ if (!mIsDragging) {
+ if (Math.abs(deltaX) > mTouchSlop) {
+ mIsDragging = true;
+ }
+ }
+
+ if (mIsDragging) {
+ mLastMotionX = x;
+ if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
+ mViewPager.fakeDragBy(deltaX);
+ }
+ }
+
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ if (!mIsDragging) {
+ final int count = mViewPager.getAdapter().getCount();
+ final int width = getWidth();
+ final float halfWidth = width / 2f;
+ final float sixthWidth = width / 6f;
+
+ if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
+ if (action != MotionEvent.ACTION_CANCEL) {
+ mViewPager.setCurrentItem(mCurrentPage - 1);
+ }
+ return true;
+ } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
+ if (action != MotionEvent.ACTION_CANCEL) {
+ mViewPager.setCurrentItem(mCurrentPage + 1);
+ }
+ return true;
+ }
+ }
+
+ mIsDragging = false;
+ mActivePointerId = INVALID_POINTER;
+ if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
+ break;
+
+ case MotionEventCompat.ACTION_POINTER_DOWN: {
+ final int index = MotionEventCompat.getActionIndex(ev);
+ mLastMotionX = MotionEventCompat.getX(ev, index);
+ mActivePointerId = MotionEventCompat.getPointerId(ev, index);
+ break;
+ }
+
+ case MotionEventCompat.ACTION_POINTER_UP:
+ final int pointerIndex = MotionEventCompat.getActionIndex(ev);
+ final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
+ if (pointerId == mActivePointerId) {
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
+ }
+ mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
+ break;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void setViewPager(ViewPager view) {
+ if (mViewPager == view) {
+ return;
+ }
+ if (mViewPager != null) {
+ mViewPager.setOnPageChangeListener(null);
+ }
+ if (view.getAdapter() == null) {
+ throw new IllegalStateException("ViewPager does not have adapter instance.");
+ }
+ mViewPager = view;
+ mViewPager.setOnPageChangeListener(this);
+ invalidate();
+ }
+
+ @Override
+ public void setViewPager(ViewPager view, int initialPosition) {
+ setViewPager(view);
+ setCurrentItem(initialPosition);
+ }
+
+ @Override
+ public void setCurrentItem(int item) {
+ if (mViewPager == null) {
+ throw new IllegalStateException("ViewPager has not been bound.");
+ }
+ mViewPager.setCurrentItem(item);
+ mCurrentPage = item;
+ invalidate();
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ invalidate();
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ mScrollState = state;
+
+ if (mListener != null) {
+ mListener.onPageScrollStateChanged(state);
+ }
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ mCurrentPage = position;
+ mPageOffset = positionOffset;
+ invalidate();
+
+ if (mListener != null) {
+ mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {
+ mCurrentPage = position;
+ mSnapPage = position;
+ invalidate();
+ }
+
+ if (mListener != null) {
+ mListener.onPageSelected(position);
+ }
+ }
+
+ @Override
+ public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
+ mListener = listener;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.view.View#onMeasure(int, int)
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mOrientation == HORIZONTAL) {
+ setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
+ } else {
+ setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
+ }
+ }
+
+ /**
+ * Determines the width of this view
+ *
+ * @param measureSpec
+ * A measureSpec packed into an int
+ * @return The width of the view, honoring constraints from measureSpec
+ */
+ private int measureLong(int measureSpec) {
+ int result;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
+ //We were told how big to be
+ result = specSize;
+ } else {
+ //Calculate the width according the views count
+ final int count = mViewPager.getAdapter().getCount();
+ result = (int)(getPaddingLeft() + getPaddingRight()
+ + (count * 2 * mRadius) + (count - 1) * mRadius + 1);
+ //Respect AT_MOST value if that was what is called for by measureSpec
+ if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Determines the height of this view
+ *
+ * @param measureSpec
+ * A measureSpec packed into an int
+ * @return The height of the view, honoring constraints from measureSpec
+ */
+ private int measureShort(int measureSpec) {
+ int result;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ //We were told how big to be
+ result = specSize;
+ } else {
+ //Measure the height
+ result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
+ //Respect AT_MOST value if that was what is called for by measureSpec
+ if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ }
+ return result;
+ }
+
+ public void setEditing(boolean editing) {
+ mEditing = editing;
+ invalidate();
+ }
+}
diff --git a/packages/SystemUI/src/com/viewpagerindicator/PageIndicator.java b/packages/SystemUI/src/com/viewpagerindicator/PageIndicator.java
new file mode 100644
index 0000000..c08c00a
--- /dev/null
+++ b/packages/SystemUI/src/com/viewpagerindicator/PageIndicator.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Patrik Akerfeldt
+ * Copyright (C) 2011 Jake Wharton
+ *
+ * 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.viewpagerindicator;
+
+import android.support.v4.view.ViewPager;
+
+/**
+ * A PageIndicator is responsible to show an visual indicator on the total views
+ * number and the current visible view.
+ */
+public interface PageIndicator extends ViewPager.OnPageChangeListener {
+ /**
+ * Bind the indicator to a ViewPager.
+ *
+ * @param view
+ */
+ void setViewPager(ViewPager view);
+
+ /**
+ * Bind the indicator to a ViewPager.
+ *
+ * @param view
+ * @param initialPosition
+ */
+ void setViewPager(ViewPager view, int initialPosition);
+
+ /**
+ * <p>Set the current page of both the ViewPager and indicator.</p>
+ *
+ * <p>This <strong>must</strong> be used if you need to set the page before
+ * the views are drawn on screen (e.g., default start page).</p>
+ *
+ * @param item
+ */
+ void setCurrentItem(int item);
+
+ /**
+ * Set a page change listener which will receive forwarded events.
+ *
+ * @param listener
+ */
+ void setOnPageChangeListener(ViewPager.OnPageChangeListener listener);
+
+ /**
+ * Notify the indicator that the fragment list has changed.
+ */
+ void notifyDataSetChanged();
+}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 6a7201c..7392869 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -31,6 +31,9 @@ LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
LOCAL_PACKAGE_NAME := SystemUITests
LOCAL_STATIC_JAVA_LIBRARIES := mockito-target Keyguard
+LOCAL_STATIC_JAVA_LIBRARIES += org.cyanogenmod.platform.internal \
+ android-support-v7-palette \
+ android-support-v4
# sign this with platform cert, so this test is allowed to inject key events into
# UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 00b8de2..7df96a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -103,9 +103,10 @@ public class CallbackHandlerTest extends AndroidTestCase {
int type = R.drawable.stat_sys_data_fully_connected_1x;
int qsType = R.drawable.ic_qs_signal_1x;
boolean wide = true;
+ boolean showSeparateRoamIndicator = false;
int subId = 5;
mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription,
- description, wide, subId);
+ description, wide, showSeparateRoamIndicator, subId);
waitForCallbacks();
ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class);
@@ -117,11 +118,13 @@ public class CallbackHandlerTest extends AndroidTestCase {
ArgumentCaptor<String> typeContentArg = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Boolean> wideArg = ArgumentCaptor.forClass(Boolean.class);
+ ArgumentCaptor<Boolean> showSeparateRoamIndicatorArg =
+ ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class);
Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(),
qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(),
outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(),
- subIdArg.capture());
+ showSeparateRoamIndicatorArg.capture(), subIdArg.capture());
assertEquals(status, statusArg.getValue());
assertEquals(qs, qsArg.getValue());
assertEquals(type, (int) typeIconArg.getValue());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 61d4e4a..5e87ea1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -280,6 +280,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
ArgumentCaptor.forClass(String.class).capture(),
ArgumentCaptor.forClass(String.class).capture(),
ArgumentCaptor.forClass(Boolean.class).capture(),
+ ArgumentCaptor.forClass(Boolean.class).capture(),
ArgumentCaptor.forClass(Integer.class).capture());
IconState iconState = iconArg.getValue();
assertEquals("Visibility in, quick settings", visible, iconState.visible);
@@ -306,6 +307,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
ArgumentCaptor.forClass(String.class).capture(),
ArgumentCaptor.forClass(String.class).capture(),
ArgumentCaptor.forClass(Boolean.class).capture(),
+ ArgumentCaptor.forClass(Boolean.class).capture(),
ArgumentCaptor.forClass(Integer.class).capture());
IconState iconState = iconArg.getValue();
diff --git a/packages/VpnDialogs/res/values-ast-rES/strings.xml b/packages/VpnDialogs/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..2bc2c7e
--- /dev/null
+++ b/packages/VpnDialogs/res/values-ast-rES/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="prompt">Solicitú de conexón</string>
+ <string name="warning"><xliff:g id="app">%s</xliff:g> quier facer una conexón VPN
+ que permite monitorear el tráficu. Aceuta namái si confíes na fonte.
+ <![CDATA[
+ <br />
+ <br />
+ <img src="vpn_icon" />
+ ]]> apaez arriba na pantalla cuando VPN ta activa.
+ </string>
+ <string name="legacy_title">VPN coneutada</string>
+ <string name="configure">Configurar</string>
+ <string name="disconnect">Desconeutar</string>
+ <string name="session">Sesión:</string>
+ <string name="duration">Duración:</string>
+ <string name="data_transmitted">Unvióse:</string>
+ <string name="data_received">Recibióse:</string>
+ <string name="data_value_format">
+ <xliff:g id="number">%1$s</xliff:g> bytes /
+ <xliff:g id="number">%2$s</xliff:g> paquetes
+    </string>
+</resources>
diff --git a/packages/VpnDialogs/res/values-be/strings.xml b/packages/VpnDialogs/res/values-be/strings.xml
new file mode 100644
index 0000000..075251f
--- /dev/null
+++ b/packages/VpnDialogs/res/values-be/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="prompt">Запыт на злучэнне</string>
+ <string name="warning"><xliff:g id="app">%s</xliff:g>хоча ўсталяваць злучэнне VPN
+ гэта дазваляе яму кантраляваць сеткавы трафік. Працягвайце, калі вы давяраеце крыніцы.
+ <![CDATA[
+ <br />
+ <br />
+ <img src="vpn_icon" />
+ ]]>адлюстроўваецца ў верхняй частцы экрана, калі VPN-актыўны.
+ </string>
+ <string name="legacy_title">VPN падключаны</string>
+ <string name="configure">Налады</string>
+ <string name="disconnect">Адключыцца</string>
+ <string name="session">Сэсія:</string>
+ <string name="duration">Працягласць:</string>
+ <string name="data_transmitted">Дасланыя:</string>
+ <string name="data_received">Атрымана:</string>
+ <string name="data_value_format">
+ <xliff:g id="number">%1$s</xliff:g> байт /
+ <xliff:g id="number">%2$s</xliff:g> пакетаў
+ </string>
+</resources>
diff --git a/packages/VpnDialogs/res/values-ku/strings.xml b/packages/VpnDialogs/res/values-ku/strings.xml
new file mode 100644
index 0000000..2706a6a
--- /dev/null
+++ b/packages/VpnDialogs/res/values-ku/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="legacy_title">VPN پەیوەستکراوە</string>
+ <string name="configure">رێکخستن</string>
+ <string name="disconnect">پچڕاندنی پەیوەندی</string>
+ <string name="session">دانشتن:</string>
+ <string name="duration">ماوه‌:</string>
+ <string name="data_transmitted">گەیشت:</string>
+ <string name="data_received">گەیشت:</string>
+ <string name="data_value_format">
+ <xliff:g id="number">%1$s</xliff:g> بایت /
+ <xliff:g id="number">%2$s</xliff:g> گیرفانەکان
+ </string>
+</resources>
diff --git a/packages/VpnDialogs/res/values-lb/strings.xml b/packages/VpnDialogs/res/values-lb/strings.xml
new file mode 100644
index 0000000..9a310e8
--- /dev/null
+++ b/packages/VpnDialogs/res/values-lb/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="prompt">Connectiounsufro</string>
+ <string name="warning"><xliff:g id="app">%s</xliff:g> wëll eng VPN-Connectioun opstellen, wouduerch den Netzwierktrafic kann iwwerwaacht ginn. Acceptéier dat just, wann s du der Quell vertraus.
+ <![CDATA[
+ <br />
+ <br />
+ <img src="vpn_icon" />
+ ]]> erschéngt uewen um Schierm, wa VPN aktiv ass.
+ </string>
+ <string name="legacy_title">VPN connectéiert</string>
+ <string name="configure">Astellen</string>
+ <string name="disconnect">Deconnectéieren</string>
+ <string name="session">Sëtzung:</string>
+ <string name="duration">Dauer:</string>
+ <string name="data_transmitted">Geschéckt:</string>
+ <string name="data_received">Empfaangen:</string>
+ <string name="data_value_format">
+ <xliff:g id="number">%1$s</xliff:g> Bytes /
+ <xliff:g id="number">%2$s</xliff:g> Päck
+    </string>
+</resources>
diff --git a/packages/VpnDialogs/res/values-ug/strings.xml b/packages/VpnDialogs/res/values-ug/strings.xml
new file mode 100644
index 0000000..bec6790
--- /dev/null
+++ b/packages/VpnDialogs/res/values-ug/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="legacy_title">VPN باغلاندى</string>
+ <string name="configure">سەپلىمە</string>
+ <string name="disconnect">ئۈز</string>
+ <string name="session">سۆزلىشىش</string>
+ <string name="duration">داۋاملىشىش ۋاقتى:</string>
+ <string name="data_transmitted">ئەۋەتىلگىنى:</string>
+ <string name="data_received">تاپشۇرۇۋالغىنى:</string>
+ <string name="data_value_format"><xliff:g id="NUMBER_0">%1$s</xliff:g> بايت/<xliff:g id="NUMBER_1">%2$s</xliff:g> بوغچا</string>
+</resources>
diff --git a/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml b/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml
index 54f8ff3..97cd620 100644
--- a/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml
+++ b/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml
@@ -32,5 +32,5 @@
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="@string/wallpaper_instructions"
- android:textColor="@android:color/white" />
+ android:textColor="@color/set_wallpaper_text_color" />
</FrameLayout>
diff --git a/packages/WallpaperCropper/res/values-ast-rES/strings.xml b/packages/WallpaperCropper/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..92ff614
--- /dev/null
+++ b/packages/WallpaperCropper/res/values-ast-rES/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="crop_wallpaper">Recortar el fondu de pantalla</string>
+ <string name="wallpaper_instructions">Afitar fondu de pantalla</string>
+ <string name="wallpaper_load_fail">Nun pudo cargase la imaxe como fondu de pantalla</string>
+</resources>
diff --git a/packages/WallpaperCropper/res/values-be/strings.xml b/packages/WallpaperCropper/res/values-be/strings.xml
new file mode 100644
index 0000000..1e728f8
--- /dev/null
+++ b/packages/WallpaperCropper/res/values-be/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="crop_wallpaper">Абрэзаць шпалеру</string>
+ <string name="wallpaper_instructions">Усталяваць шпалеру</string>
+ <string name="wallpaper_load_fail">Не атрымалася загрузіць выяву</string>
+</resources>
diff --git a/packages/WallpaperCropper/res/values-ku/strings.xml b/packages/WallpaperCropper/res/values-ku/strings.xml
new file mode 100644
index 0000000..f2a9f6c
--- /dev/null
+++ b/packages/WallpaperCropper/res/values-ku/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="crop_wallpaper">بڕینی وێنەی پشتەوە</string>
+ <string name="wallpaper_instructions">دانانی وێنەی پشتەوە</string>
+ <string name="wallpaper_load_fail">نەتوانرا وێنەی پشتەوە دابنرێت</string>
+</resources>
diff --git a/packages/WallpaperCropper/res/values-lb/strings.xml b/packages/WallpaperCropper/res/values-lb/strings.xml
new file mode 100644
index 0000000..46fcd67
--- /dev/null
+++ b/packages/WallpaperCropper/res/values-lb/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="crop_wallpaper">Hannergrondbild schneiden</string>
+ <string name="wallpaper_instructions">Hannergrondbild setzen</string>
+ <string name="wallpaper_load_fail">D\'Bild konnt net als Hannergrondbild geluede ginn</string>
+</resources>
diff --git a/packages/WallpaperCropper/res/values/cm_colors.xml b/packages/WallpaperCropper/res/values/cm_colors.xml
new file mode 100644
index 0000000..bfb2994
--- /dev/null
+++ b/packages/WallpaperCropper/res/values/cm_colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod 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.
+-->
+<resources>
+
+ <color name="set_wallpaper_text_color">@android:color/white</color>
+</resources>
diff --git a/services/Android.mk b/services/Android.mk
index 1918db5..b15f575 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -35,6 +35,8 @@ services := \
# The convention is to name each service module 'services.$(module_name)'
LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services))
+LOCAL_JAVA_LIBRARIES += org.cyanogenmod.platform.internal
+
include $(BUILD_JAVA_LIBRARY)
# native library
@@ -48,6 +50,11 @@ LOCAL_SHARED_LIBRARIES :=
# include all the jni subdirs to collect their sources
include $(wildcard $(LOCAL_PATH)/*/jni/Android.mk)
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/services/libtvextensions \
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libTvInputHalExtensions
+
LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
LOCAL_MODULE:= libandroid_servers
diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk
index d98fc28..39355a7 100644
--- a/services/accessibility/Android.mk
+++ b/services/accessibility/Android.mk
@@ -7,4 +7,6 @@ LOCAL_MODULE := services.accessibility
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
+LOCAL_JAVA_LIBRARIES += org.cyanogenmod.platform.internal
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
index d0b5898..1b4182d 100644
--- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
+++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
@@ -26,11 +26,12 @@ import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Slog;
import android.view.accessibility.AccessibilityManager;
+import cyanogenmod.providers.CMSettings;
/**
* Utility methods for performing accessibility display adjustments.
*/
-class DisplayAdjustmentUtils {
+public class DisplayAdjustmentUtils {
private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName();
/** Matrix and offset used for converting color to gray-scale. */
@@ -76,6 +77,11 @@ class DisplayAdjustmentUtils {
return true;
}
+ if (CMSettings.Secure.getStringForUser(cr,
+ CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, userId) != null) {
+ return true;
+ }
+
return false;
}
@@ -91,6 +97,23 @@ class DisplayAdjustmentUtils {
colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY);
}
+ String adj = CMSettings.Secure.getStringForUser(cr,
+ CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, userId);
+ if (adj != null) {
+ String[] tmp = adj.split(" ");
+ if (tmp.length == 16) {
+ float[] adjMatrix = new float[16];
+ try {
+ for (int i = 0; i < 16; i++) {
+ adjMatrix[i] = Float.parseFloat(tmp[i]);
+ }
+ colorMatrix = multiply(colorMatrix, adjMatrix);
+ } catch (NumberFormatException e) {
+ Slog.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ }
+
if (Settings.Secure.getIntForUser(cr,
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
final int daltonizerMode = Settings.Secure.getIntForUser(cr,
diff --git a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
index b4613d6..9be29c2 100644
--- a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -790,12 +790,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
while (mDelayedEventQueue != null) {
MotionEventInfo info = mDelayedEventQueue;
mDelayedEventQueue = info.mNext;
- final long offset = SystemClock.uptimeMillis() - info.mCachedTimeMillis;
- MotionEvent event = obtainEventWithOffsetTimeAndDownTime(info.mEvent, offset);
- MotionEvent rawEvent = obtainEventWithOffsetTimeAndDownTime(info.mRawEvent, offset);
- ScreenMagnifier.this.onMotionEvent(event, rawEvent, info.mPolicyFlags);
- event.recycle();
- rawEvent.recycle();
+ ScreenMagnifier.this.onMotionEvent(info.mEvent, info.mRawEvent, info.mPolicyFlags);
info.recycle();
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index fa87270..bc84676 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2009,6 +2009,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (widget.views != null) {
pw.print(" views="); pw.println(widget.views);
}
+ if (widget.options != null) {
+ pw.print(" options="); pw.println(widget.options);
+ }
}
private static void serializeProvider(XmlSerializer out, Provider p) throws IOException {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 12003e2..1629a37 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2218,10 +2218,10 @@ public class BackupManagerService {
// fire off a backup agent, blocking until it attaches or times out
IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) {
IBackupAgent agent = null;
- synchronized(mAgentConnectLock) {
- mConnecting = true;
- mConnectedAgent = null;
- try {
+ try {
+ synchronized(mAgentConnectLock) {
+ mConnecting = true;
+ mConnectedAgent = null;
if (mActivityManager.bindBackupAgent(app, mode)) {
Slog.d(TAG, "awaiting agent for " + app);
@@ -2235,7 +2235,6 @@ public class BackupManagerService {
} catch (InterruptedException e) {
// just bail
Slog.w(TAG, "Interrupted: " + e);
- mActivityManager.clearPendingBackup();
return null;
}
}
@@ -2243,14 +2242,22 @@ public class BackupManagerService {
// if we timed out with no connect, abort and move on
if (mConnecting == true) {
Slog.w(TAG, "Timeout waiting for agent " + app);
- mActivityManager.clearPendingBackup();
return null;
}
if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
agent = mConnectedAgent;
}
- } catch (RemoteException e) {
+ }
+ } catch (RemoteException e) {
// can't happen - ActivityManager is local
+ } finally {
+ // failed to bind backup agent, clear pending backup
+ if (agent == null) {
+ try {
+ mActivityManager.clearPendingBackup();
+ } catch (RemoteException e) {
+ // can't happen - ActivityManager is local
+ }
}
}
return agent;
@@ -2931,6 +2938,12 @@ public class BackupManagerService {
final String pkgName = mCurrentPackage.packageName;
final long filepos = mBackupDataName.length();
+ if (mBackupData == null) {
+ failAgent(mAgentBinder, "Backup data was null: " + mBackupDataName);
+ addBackupTrace("backup data was null: " + mBackupDataName);
+ agentErrorCleanup();
+ return;
+ }
FileDescriptor fd = mBackupData.getFileDescriptor();
try {
// If it's a 3rd party app, see whether they wrote any protected keys
@@ -7935,6 +7948,11 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
int toCopy = result;
while (toCopy > 0) {
+ if (!mEngine.isRunning() && RestoreEngine.SUCCESS != mEngine.getResult()) {
+ Slog.e(TAG, "RestoreEngine fail");
+ // throw IOException to abandon this package's restore
+ throw new IOException();
+ }
int n = transportIn.read(buffer, 0, toCopy);
engineOut.write(buffer, 0, n);
toCopy -= n;
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 666f2ff..d2ecac9 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -12,4 +12,8 @@ LOCAL_SRC_FILES += \
LOCAL_JAVA_LIBRARIES := services.net telephony-common
LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
+LOCAL_JAVA_LIBRARIES += services.accessibility
+
+LOCAL_JAVA_LIBRARIES += org.cyanogenmod.platform.internal
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 130a234..1433490 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -28,7 +28,9 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
@@ -42,6 +44,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.AlarmClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
@@ -66,6 +69,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.TimeZone;
@@ -75,16 +79,26 @@ import static android.app.AlarmManager.RTC_WAKEUP;
import static android.app.AlarmManager.RTC;
import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
import static android.app.AlarmManager.ELAPSED_REALTIME;
+import static android.app.AlarmManager.RTC_POWEROFF_WAKEUP;
import com.android.internal.util.LocalLog;
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
+
class AlarmManagerService extends SystemService {
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
+ private static final int RTC_POWEROFF_WAKEUP_MASK = 1 << RTC_POWEROFF_WAKEUP;
static final int TIME_CHANGED_MASK = 1 << 16;
- static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
+ static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK
+ |RTC_POWEROFF_WAKEUP_MASK;
// Mask for testing whether a given alarm type is wakeup vs non-wakeup
static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
@@ -111,8 +125,12 @@ class AlarmManagerService extends SystemService {
final Object mLock = new Object();
+ private final ArrayList<Integer> mTriggeredUids = new ArrayList<Integer>();
+ private final ArrayList<Integer> mBlockedUids = new ArrayList<Integer>();
+
long mNativeData;
private long mNextWakeup;
+ private long mNextRtcWakeup;
private long mNextNonWakeup;
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
@@ -286,6 +304,14 @@ class AlarmManagerService extends SystemService {
final Constants mConstants;
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ processQSChangedLocked();
+ }
+ };
+ private ContentObserver mQSObserver;
+
// Alarm delivery ordering bookkeeping
static final int PRIO_TICK = 0;
static final int PRIO_WAKEUP = 1;
@@ -347,6 +373,14 @@ class AlarmManagerService extends SystemService {
return alarms.get(index);
}
+ long getWhenByElapsedTime(long whenElapsed) {
+ for(int i=0;i< alarms.size();i++) {
+ if(alarms.get(i).whenElapsed == whenElapsed)
+ return alarms.get(i).when;
+ }
+ return 0;
+ }
+
boolean canHold(long whenElapsed, long maxWhen) {
return (end >= whenElapsed) && (start <= maxWhen);
}
@@ -496,6 +530,17 @@ class AlarmManagerService extends SystemService {
return false;
}
+ boolean isRtcPowerOffWakeup() {
+ final int N = alarms.size();
+ for (int i = 0; i < N; i++) {
+ Alarm a = alarms.get(i);
+ if (a.type == RTC_POWEROFF_WAKEUP) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public String toString() {
StringBuilder b = new StringBuilder(40);
@@ -602,7 +647,8 @@ class AlarmManagerService extends SystemService {
}
static long convertToElapsed(long when, int type) {
- final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
+ final boolean isRtc = (type == RTC || type == RTC_WAKEUP
+ || type == RTC_POWEROFF_WAKEUP);
if (isRtc) {
when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
}
@@ -732,9 +778,10 @@ class AlarmManagerService extends SystemService {
final BroadcastStats mBroadcastStats;
final FilterStats mFilterStats;
final int mAlarmType;
+ final int mUid;
InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
- int alarmType, String tag, long nowELAPSED) {
+ int alarmType, String tag, long nowELAPSED, int uid) {
mPendingIntent = pendingIntent;
mWorkSource = workSource;
mTag = tag;
@@ -747,6 +794,7 @@ class AlarmManagerService extends SystemService {
fs.lastTime = nowELAPSED;
mFilterStats = fs;
mAlarmType = alarmType;
+ mUid = uid;
}
}
@@ -794,7 +842,7 @@ class AlarmManagerService extends SystemService {
@Override
public void onStart() {
mNativeData = init();
- mNextWakeup = mNextNonWakeup = 0;
+ mNextWakeup = mNextRtcWakeup = mNextNonWakeup = 0;
// We have to set current TimeZone info to kernel
// because kernel doesn't keep this after reboot
@@ -828,6 +876,8 @@ class AlarmManagerService extends SystemService {
}
publishBinderService(Context.ALARM_SERVICE, mService);
+
+ mQSObserver = QSUtils.registerObserverForQSChanges(getContext(), mQSListener);
}
@Override
@@ -840,6 +890,12 @@ class AlarmManagerService extends SystemService {
@Override
protected void finalize() throws Throwable {
try {
+ QSUtils.unregisterObserverForQSChanges(getContext(), mQSObserver);
+ } catch (Exception ex) {
+ // Ignore
+ }
+
+ try {
close(mNativeData);
} finally {
super.finalize();
@@ -916,7 +972,7 @@ class AlarmManagerService extends SystemService {
interval = minInterval;
}
- if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
+ if (type < RTC_WAKEUP || type > RTC_POWEROFF_WAKEUP) {
throw new IllegalArgumentException("Invalid alarm type " + type);
}
@@ -1023,6 +1079,8 @@ class AlarmManagerService extends SystemService {
if (a.alarmClock != null) {
mNextAlarmClockMayChange = true;
+ //Publish as system user
+ publishNextAlarmCustomTile(UserHandle.myUserId());
}
boolean needRebatch = false;
@@ -1174,6 +1232,39 @@ class AlarmManagerService extends SystemService {
dumpImpl(pw);
}
+
+ @Override
+ /* updates the blocked uids, so if a wake lock is acquired to only fire
+ * alarm for it, it can be released.
+ */
+ public void updateBlockedUids(int uid, boolean isBlocked) {
+
+ if (localLOGV) Slog.v(TAG, "UpdateBlockedUids: uid = " + uid +
+ " isBlocked = " + isBlocked);
+
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (localLOGV) Slog.v(TAG, "UpdateBlockedUids is not allowed");
+ return;
+ }
+
+ synchronized(mLock) {
+ if(isBlocked) {
+ mBlockedUids.add(new Integer(uid));
+ if (checkReleaseWakeLock()) {
+ /* all the uids for which the alarms are triggered
+ * are either blocked or have called onSendFinished.
+ */
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ if (localLOGV)
+ Slog.v(TAG, "AM WakeLock Released Internally in updateBlockedUids");
+ }
+ }
+ } else {
+ mBlockedUids.clear();
+ }
+ }
+ }
};
void dumpImpl(PrintWriter pw) {
@@ -1469,6 +1560,19 @@ class AlarmManagerService extends SystemService {
return null;
}
+ private Batch findFirstRtcWakeupBatchLocked() {
+ long elapsed = SystemClock.elapsedRealtime();
+ final int N = mAlarmBatches.size();
+ for (int i = 0; i < N; i++) {
+ Batch b = mAlarmBatches.get(i);
+ long intervalTime = b.start - elapsed;
+ if (b.isRtcPowerOffWakeup()) {
+ return b;
+ }
+ }
+ return null;
+ }
+
long getNextWakeFromIdleTimeImpl() {
synchronized (mLock) {
return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
@@ -1536,6 +1640,9 @@ class AlarmManagerService extends SystemService {
updateNextAlarmInfoForUserLocked(userId, null);
}
}
+
+ // Process dynamic custom tile
+ processQSChangedLocked();
}
private void updateNextAlarmInfoForUserLocked(int userId,
@@ -1611,10 +1718,18 @@ class AlarmManagerService extends SystemService {
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
final Batch firstBatch = mAlarmBatches.get(0);
+ final Batch firstRtcWakeup = findFirstRtcWakeupBatchLocked();
if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
}
+ if (firstRtcWakeup != null && mNextRtcWakeup != firstRtcWakeup.start) {
+ mNextRtcWakeup = firstRtcWakeup.start;
+ long when = firstRtcWakeup.getWhenByElapsedTime(mNextRtcWakeup);
+ if (when != 0) {
+ setLocked(RTC_POWEROFF_WAKEUP, when);
+ }
+ }
if (firstBatch != firstWakeup) {
nextNonWakeup = firstBatch.start;
}
@@ -1630,10 +1745,36 @@ class AlarmManagerService extends SystemService {
}
}
+ boolean checkReleaseWakeLock() {
+ if (mTriggeredUids.size() == 0 || mBlockedUids.size() == 0)
+ return false;
+
+ int uid;
+ for (int i = 0; i < mTriggeredUids.size(); i++) {
+ uid = mTriggeredUids.get(i);
+ if (!mBlockedUids.contains(uid)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private void removeLocked(PendingIntent operation) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
+ ArrayList<Alarm> alarmList = b.alarms;
+ Alarm alarm = null;
+ for (int j = alarmList.size() - 1; j >= 0; j--) {
+ alarm = alarmList.get(j);
+ if (alarm.type == RTC_POWEROFF_WAKEUP && alarm.operation.equals(operation)) {
+ long alarmSeconds, alarmNanoseconds;
+ alarmSeconds = alarm.when / 1000;
+ alarmNanoseconds = (alarm.when % 1000) * 1000 * 1000;
+ clear(mNativeData, alarm.type, alarmSeconds, alarmNanoseconds);
+ mNextRtcWakeup = 0;
+ }
+ }
didRemove |= b.remove(operation);
if (b.size() == 0) {
mAlarmBatches.remove(i);
@@ -1804,6 +1945,7 @@ class AlarmManagerService extends SystemService {
case RTC_WAKEUP : return "RTC_WAKEUP";
case ELAPSED_REALTIME : return "ELAPSED";
case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
+ case RTC_POWEROFF_WAKEUP : return "RTC_POWEROFF_WAKEUP";
default:
break;
}
@@ -1824,6 +1966,7 @@ class AlarmManagerService extends SystemService {
private native long init();
private native void close(long nativeData);
private native void set(long nativeData, int type, long seconds, long nanoseconds);
+ private native void clear(long nativeData, int type, long seconds, long nanoseconds);
private native int waitForAlarm(long nativeData);
private native int setKernelTime(long nativeData, long millis);
private native int setKernelTimezone(long nativeData, int minuteswest);
@@ -1959,6 +2102,7 @@ class AlarmManagerService extends SystemService {
public long maxWhenElapsed; // also in the elapsed time base
public long repeatInterval;
public PriorityClass priorityClass;
+ public int pid;
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws, int _flags,
@@ -1966,7 +2110,8 @@ class AlarmManagerService extends SystemService {
type = _type;
origWhen = _when;
wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
- || _type == AlarmManager.RTC_WAKEUP;
+ || _type == AlarmManager.RTC_WAKEUP
+ || _type == AlarmManager.RTC_POWEROFF_WAKEUP;
when = _when;
whenElapsed = _whenElapsed;
windowLength = _windowLength;
@@ -1977,12 +2122,13 @@ class AlarmManagerService extends SystemService {
workSource = _ws;
flags = _flags;
alarmClock = _info;
- uid = _uid;
+ uid = operation.getCreatorUid();
+ pid = Binder.getCallingPid();
}
public static String makeTag(PendingIntent pi, int type) {
return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
- ? "*walarm*:" : "*alarm*:");
+ || type == RTC_POWEROFF_WAKEUP ? "*walarm*:" : "*alarm*:");
}
@Override
@@ -2002,7 +2148,8 @@ class AlarmManagerService extends SystemService {
public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
SimpleDateFormat sdf) {
- final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
+ final boolean isRtc = (type == RTC || type == RTC_WAKEUP
+ || type == RTC_POWEROFF_WAKEUP);
pw.print(prefix); pw.print("tag="); pw.println(tag);
pw.print(prefix); pw.print("type="); pw.print(type);
pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
@@ -2117,15 +2264,25 @@ class AlarmManagerService extends SystemService {
mResultReceiver, mHandler, null, allowWhileIdle ? mIdleOptions : null);
// we have an active broadcast so stay awake.
- if (mBroadcastRefCount == 0) {
+ if (mBroadcastRefCount == 0 || !mWakeLock.isHeld()) {
setWakelockWorkSource(alarm.operation, alarm.workSource,
alarm.type, alarm.tag, true);
mWakeLock.acquire();
}
final InFlight inflight = new InFlight(AlarmManagerService.this,
- alarm.operation, alarm.workSource, alarm.type, alarm.tag, nowELAPSED);
+ alarm.operation,
+ alarm.workSource,
+ alarm.type, alarm.tag,
+ nowELAPSED, alarm.uid);
mInFlight.add(inflight);
mBroadcastRefCount++;
+ mTriggeredUids.add(new Integer(alarm.uid));
+ if (checkReleaseWakeLock()) {
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally deliverAlarms");
+ }
+ }
if (allowWhileIdle) {
// Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
@@ -2149,7 +2306,8 @@ class AlarmManagerService extends SystemService {
fs.nesting++;
}
if (alarm.type == ELAPSED_REALTIME_WAKEUP
- || alarm.type == RTC_WAKEUP) {
+ || alarm.type == RTC_WAKEUP
+ || alarm.type == RTC_POWEROFF_WAKEUP) {
bs.numWakeup++;
fs.numWakeup++;
if (alarm.workSource != null && alarm.workSource.size() > 0) {
@@ -2321,11 +2479,10 @@ class AlarmManagerService extends SystemService {
mWakeLock.setWorkSource(new WorkSource(uid));
return;
}
+ // Something went wrong; fall back to attributing the lock to the OS
+ mWakeLock.setWorkSource(null);
} catch (Exception e) {
}
-
- // Something went wrong; fall back to attributing the lock to the OS
- mWakeLock.setWorkSource(null);
}
private class AlarmHandler extends Handler {
@@ -2529,13 +2686,124 @@ class AlarmManagerService extends SystemService {
return bs;
}
+ private void publishNextAlarmCustomTile(int userId) {
+ // This action should be performed as system
+ long token = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = new UserHandle(userId);
+ final int icon = QSUtils.getDynamicQSTileResIconId(getContext(), userId,
+ QSConstants.DYNAMIC_TILE_NEXT_ALARM);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(getContext(), userId,
+ QSConstants.DYNAMIC_TILE_NEXT_ALARM);
+ final Context resourceContext = QSUtils.getQSTileContext(getContext(), userId);
+
+ // Create the expanded view with all the user alarms
+ AlarmManager.AlarmClockInfo nextAlarm = null;
+ CustomTile.ListExpandedStyle style = new CustomTile.ListExpandedStyle();
+ ArrayList<CustomTile.ExpandedListItem> items = new ArrayList<>();
+ for (Alarm alarm : getAllUserAlarmsLocked(userId)) {
+ if (nextAlarm == null) {
+ nextAlarm = alarm.alarmClock;
+ }
+
+ final String pkg = alarm.operation.getCreatorPackage();
+ CustomTile.ExpandedListItem item = new CustomTile.ExpandedListItem();
+ item.setExpandedListItemDrawable(icon);
+ item.setExpandedListItemTitle(formatNextAlarm(getContext(), alarm.alarmClock,
+ userId));
+ item.setExpandedListItemSummary(getAlarmApkLabel(pkg));
+ item.setExpandedListItemOnClickIntent(getCustomTilePendingIntent(user, pkg));
+ items.add(item);
+ }
+ style.setListItems(items);
+
+ // Don't bother posting a tile if no "next alarms" are available.
+ if (nextAlarm == null) {
+ return;
+ }
+ // Build the custom tile
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(getContext());
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(formatNextAlarm(getContext(), nextAlarm, userId))
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setExpandedStyle(style)
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_NEXT_ALARM,
+ AlarmManagerService.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishNextAlarmCustomTile(int userId) {
+ // This action should be performed as system
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(getContext());
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_NEXT_ALARM,
+ AlarmManagerService.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private List<Alarm> getAllUserAlarmsLocked(int userId) {
+ List<Alarm> userAlarms = new ArrayList<>();
+ synchronized (mLock) {
+ final int N = mAlarmBatches.size();
+ for (int i = 0; i < N; i++) {
+ ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
+ final int M = alarms.size();
+ for (int j = 0; j < M; j++) {
+ Alarm a = alarms.get(j);
+ if (a.alarmClock != null && userId == a.uid) {
+ userAlarms.add(a);
+ }
+ }
+ }
+ }
+ return userAlarms;
+ }
+
+ private String getAlarmApkLabel(String pkg) {
+ final PackageManager pm = getContext().getPackageManager();
+ ApplicationInfo ai = null;
+ try {
+ ai = pm.getApplicationInfo(pkg, 0);
+ } catch (final NameNotFoundException e) {
+ // Ignore
+ }
+ return (String) (ai != null ? pm.getApplicationLabel(ai) : pkg);
+ }
+
+ private PendingIntent getCustomTilePendingIntent(UserHandle user, String pkg) {
+ Intent i = new Intent(AlarmClock.ACTION_SHOW_ALARMS);
+ i.setPackage(pkg);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return PendingIntent.getActivityAsUser(getContext(), 0, i,
+ PendingIntent.FLAG_UPDATE_CURRENT, null, user);
+ }
+
+ private void processQSChangedLocked() {
+ synchronized (mLock) {
+ int count = mNextAlarmClockForUser.size();
+ for (int i = 0; i < count; i++) {
+ int userId = mNextAlarmClockForUser.keyAt(i);
+ publishNextAlarmCustomTile(userId);
+ }
+ }
+ }
+
class ResultReceiver implements PendingIntent.OnFinished {
public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
String resultData, Bundle resultExtras) {
synchronized (mLock) {
+ int uid = 0;
InFlight inflight = null;
for (int i=0; i<mInFlight.size(); i++) {
if (mInFlight.get(i).mPendingIntent == pi) {
+ uid = mInFlight.get(i).mUid;
inflight = mInFlight.remove(i);
break;
}
@@ -2569,8 +2837,19 @@ class AlarmManagerService extends SystemService {
mLog.w("No in-flight alarm for " + pi + " " + intent);
}
mBroadcastRefCount--;
+ mTriggeredUids.remove(new Integer(uid));
+
+ if (checkReleaseWakeLock()) {
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally onSendFinish");
+ }
+ }
+
if (mBroadcastRefCount == 0) {
- mWakeLock.release();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
if (mInFlight.size() > 0) {
mLog.w("Finished all broadcasts with " + mInFlight.size()
+ " remaining inflights");
@@ -2581,8 +2860,12 @@ class AlarmManagerService extends SystemService {
}
} else {
// the next of our alarms is now in flight. reattribute the wakelock.
+ InFlight inFlight = null;
if (mInFlight.size() > 0) {
- InFlight inFlight = mInFlight.get(0);
+ for(int index = 0; index < mInFlight.size(); index++){
+ inFlight = mInFlight.get(index);
+ if(!mBlockedUids.contains(inFlight.mUid)) break;
+ }
setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
inFlight.mAlarmType, inFlight.mTag, false);
} else {
diff --git a/services/core/java/com/android/server/AppOpsPolicy.java b/services/core/java/com/android/server/AppOpsPolicy.java
new file mode 100644
index 0000000..75bca05
--- /dev/null
+++ b/services/core/java/com/android/server/AppOpsPolicy.java
@@ -0,0 +1,441 @@
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.server;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+
+public class AppOpsPolicy {
+ static final String TAG = "AppOpsPolicy";
+ static final boolean DEBUG = false;
+ final File mFile;
+ final Context mContext;
+ public static final int CONTROL_SHOW = 0;
+
+ public static final int CONTROL_NOSHOW = 1;
+
+ public static final int CONTROL_UNKNOWN = 2;
+
+ public static int stringToControl(String show) {
+ if ("true".equalsIgnoreCase(show)) {
+ return CONTROL_SHOW;
+ } else if ("false".equalsIgnoreCase(show)) {
+ return CONTROL_NOSHOW;
+ }
+ return CONTROL_UNKNOWN;
+ }
+
+ HashMap<String, PolicyPkg> mPolicy = new HashMap<String, PolicyPkg>();
+
+ public AppOpsPolicy(File file, Context context) {
+ super();
+ mFile = file;
+ mContext = context;
+ }
+
+ public final static class PolicyPkg extends SparseArray<PolicyOp> {
+ public String packageName;
+ public int mode;
+ public int show;
+ public String type;
+
+ public PolicyPkg(String packageName, int mode, int show, String type) {
+ this.packageName = packageName;
+ this.mode = mode;
+ this.show = show;
+ this.type = type;
+ }
+
+ @Override
+ public String toString() {
+ return "PolicyPkg [packageName=" + packageName + ", mode=" + mode
+ + ", show=" + show + ", type=" + type + "]";
+ }
+
+ }
+
+ public final static class PolicyOp {
+ public int op;
+ public int mode;
+ public int show;
+
+ public PolicyOp(int op, int mode, int show) {
+ this.op = op;
+ this.mode = mode;
+ this.show = show;
+ }
+
+ @Override
+ public String toString() {
+ return "PolicyOp [op=" + op + ", mode=" + mode + ", show=" + show
+ + "]";
+ }
+ }
+
+ void readPolicy() {
+ FileInputStream stream;
+ synchronized (mFile) {
+ try {
+ stream = new FileInputStream(mFile);
+ } catch (FileNotFoundException e) {
+ Slog.i(TAG, "App ops policy file (" + mFile.getPath()
+ + ") not found; Skipping.");
+ return;
+ }
+ boolean success = false;
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, null);
+ int type;
+ success = true;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ ;
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new IllegalStateException("no start tag found");
+ }
+
+ int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("user-app")
+ || tagName.equals("system-app")) {
+ readDefaultPolicy(parser, tagName);
+ } else if (tagName.equals("application")) {
+ readApplicationPolicy(parser);
+ } else {
+ Slog.w(TAG, "Unknown element under <appops-policy>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (NullPointerException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (IndexOutOfBoundsException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } finally {
+ if (!success) {
+ mPolicy.clear();
+ }
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ private void readDefaultPolicy(XmlPullParser parser, String packageName)
+ throws NumberFormatException, XmlPullParserException, IOException {
+ if (!"user-app".equalsIgnoreCase(packageName)
+ && !"system-app".equalsIgnoreCase(packageName)) {
+ return;
+ }
+ int mode = AppOpsManager.stringToMode(parser.getAttributeValue(null,
+ "permission"));
+ int show = stringToControl(parser.getAttributeValue(null, "show"));
+ if (mode == AppOpsManager.MODE_ERRORED && show == CONTROL_UNKNOWN) {
+ return;
+ }
+ PolicyPkg pkg = this.mPolicy.get(packageName);
+ if (pkg == null) {
+ pkg = new PolicyPkg(packageName, mode, show, packageName);
+ this.mPolicy.put(packageName, pkg);
+ } else {
+ Slog.w(TAG, "Duplicate policy found for package: " + packageName
+ + " of type: " + packageName);
+ pkg.mode = mode;
+ pkg.show = show;
+ }
+ }
+
+ private void readApplicationPolicy(XmlPullParser parser)
+ throws NumberFormatException, XmlPullParserException, IOException {
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ String tagName = parser.getName();
+ if (tagName.equals("pkg")) {
+ readPkgPolicy(parser);
+ } else {
+ Slog.w(TAG,
+ "Unknown element under <application>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ }
+
+ private void readPkgPolicy(XmlPullParser parser)
+ throws NumberFormatException, XmlPullParserException, IOException {
+ String packageName = parser.getAttributeValue(null, "name");
+ if (packageName == null)
+ return;
+ String appType = parser.getAttributeValue(null, "type");
+ if (appType == null)
+ return;
+ int mode = AppOpsManager.stringToMode(parser.getAttributeValue(null,
+ "permission"));
+ int show = stringToControl(parser.getAttributeValue(null, "show"));
+ String key = packageName + "." + appType;
+ PolicyPkg pkg = this.mPolicy.get(key);
+ if (pkg == null) {
+ pkg = new PolicyPkg(packageName, mode, show, appType);
+ this.mPolicy.put(key, pkg);
+ } else {
+ Slog.w(TAG, "Duplicate policy found for package: " + packageName
+ + " of type: " + appType);
+ pkg.mode = mode;
+ pkg.show = show;
+ }
+
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ String tagName = parser.getName();
+ if (tagName.equals("op")) {
+ readOpPolicy(parser, pkg);
+ } else {
+ Slog.w(TAG, "Unknown element under <pkg>: " + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ }
+
+ private void readOpPolicy(XmlPullParser parser, PolicyPkg pkg)
+ throws NumberFormatException, XmlPullParserException, IOException {
+ if (pkg == null) {
+ return;
+ }
+ String opName = parser.getAttributeValue(null, "name");
+ if (opName == null) {
+ Slog.w(TAG, "Op name is null");
+ return;
+ }
+ int code = AppOpsManager.stringOpToOp(opName);
+ if (code == AppOpsManager.OP_NONE) {
+ Slog.w(TAG, "Unknown Op: " + opName);
+ return;
+ }
+ int mode = AppOpsManager.stringToMode(parser.getAttributeValue(null,
+ "permission"));
+ int show = stringToControl(parser.getAttributeValue(null, "show"));
+ if (mode == AppOpsManager.MODE_ERRORED && show == CONTROL_UNKNOWN) {
+ return;
+ }
+ PolicyOp op = pkg.get(code);
+ if (op == null) {
+ op = new PolicyOp(code, mode, show);
+ pkg.put(code, op);
+ } else {
+ Slog.w(TAG, "Duplicate policy found for package: "
+ + pkg.packageName + " type: " + pkg.type + " op: " + op.op);
+ op.mode = mode;
+ op.show = show;
+ }
+ }
+
+ void debugPoilcy() {
+ Iterator<Map.Entry<String, PolicyPkg>> iterator = mPolicy.entrySet()
+ .iterator();
+ while (iterator.hasNext()) {
+ String key = iterator.next().getKey();
+ if (DEBUG)
+ Slog.d(TAG, "Key: " + key);
+ PolicyPkg pkg = mPolicy.get(key);
+ if (pkg == null) {
+ if (DEBUG)
+ Slog.d(TAG, "Pkg is null for key: " + key);
+ continue;
+ }
+ if (DEBUG)
+ Slog.d(TAG, pkg.toString());
+ for (int i = 0; i < pkg.size(); i++) {
+ PolicyOp op = pkg.valueAt(i);
+ if (DEBUG)
+ Slog.d(TAG, op.toString());
+ }
+ }
+ }
+
+ private String getAppType(String packageName) {
+ String appType = null;
+ ApplicationInfo appInfo = null;
+ if (mContext != null) {
+ try {
+ appInfo = mContext.getPackageManager().getApplicationInfo(
+ packageName, 0);
+ } catch (NameNotFoundException e) {
+ appInfo = null;
+ }
+ if (appInfo != null) {
+ if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ appType = "system-app";
+ } else {
+ appType = "user-app";
+ }
+ }
+ } else {
+ Slog.e(TAG, "Context is null");
+ }
+ return appType;
+ }
+
+ public boolean isControlAllowed(int code, String packageName) {
+ boolean isShow = true;
+ int show = CONTROL_UNKNOWN;
+ PolicyPkg pkg;
+ String key;
+ String type;
+
+ if (mPolicy == null) {
+ return isShow;
+ }
+
+ type = getAppType(packageName);
+ if (type != null) {
+ key = type;
+ pkg = mPolicy.get(key);
+ if (pkg != null && pkg.show != CONTROL_UNKNOWN) {
+ show = pkg.show;
+ }
+ }
+ key = packageName;
+ if (type != null) {
+ key = key + "." + type;
+ }
+ pkg = mPolicy.get(key);
+ if (pkg != null) {
+ if (pkg.show != CONTROL_UNKNOWN) {
+ show = pkg.show;
+ }
+ PolicyOp op = pkg.get(code);
+ if (op != null) {
+ if (op.show != CONTROL_UNKNOWN) {
+ show = op.show;
+ }
+ }
+ }
+ if (show == CONTROL_NOSHOW) {
+ isShow = false;
+ }
+ return isShow;
+ }
+
+ public int getDefualtMode(int code, String packageName) {
+ int mode = AppOpsManager.MODE_ERRORED;
+ PolicyPkg pkg;
+ String key;
+ String type;
+
+ if (mPolicy == null) {
+ return mode;
+ }
+ if (DEBUG)
+ Slog.d(TAG, "Default mode requested for op=" + code + " package="
+ + packageName);
+ type = getAppType(packageName);
+ if (type != null) {
+ // Get value based on 'type'
+ key = type;
+ pkg = mPolicy.get(key);
+ if (pkg != null && pkg.mode != AppOpsManager.MODE_ERRORED) {
+ if (DEBUG)
+ Slog.d(TAG, "Setting value based on type: " + pkg);
+ mode = pkg.mode;
+ }
+ }
+ // Get value based on 'pkg'.
+ key = packageName;
+ if (type != null) {
+ key = key + "." + type;
+ }
+ pkg = mPolicy.get(key);
+ if (pkg != null) {
+ if (pkg.mode != AppOpsManager.MODE_ERRORED) {
+ if (DEBUG)
+ Slog.d(TAG, "Setting value based on packageName: " + pkg);
+ mode = pkg.mode;
+ }
+ // Get value base on 'op'
+ PolicyOp op = pkg.get(code);
+ if (op != null) {
+ if (op.mode != AppOpsManager.MODE_ERRORED) {
+ if (DEBUG)
+ Slog.d(TAG, "Setting value based on op: " + op);
+ mode = op.mode;
+ }
+ }
+ }
+ if (DEBUG)
+ Slog.d(TAG, "Returning mode=" + mode);
+ return mode;
+ }
+} \ No newline at end of file
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 96c1e2a..83a0a99 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,7 +38,9 @@ import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.Dialog;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -45,6 +50,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -67,6 +73,7 @@ import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
+import com.android.server.PermissionDialogReqQueue.PermissionDialogReq;
import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
@@ -80,9 +87,23 @@ public class AppOpsService extends IAppOpsService.Stub {
// Write at most every 30 minutes.
static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
+ // Location of policy file.
+ static final String DEFAULT_POLICY_FILE = "/system/etc/appops_policy.xml";
+
Context mContext;
final AtomicFile mFile;
final Handler mHandler;
+ final Looper mLooper;
+ final boolean mStrictEnable;
+ AppOpsPolicy mPolicy;
+
+ private static final int[] PRIVACY_GUARD_OP_STATES = new int[] {
+ AppOpsManager.OP_COARSE_LOCATION,
+ AppOpsManager.OP_READ_CALL_LOG,
+ AppOpsManager.OP_READ_CONTACTS,
+ AppOpsManager.OP_READ_CALENDAR,
+ AppOpsManager.OP_READ_SMS
+ };
boolean mWriteScheduled;
boolean mFastWriteScheduled;
@@ -104,6 +125,14 @@ public class AppOpsService extends IAppOpsService.Stub {
final SparseArray<UidState> mUidStates = new SparseArray<>();
+ private Runnable mSuSessionChangedRunner = new Runnable() {
+ @Override
+ public void run() {
+ mContext.sendBroadcastAsUser(new Intent(AppOpsManager.ACTION_SU_SESSION_CHANGED),
+ UserHandle.ALL);
+ }
+ };
+
private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>();
private static final class UidState {
@@ -149,12 +178,20 @@ public class AppOpsService extends IAppOpsService.Stub {
public long time;
public long rejectTime;
public int nesting;
-
- public Op(int _uid, String _packageName, int _op) {
+ public int noteOpCount;
+ public int startOpCount;
+ public PermissionDialogReqQueue dialogReqQueue;
+ final ArrayList<IBinder> clientTokens;
+ public int allowedCount;
+ public int ignoredCount;
+
+ public Op(int _uid, String _packageName, int _op, int _mode) {
uid = _uid;
packageName = _packageName;
op = _op;
- mode = AppOpsManager.opToDefaultMode(op);
+ mode = _mode;
+ dialogReqQueue = new PermissionDialogReqQueue();
+ clientTokens = new ArrayList<IBinder>();
}
}
@@ -226,17 +263,27 @@ public class AppOpsService extends IAppOpsService.Stub {
}
mClients.remove(mAppToken);
}
+
+ // We cannot broadcast on the synchronized block above because the broadcast might
+ // trigger another appop call that eventually arrives here from a different thread,
+ // causing a deadlock.
+ for (int i=mStartedOps.size()-1; i>=0; i--) {
+ broadcastOpIfNeeded(mStartedOps.get(i).op);
+ }
}
}
public AppOpsService(File storagePath, Handler handler) {
mFile = new AtomicFile(storagePath);
mHandler = handler;
+ mLooper = Looper.myLooper();
+ mStrictEnable = AppOpsManager.isStrictEnable();
readState();
}
public void publish(Context context) {
mContext = context;
+ readPolicy();
ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
}
@@ -372,7 +419,7 @@ public class AppOpsService extends IAppOpsService.Stub {
Op curOp = pkgOps.valueAt(j);
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
curOp.rejectTime, curOp.duration, curOp.proxyUid,
- curOp.proxyPackageName));
+ curOp.proxyPackageName, curOp.allowedCount, curOp.ignoredCount));
}
} else {
for (int j=0; j<ops.length; j++) {
@@ -383,7 +430,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
curOp.rejectTime, curOp.duration, curOp.proxyUid,
- curOp.proxyPackageName));
+ curOp.proxyPackageName, curOp.allowedCount, curOp.ignoredCount));
}
}
}
@@ -475,7 +522,8 @@ public class AppOpsService extends IAppOpsService.Stub {
code = AppOpsManager.opToSwitch(code);
synchronized (this) {
- final int defaultMode = AppOpsManager.opToDefaultMode(code);
+ final int defaultMode = AppOpsManager.opToDefaultMode(code,
+ AppOpsManager.isStrictOp(code));
UidState uidState = getUidStateLocked(uid, false);
if (uidState == null) {
@@ -512,33 +560,35 @@ public class AppOpsService extends IAppOpsService.Stub {
String[] uidPackageNames = getPackagesForUid(uid);
ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
- ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
- if (callbacks != null) {
- final int callbackCount = callbacks.size();
- for (int i = 0; i < callbackCount; i++) {
- Callback callback = callbacks.get(i);
- ArraySet<String> changedPackages = new ArraySet<>();
- Collections.addAll(changedPackages, uidPackageNames);
- callbackSpecs = new ArrayMap<>();
- callbackSpecs.put(callback, changedPackages);
- }
- }
-
- for (String uidPackageName : uidPackageNames) {
- callbacks = mPackageModeWatchers.get(uidPackageName);
+ synchronized (this) {
+ ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
if (callbacks != null) {
- if (callbackSpecs == null) {
- callbackSpecs = new ArrayMap<>();
- }
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
Callback callback = callbacks.get(i);
- ArraySet<String> changedPackages = callbackSpecs.get(callback);
- if (changedPackages == null) {
- changedPackages = new ArraySet<>();
- callbackSpecs.put(callback, changedPackages);
+ ArraySet<String> changedPackages = new ArraySet<>();
+ Collections.addAll(changedPackages, uidPackageNames);
+ callbackSpecs = new ArrayMap<>();
+ callbackSpecs.put(callback, changedPackages);
+ }
+ }
+
+ for (String uidPackageName : uidPackageNames) {
+ callbacks = mPackageModeWatchers.get(uidPackageName);
+ if (callbacks != null) {
+ if (callbackSpecs == null) {
+ callbackSpecs = new ArrayMap<>();
+ }
+ final int callbackCount = callbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ Callback callback = callbacks.get(i);
+ ArraySet<String> changedPackages = callbackSpecs.get(callback);
+ if (changedPackages == null) {
+ changedPackages = new ArraySet<>();
+ callbackSpecs.put(callback, changedPackages);
+ }
+ changedPackages.add(uidPackageName);
}
- changedPackages.add(uidPackageName);
}
}
}
@@ -603,7 +653,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
repCbs.addAll(cbs);
}
- if (mode == AppOpsManager.opToDefaultMode(op.op)) {
+ if (mode == getDefaultMode(code, uid, packageName)) {
// If going into the default mode, prune this op
// if there is nothing else interesting in it.
pruneOp(op, uid, packageName);
@@ -730,9 +780,11 @@ public class AppOpsService extends IAppOpsService.Stub {
Ops pkgOps = ent.getValue();
for (int j=pkgOps.size()-1; j>=0; j--) {
Op curOp = pkgOps.valueAt(j);
+ int defaultMode = getDefaultMode(curOp.op, curOp.uid,
+ curOp.packageName);
if (AppOpsManager.opAllowsReset(curOp.op)
- && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
- curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
+ && curOp.mode != defaultMode) {
+ curOp.mode = defaultMode;
changed = true;
callbacks = addCallbacks(callbacks, packageName, curOp.op,
mOpModeWatchers.get(curOp.op));
@@ -853,7 +905,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
Op op = getOpLocked(code, uid, packageName, false);
if (op == null) {
- return AppOpsManager.opToDefaultMode(code);
+ return getDefaultMode(code, uid, packageName);
}
return op.mode;
}
@@ -944,6 +996,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private int noteOperationUnchecked(int code, int uid, String packageName,
int proxyUid, String proxyPackageName) {
+ final PermissionDialogReq req;
synchronized (this) {
Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
@@ -953,6 +1006,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
Op op = getOpLocked(ops, code, true);
if (isOpRestricted(uid, code, packageName)) {
+ op.ignoredCount++;
return AppOpsManager.MODE_IGNORED;
}
if (op.duration == -1) {
@@ -973,24 +1027,51 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
+ if (switchOp.mode != AppOpsManager.MODE_ALLOWED
+ && switchOp.mode != AppOpsManager.MODE_ASK) {
+ if (DEBUG)
+ Log.d(TAG, "noteOperation: reject #" + op.mode
+ + " for code " + switchCode + " (" + code
+ + ") uid " + uid + " package " + packageName);
op.rejectTime = System.currentTimeMillis();
+ op.ignoredCount++;
return switchOp.mode;
+ } else if (switchOp.mode == AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+ + " package " + packageName);
+ op.time = System.currentTimeMillis();
+ op.rejectTime = 0;
+ op.proxyUid = proxyUid;
+ op.proxyPackageName = proxyPackageName;
+ op.allowedCount++;
+ broadcastOpIfNeeded(code);
+ return AppOpsManager.MODE_ALLOWED;
+
+ } else {
+ if (Looper.myLooper() == mLooper) {
+ Log.e(TAG,
+ "noteOperation: This method will deadlock if called from the main thread. (Code: "
+ + code
+ + " uid: "
+ + uid
+ + " package: "
+ + packageName + ")");
+ return switchOp.mode;
+ }
+ op.noteOpCount++;
+ req = askOperationLocked(code, uid, packageName, switchOp);
}
- if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
- + " package " + packageName);
- op.time = System.currentTimeMillis();
- op.rejectTime = 0;
- op.proxyUid = proxyUid;
- op.proxyPackageName = proxyPackageName;
- return AppOpsManager.MODE_ALLOWED;
}
+
+ int result = req.get();
+ broadcastOpIfNeeded(code);
+ return result;
}
@Override
- public int startOperation(IBinder token, int code, int uid, String packageName) {
+ public int startOperation(IBinder token, int code, int uid,
+ String packageName) {
+ final PermissionDialogReq req;
verifyIncomingUid(uid);
verifyIncomingOp(code);
ClientState client = (ClientState)token;
@@ -1003,6 +1084,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
Op op = getOpLocked(ops, code, true);
if (isOpRestricted(uid, code, packageName)) {
+ op.ignoredCount++;
return AppOpsManager.MODE_IGNORED;
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1018,25 +1100,51 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
+ if (switchOp.mode != AppOpsManager.MODE_ALLOWED
+ && switchOp.mode != AppOpsManager.MODE_ASK) {
+ if (DEBUG)
+ Log.d(TAG, "startOperation: reject #" + op.mode
+ + " for code " + switchCode + " (" + code
+ + ") uid " + uid + " package " + packageName);
op.rejectTime = System.currentTimeMillis();
+ op.ignoredCount++;
return switchOp.mode;
+ } else if (switchOp.mode == AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG)
+ Log.d(TAG, "startOperation: allowing code " + code
+ + " uid " + uid + " package " + packageName);
+ if (op.nesting == 0) {
+ op.time = System.currentTimeMillis();
+ op.rejectTime = 0;
+ op.duration = -1;
+ op.allowedCount++;
+ }
+ op.nesting++;
+ if (client.mStartedOps != null) {
+ client.mStartedOps.add(op);
+ }
+ broadcastOpIfNeeded(code);
+ return AppOpsManager.MODE_ALLOWED;
+ } else {
+ if (Looper.myLooper() == mLooper) {
+ Log.e(TAG,
+ "startOperation: This method will deadlock if called from the main thread. (Code: "
+ + code
+ + " uid: "
+ + uid
+ + " package: "
+ + packageName + ")");
+ return switchOp.mode;
+ }
+ op.startOpCount++;
+ IBinder clientToken = client.mAppToken;
+ op.clientTokens.add(clientToken);
+ req = askOperationLocked(code, uid, packageName, switchOp);
}
- if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
- + " package " + packageName);
- if (op.nesting == 0) {
- op.time = System.currentTimeMillis();
- op.rejectTime = 0;
- op.duration = -1;
- }
- op.nesting++;
- if (client.mStartedOps != null) {
- client.mStartedOps.add(op);
- }
- return AppOpsManager.MODE_ALLOWED;
}
+ int result = req.get();
+ broadcastOpIfNeeded(code);
+ return result;
}
@Override
@@ -1057,6 +1165,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
finishOperationLocked(op);
}
+ broadcastOpIfNeeded(code);
}
@Override
@@ -1081,6 +1190,10 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private void verifyIncomingUid(int uid) {
+ if (Binder.getCallingUid() == 0) {
+ // Allow root to delegate uid operations.
+ return;
+ }
if (uid == Binder.getCallingUid()) {
return;
}
@@ -1115,6 +1228,9 @@ public class AppOpsService extends IAppOpsService.Stub {
packageName = "root";
} else if (uid == Process.SHELL_UID) {
packageName = "com.android.shell";
+ } else if (uid == Process.SYSTEM_UID) {
+ if (packageName == null)
+ packageName = "android";
}
return getOpsRawLocked(uid, packageName, edit);
}
@@ -1202,12 +1318,14 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private Op getOpLocked(Ops ops, int code, boolean edit) {
+ int mode;
Op op = ops.get(code);
if (op == null) {
if (!edit) {
return null;
}
- op = new Op(ops.uidState.uid, ops.packageName, code);
+ mode = getDefaultMode(code, ops.uidState.uid, ops.packageName);
+ op = new Op(ops.uidState.uid, ops.packageName, code, mode);
ops.put(code, op);
}
if (edit) {
@@ -1387,10 +1505,32 @@ public class AppOpsService extends IAppOpsService.Stub {
String tagName = parser.getName();
if (tagName.equals("op")) {
- Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n")));
+ int code = Integer
+ .parseInt(parser.getAttributeValue(null, "n"));
+ // use op name string if it exists
+ String codeNameStr = parser.getAttributeValue(null, "ns");
+ if (codeNameStr != null) {
+ // returns OP_NONE if it could not be mapped
+ code = AppOpsManager.nameToOp(codeNameStr);
+ }
+ // skip op codes that are out of bounds
+ if (code == AppOpsManager.OP_NONE
+ || code >= AppOpsManager._NUM_OP) {
+ continue;
+ }
+ Op op = new Op(uid, pkgName, code, AppOpsManager.MODE_ERRORED);
String mode = parser.getAttributeValue(null, "m");
if (mode != null) {
op.mode = Integer.parseInt(mode);
+ } else {
+ String sDefualtMode = parser.getAttributeValue(null, "dm");
+ int defaultMode;
+ if (sDefualtMode != null) {
+ defaultMode = Integer.parseInt(sDefualtMode);
+ } else {
+ defaultMode = getDefaultMode(code, uid, pkgName);
+ }
+ op.mode = defaultMode;
}
String time = parser.getAttributeValue(null, "t");
if (time != null) {
@@ -1412,7 +1552,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (proxyPackageName != null) {
op.proxyPackageName = proxyPackageName;
}
-
+ String allowed = parser.getAttributeValue(null, "ac");
+ if (allowed != null) {
+ op.allowedCount = Integer.parseInt(allowed);
+ }
+ String ignored = parser.getAttributeValue(null, "ic");
+ if (ignored != null) {
+ op.ignoredCount = Integer.parseInt(ignored);
+ }
UidState uidState = getUidStateLocked(uid, true);
if (uidState.pkgOps == null) {
uidState.pkgOps = new ArrayMap<>();
@@ -1499,8 +1646,13 @@ public class AppOpsService extends IAppOpsService.Stub {
AppOpsManager.OpEntry op = ops.get(j);
out.startTag(null, "op");
out.attribute(null, "n", Integer.toString(op.getOp()));
- if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
+ out.attribute(null, "ns", AppOpsManager.opToName(op.getOp()));
+ int defaultMode = getDefaultMode(op.getOp(),
+ pkg.getUid(), pkg.getPackageName());
+ if (op.getMode() != defaultMode) {
out.attribute(null, "m", Integer.toString(op.getMode()));
+ } else {
+ out.attribute(null, "dm", Integer.toString(defaultMode));
}
long time = op.getTime();
if (time != 0) {
@@ -1522,6 +1674,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (proxyPackageName != null) {
out.attribute(null, "pp", proxyPackageName);
}
+ int allowed = op.getAllowedCount();
+ if (allowed != 0) {
+ out.attribute(null, "ac", Integer.toString(allowed));
+ }
+ int ignored = op.getIgnoredCount();
+ if (ignored != 0) {
+ out.attribute(null, "ic", Integer.toString(ignored));
+ }
out.endTag(null, "op");
}
out.endTag(null, "uid");
@@ -1765,14 +1925,181 @@ public class AppOpsService extends IAppOpsService.Stub {
private void checkSystemUid(String function) {
int uid = Binder.getCallingUid();
if (uid != Process.SYSTEM_UID) {
- throw new SecurityException(function + " must by called by the system");
+ throw new SecurityException(function
+ + " must by called by the system");
+ }
+ }
+
+ final class AskRunnable implements Runnable {
+ final int code;
+ final int uid;
+ final String packageName;
+ final Op op;
+ final PermissionDialogReq request;
+
+ public AskRunnable(int code, int uid, String packageName, Op op,
+ PermissionDialogReq request) {
+ super();
+ this.code = code;
+ this.uid = uid;
+ this.packageName = packageName;
+ this.op = op;
+ this.request = request;
+ }
+
+ @Override
+ public void run() {
+ PermissionDialog permDialog = null;
+ synchronized (AppOpsService.this) {
+ Log.e(TAG, "Creating dialog box");
+ op.dialogReqQueue.register(request);
+ if (op.dialogReqQueue.getDialog() == null) {
+ permDialog = new PermissionDialog(mContext,
+ AppOpsService.this, code, uid, packageName);
+ op.dialogReqQueue.setDialog(permDialog);
+ }
+ }
+ if (permDialog != null) {
+ permDialog.show();
+ }
+ }
+ }
+
+ private PermissionDialogReq askOperationLocked(int code, int uid,
+ String packageName, Op op) {
+ PermissionDialogReq request = new PermissionDialogReq();
+ mHandler.post(new AskRunnable(code, uid, packageName, op, request));
+ return request;
+ }
+
+ private int getDefaultMode(int code, int uid, String packageName) {
+ int mode = AppOpsManager.opToDefaultMode(code,
+ isStrict(code, uid, packageName));
+ if (AppOpsManager.isStrictOp(code) && mPolicy != null) {
+ int policyMode = mPolicy.getDefualtMode(code, packageName);
+ if (policyMode != AppOpsManager.MODE_ERRORED) {
+ mode = policyMode;
+ }
+ }
+ return mode;
+ }
+
+ private boolean isStrict(int code, int uid, String packageName) {
+ if (!mStrictEnable)
+ return false;
+
+ return UserHandle.isApp(uid);
+ }
+
+ private void printOperationLocked(Op op, int mode, String operation) {
+ if(op != null) {
+ int switchCode = AppOpsManager.opToSwitch(op.op);
+ if (mode == AppOpsManager.MODE_IGNORED) {
+ if (DEBUG) Log.d(TAG, operation + ": reject #" + mode + " for code "
+ + switchCode + " (" + op.op + ") uid " + op.uid + " package "
+ + op.packageName);
+ } else if (mode == AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG) Log.d(TAG, operation + ": allowing code " + op.op + " uid "
+ + op.uid
+ + " package " + op.packageName);
+ }
+ }
+ }
+
+ private void recordOperationLocked(int code, int uid, String packageName,
+ int mode) {
+ Op op = getOpLocked(code, uid, packageName, false);
+ if(op != null) {
+ if(op.noteOpCount != 0)
+ printOperationLocked(op, mode, "noteOperartion");
+ if(op.startOpCount != 0)
+ printOperationLocked(op, mode, "startOperation");
+ if (mode == AppOpsManager.MODE_IGNORED) {
+ op.rejectTime = System.currentTimeMillis();
+ } else if (mode == AppOpsManager.MODE_ALLOWED) {
+ if(op.noteOpCount != 0) {
+ op.time = System.currentTimeMillis();
+ op.rejectTime = 0;
+ }
+ if(op.startOpCount != 0) {
+ if(op.nesting == 0) {
+ op.time = System.currentTimeMillis();
+ op.rejectTime = 0;
+ op.duration = -1;
+ }
+ op.nesting = op.nesting + op.startOpCount;
+ while(op.clientTokens.size() != 0) {
+ IBinder clientToken = op.clientTokens.get(0);
+ ClientState client = mClients.get(clientToken);
+ if (client != null) {
+ if (client.mStartedOps != null) {
+ client.mStartedOps.add(op);
+ }
+ }
+ op.clientTokens.remove(0);
+ }
+ }
+ }
+ op.clientTokens.clear();
+ op.startOpCount = 0;
+ op.noteOpCount = 0;
+ }
+ }
+
+ public void notifyOperation(int code, int uid, String packageName,
+ int mode, boolean remember) {
+ verifyIncomingUid(uid);
+ verifyIncomingOp(code);
+ ArrayList<Callback> repCbs = null;
+ int switchCode = AppOpsManager.opToSwitch(code);
+ synchronized (this) {
+ recordOperationLocked(code, uid, packageName, mode);
+ Op op = getOpLocked(switchCode, uid, packageName, true);
+ if (op != null) {
+ // Send result to all waiting client
+ if (op.dialogReqQueue.getDialog() != null) {
+ op.dialogReqQueue.notifyAll(mode);
+ op.dialogReqQueue.setDialog(null);
+ }
+ if (remember && op.mode != mode) {
+ op.mode = mode;
+ ArrayList<Callback> cbs = mOpModeWatchers.get(switchCode);
+ if (cbs != null) {
+ if (repCbs == null) {
+ repCbs = new ArrayList<Callback>();
+ }
+ repCbs.addAll(cbs);
+ }
+ cbs = mPackageModeWatchers.get(packageName);
+ if (cbs != null) {
+ if (repCbs == null) {
+ repCbs = new ArrayList<Callback>();
+ }
+ repCbs.addAll(cbs);
+ }
+ if (mode == getDefaultMode(op.op, op.uid, op.packageName)) {
+ // If going into the default mode, prune this op
+ // if there is nothing else interesting in it.
+ pruneOp(op, uid, packageName);
+ }
+ scheduleWriteLocked();
+ }
+ }
+ }
+ if (repCbs != null) {
+ for (int i = 0; i < repCbs.size(); i++) {
+ try {
+ repCbs.get(i).mCallback.opChanged(switchCode, packageName);
+ } catch (RemoteException e) {
+ }
+ }
}
}
private static String[] getPackagesForUid(int uid) {
String[] packageNames = null;
try {
- packageNames= AppGlobals.getPackageManager().getPackagesForUid(uid);
+ packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
} catch (RemoteException e) {
/* ignore - local call */
}
@@ -1781,4 +2108,75 @@ public class AppOpsService extends IAppOpsService.Stub {
}
return packageNames;
}
+
+ private void broadcastOpIfNeeded(int op) {
+ switch (op) {
+ case AppOpsManager.OP_SU:
+ mHandler.post(mSuSessionChangedRunner);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void readPolicy() {
+ if (mStrictEnable) {
+ mPolicy = new AppOpsPolicy(new File(DEFAULT_POLICY_FILE), mContext);
+ mPolicy.readPolicy();
+ mPolicy.debugPoilcy();
+ } else {
+ mPolicy = null;
+ }
+ }
+
+ public boolean isControlAllowed(int code, String packageName) {
+ boolean isShow = true;
+ if (mPolicy != null) {
+ isShow = mPolicy.isControlAllowed(code, packageName);
+ }
+ return isShow;
+ }
+
+ @Override
+ public boolean getPrivacyGuardSettingForPackage(int uid, String packageName) {
+ for (int op : PRIVACY_GUARD_OP_STATES) {
+ int switchOp = AppOpsManager.opToSwitch(op);
+ int mode = checkOperation(op, uid, packageName);
+ if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_IGNORED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void setPrivacyGuardSettingForPackage(int uid, String packageName, boolean state) {
+ for (int op : PRIVACY_GUARD_OP_STATES) {
+ int switchOp = AppOpsManager.opToSwitch(op);
+ setMode(switchOp, uid, packageName, state
+ ? AppOpsManager.MODE_ASK : AppOpsManager.MODE_ALLOWED);
+ }
+ }
+
+ @Override
+ public void resetCounters() {
+ mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ synchronized (this) {
+ for (int i=0; i<mUidStates.size(); i++) {
+ final UidState uidState = mUidStates.valueAt(i);
+ for (Map.Entry<String, Ops> ent : uidState.pkgOps.entrySet()) {
+ String packageName = ent.getKey();
+ Ops pkgOps = ent.getValue();
+ for (int j=0; j<pkgOps.size(); j++) {
+ Op curOp = pkgOps.valueAt(j);
+ curOp.allowedCount = 0;
+ curOp.ignoredCount = 0;
+ }
+ }
+ }
+ // ensure the counter reset persists
+ scheduleWriteLocked();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 4569dae..ff4456e 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -391,6 +391,11 @@ public class AssetAtlasService extends IAssetAtlas.Stub {
}
}
+ if (results.size() == 0) {
+ if (DEBUG_ATLAS) Log.w(LOG_TAG, "No atlas configuration found!");
+ return null;
+ }
+
// Maximize the number of packed bitmaps, minimize the texture size
Collections.sort(results, new Comparator<WorkerResult>() {
@Override
diff --git a/services/core/java/com/android/server/BasePermissionDialog.java b/services/core/java/com/android/server/BasePermissionDialog.java
new file mode 100644
index 0000000..e3dbcda
--- /dev/null
+++ b/services/core/java/com/android/server/BasePermissionDialog.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import com.android.internal.R;
+
+public class BasePermissionDialog extends AlertDialog {
+ public BasePermissionDialog(Context context) {
+ super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+ getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ WindowManager.LayoutParams attrs = getWindow().getAttributes();
+ attrs.setTitle("Permission Dialog");
+ getWindow().setAttributes(attrs);
+ setIconAttribute(R.attr.alertDialogIcon);
+ }
+
+ public void onStart() {
+ super.onStart();
+ setEnabled(false);
+ mHandler.sendMessage(mHandler.obtainMessage(0));
+ }
+
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (mConsuming) {
+ // Slog.i(TAG, "Consuming: " + event);
+ return true;
+ }
+ // Slog.i(TAG, "Dispatching: " + event);
+ return super.dispatchKeyEvent(event);
+ }
+
+ private void setEnabled(boolean enabled) {
+ Button b = (Button) findViewById(R.id.button1);
+ if (b != null) {
+ b.setEnabled(enabled);
+ }
+ b = (Button) findViewById(R.id.button2);
+ if (b != null) {
+ b.setEnabled(enabled);
+ }
+ b = (Button) findViewById(R.id.button3);
+ if (b != null) {
+ b.setEnabled(enabled);
+ }
+ }
+
+ private Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ if (msg.what == 0) {
+ mConsuming = false;
+ setEnabled(true);
+ }
+ }
+ };
+
+ private boolean mConsuming = true;
+}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 2eeaec9..f20cfe9 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,10 +26,16 @@ import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import android.app.ActivityManagerNative;
+import android.app.IBatteryService;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.BatteryProperties;
@@ -51,9 +58,14 @@ import android.util.Slog;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import cyanogenmod.providers.CMSettings;
/**
* <p>BatteryService monitors the charging status, and charge level of the device
@@ -77,6 +89,21 @@ import java.io.PrintWriter;
* a degree Centigrade</p>
* <p>&quot;technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
*
+ * <p>If a dock battery is present, then this Intent data will be present too related
+ * to dock battery information:</p>
+ * <p>&quot;dock_scale&quot; - int, the maximum value for the charge level</p>
+ * <p>&quot;dock_level&quot; - int, charge level, from 0 through &quot;scale&quot; inclusive</p>
+ * <p>&quot;dock_status&quot; - String, the current charging status.<br />
+ * <p>&quot;dock_health&quot; - String, the current battery health.<br />
+ * <p>&quot;dock_present&quot; - boolean, true if the battery is present<br />
+ * <p>&quot;dock_icon-small&quot; - int, suggested small icon to use for this state</p>
+ * <p>&quot;dock_plugged&quot; - int, 0 if the device is not plugged in; 1 if plugged
+ * into an AC power adapter; 2 if plugged in via USB.</p>
+ * <p>&quot;dock_voltage&quot; - int, current battery voltage in millivolts</p>
+ * <p>&quot;dock_temperature&quot; - int, current battery temperature in tenths of
+ * a degree Centigrade</p>
+ * <p>&quot;dock_technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
+ *
* <p>
* The battery service may be called by the power manager while holding its locks so
* we take care to post all outcalls into the activity manager to a handler.
@@ -92,6 +119,9 @@ public final class BatteryService extends SystemService {
private static final int BATTERY_SCALE = 100; // battery capacity is a percentage
+ // notification light maximum brightness value to use
+ private static final int LIGHT_BRIGHTNESS_MAXIMUM = 255;
+
// Used locally for determining when to make a last ditch effort to log
// discharge stats before the device dies.
private int mCriticalBatteryLevel;
@@ -122,17 +152,34 @@ public final class BatteryService extends SystemService {
private boolean mLastBatteryLevelCritical;
private int mLastMaxChargingCurrent;
+ private boolean mDockBatterySupported;
+ private int mLastDockBatteryStatus;
+ private int mLastDockBatteryHealth;
+ private boolean mLastDockBatteryPresent;
+ private int mLastDockBatteryLevel;
+ private int mLastDockBatteryVoltage;
+ private int mLastDockBatteryTemperature;
+
private int mInvalidCharger;
private int mLastInvalidCharger;
+ private boolean mAdjustableNotificationLedBrightness;
+ private int mNotificationLedBrightnessLevel = LIGHT_BRIGHTNESS_MAXIMUM;
+
+ private boolean mMultipleNotificationLeds;
+ private boolean mMultipleLedsEnabled = false;
+
private int mLowBatteryWarningLevel;
private int mLowBatteryCloseWarningLevel;
private int mShutdownBatteryTemperature;
private int mPlugType;
private int mLastPlugType = -1; // Extra state so we can detect first run
+ private int mDockPlugType;
+ private int mLastDockPlugType = -1; // Extra state so we can detect first run
private boolean mBatteryLevelLow;
+ private boolean mDockBatteryLevelLow;
private long mDischargeStartTime;
private int mDischargeStartLevel;
@@ -140,9 +187,19 @@ public final class BatteryService extends SystemService {
private boolean mUpdatesStopped;
private Led mLed;
+ // Disable LED until SettingsObserver can be started
+ private boolean mLightEnabled = false;
+ private boolean mLedPulseEnabled;
+ private int mBatteryLowARGB;
+ private int mBatteryMediumARGB;
+ private int mBatteryFullARGB;
+ private boolean mMultiColorLed;
private boolean mSentLowBatteryBroadcast = false;
+ private boolean mShowBatteryFullyChargedNotification;
+ private boolean mIsShowingBatteryFullyChargedNotification;
+
public BatteryService(Context context) {
super(context);
@@ -151,6 +208,10 @@ public final class BatteryService extends SystemService {
mLed = new Led(context, getLocalService(LightsManager.class));
mBatteryStats = BatteryStatsService.getService();
+ // By default dock battery are not supported. The first events will refresh
+ // this status from the battery property bag
+ mDockBatterySupported = false;
+
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mLowBatteryWarningLevel = mContext.getResources().getInteger(
@@ -159,6 +220,8 @@ public final class BatteryService extends SystemService {
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
+ mShowBatteryFullyChargedNotification = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_showBatteryFullyChargedNotification);
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
@@ -178,7 +241,7 @@ public final class BatteryService extends SystemService {
// Should never happen.
}
- publishBinderService("battery", new BinderService());
+ publishBinderService(Context.BATTERY_SERVICE, new BinderService());
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
@@ -201,6 +264,9 @@ public final class BatteryService extends SystemService {
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevelLocked();
}
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ SettingsObserver observer = new SettingsObserver(new Handler());
+ observer.observe();
}
}
@@ -257,8 +323,10 @@ public final class BatteryService extends SystemService {
private void shutdownIfNoPowerLocked() {
// shut down gracefully if our battery is critically low and we are not powered.
+ // or the battery voltage is decreasing (consumption rate higher than charging rate)
// wait until the system has booted before attempting to display the shutdown dialog.
- if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
+ if (mBatteryProps.batteryLevel == 0 && (!isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY) ||
+ mBatteryProps.batteryVoltage < mLastBatteryVoltage) ) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -308,21 +376,31 @@ public final class BatteryService extends SystemService {
boolean logOutlier = false;
long dischargeDuration = 0;
+ mDockBatterySupported = mBatteryProps.dockBatterySupported;
+
mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
+ mPlugType = BATTERY_PLUGGED_NONE;
if (mBatteryProps.chargerAcOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mBatteryProps.chargerUsbOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
} else if (mBatteryProps.chargerWirelessOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
- } else {
- mPlugType = BATTERY_PLUGGED_NONE;
+ }
+ mDockPlugType = BATTERY_PLUGGED_NONE;
+ if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerAcOnline) {
+ mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_AC;
+ } else if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerUsbOnline) {
+ mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_USB;
}
if (DEBUG) {
- Slog.d(TAG, "Processing new values: "
- + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
- + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
+ String msg = "Processing new values: "
+ + "chargerAcOnline=" + mBatteryProps.chargerAcOnline;
+ if (mDockBatterySupported) {
+ msg += ", chargerDockAcOnline=" + mBatteryProps.chargerDockAcOnline;
+ }
+ msg += ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
+ ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
+ ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent
+ ", batteryStatus=" + mBatteryProps.batteryStatus
@@ -332,8 +410,22 @@ public final class BatteryService extends SystemService {
+ ", batteryTechnology=" + mBatteryProps.batteryTechnology
+ ", batteryVoltage=" + mBatteryProps.batteryVoltage
+ ", batteryTemperature=" + mBatteryProps.batteryTemperature
- + ", mBatteryLevelCritical=" + mBatteryLevelCritical
- + ", mPlugType=" + mPlugType);
+ + ", mBatteryLevelCritical=" + mBatteryLevelCritical;
+ if (mDockBatterySupported) {
+ msg += ", dockBatteryStatus=" + mBatteryProps.dockBatteryStatus
+ + ", dockBatteryHealth=" + mBatteryProps.dockBatteryHealth
+ + ", dockBatteryPresent=" + mBatteryProps.dockBatteryPresent
+ + ", dockBatteryLevel=" + mBatteryProps.dockBatteryLevel
+ + ", dockBatteryTechnology=" + mBatteryProps.dockBatteryTechnology
+ + ", dockBatteryVoltage=" + mBatteryProps.dockBatteryVoltage
+ + ", dockBatteryTemperature=" + mBatteryProps.dockBatteryTemperature;
+ }
+ msg += ", mPlugType=" + mPlugType;
+ if (mDockBatterySupported) {
+ msg += ", mDockPlugType=" + mDockPlugType;
+ }
+
+ Slog.d(TAG, msg);
}
// Let the battery stats keep track of the current level.
@@ -344,19 +436,40 @@ public final class BatteryService extends SystemService {
} catch (RemoteException e) {
// Should never happen.
}
+ if (mDockBatterySupported) {
+ try {
+ mBatteryStats.setDockBatteryState(mBatteryProps.dockBatteryStatus,
+ mBatteryProps.dockBatteryHealth, mDockPlugType,
+ mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryTemperature,
+ mBatteryProps.dockBatteryVoltage);
+ } catch (RemoteException e) {
+ // Should never happen.
+ }
+ }
shutdownIfNoPowerLocked();
shutdownIfOverTempLocked();
- if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
+ final boolean batteryChanged = mBatteryProps.batteryStatus != mLastBatteryStatus ||
mBatteryProps.batteryHealth != mLastBatteryHealth ||
mBatteryProps.batteryPresent != mLastBatteryPresent ||
mBatteryProps.batteryLevel != mLastBatteryLevel ||
mPlugType != mLastPlugType ||
mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
- mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent ||
- mInvalidCharger != mLastInvalidCharger)) {
+ mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent;
+
+ final boolean dockBatteryChanged = mDockBatterySupported &&
+ (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus ||
+ mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth ||
+ mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent ||
+ mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel ||
+ mDockPlugType != mLastDockPlugType ||
+ mBatteryProps.dockBatteryVoltage != mLastDockBatteryVoltage ||
+ mBatteryProps.dockBatteryTemperature != mLastDockBatteryTemperature);
+
+ if (force || batteryChanged || dockBatteryChanged ||
+ mInvalidCharger != mLastInvalidCharger) {
if (mPlugType != mLastPlugType) {
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -386,12 +499,30 @@ public final class BatteryService extends SystemService {
mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
mPlugType, mBatteryProps.batteryTechnology);
}
+ if (mDockBatterySupported &&
+ (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus ||
+ mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth ||
+ mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent ||
+ mDockPlugType != mLastDockPlugType)) {
+ EventLog.writeEvent(EventLogTags.DOCK_BATTERY_STATUS,
+ mBatteryProps.dockBatteryStatus, mBatteryProps.dockBatteryHealth,
+ mBatteryProps.dockBatteryPresent ? 1 : 0,
+ mDockPlugType, mBatteryProps.dockBatteryTechnology);
+ }
if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
// Don't do this just from voltage or temperature changes, that is
// too noisy.
EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
}
+ if (mDockBatterySupported &&
+ (mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel)) {
+ // Don't do this just from voltage or temperature changes, that is
+ // too noisy.
+ EventLog.writeEvent(EventLogTags.DOCK_BATTERY_LEVEL,
+ mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryVoltage,
+ mBatteryProps.dockBatteryTemperature);
+ }
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
mPlugType == BATTERY_PLUGGED_NONE) {
// We want to make sure we log discharge cycle outliers
@@ -418,13 +549,34 @@ public final class BatteryService extends SystemService {
mBatteryLevelLow = false;
}
}
+ if (mDockBatterySupported) {
+ if (!mDockBatteryLevelLow) {
+ // Should we now switch in to low battery mode?
+ if (mDockPlugType == BATTERY_PLUGGED_NONE
+ && mBatteryProps.dockBatteryLevel <= mLowBatteryWarningLevel) {
+ mDockBatteryLevelLow = true;
+ }
+ } else {
+ // Should we now switch out of low battery mode?
+ if (mDockPlugType != BATTERY_PLUGGED_NONE) {
+ mDockBatteryLevelLow = false;
+ } else if (mBatteryProps.dockBatteryLevel >= mLowBatteryCloseWarningLevel) {
+ mDockBatteryLevelLow = false;
+ } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
+ // If being forced, the previous state doesn't matter, we will just
+ // absolutely check to see if we are now above the warning level.
+ mDockBatteryLevelLow = false;
+ }
+ }
+ }
sendIntentLocked();
// Separate broadcast is sent for power connected / not connected
// since the standard intent will not wake any applications and some
// applications may want to have smart behavior based on this.
- if (mPlugType != 0 && mLastPlugType == 0) {
+ if (mPlugType != 0 && mLastPlugType == 0 ||
+ (mLastPlugType == 0 && mDockPlugType != 0 && mLastDockPlugType == 0)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -434,7 +586,8 @@ public final class BatteryService extends SystemService {
}
});
}
- else if (mPlugType == 0 && mLastPlugType != 0) {
+ else if (mPlugType == 0 && mLastPlugType != 0 ||
+ (mLastPlugType != 0 && mDockPlugType == 0 && mLastDockPlugType != 0)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -470,6 +623,12 @@ public final class BatteryService extends SystemService {
// Update the battery LED
mLed.updateLightsLocked();
+ if (shouldShowBatteryFullyChargedNotificationLocked()) {
+ showBatteryFullyChargedNotificationLocked();
+ } else if (shouldClearBatteryFullyChargedNotificationLocked()) {
+ clearBatteryFullyChargedNotificationLocked();
+ }
+
// This needs to be done after sendIntent() so that we get the lastest battery stats.
if (logOutlier && dischargeDuration != 0) {
logOutlierLocked(dischargeDuration);
@@ -484,6 +643,14 @@ public final class BatteryService extends SystemService {
mLastBatteryTemperature = mBatteryProps.batteryTemperature;
mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
mLastBatteryLevelCritical = mBatteryLevelCritical;
+ mLastDockBatteryStatus = mBatteryProps.dockBatteryStatus;
+ mLastDockBatteryHealth = mBatteryProps.dockBatteryHealth;
+ mLastDockBatteryPresent = mBatteryProps.dockBatteryPresent;
+ mLastDockBatteryLevel = mBatteryProps.dockBatteryLevel;
+ mLastDockPlugType = mDockPlugType;
+ mLastDockBatteryVoltage = mBatteryProps.dockBatteryVoltage;
+ mLastDockBatteryTemperature = mBatteryProps.dockBatteryTemperature;
+
mLastInvalidCharger = mInvalidCharger;
}
}
@@ -495,6 +662,7 @@ public final class BatteryService extends SystemService {
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
int icon = getIconLocked(mBatteryProps.batteryLevel);
+ int dockIcon = 0;
intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
@@ -509,19 +677,62 @@ public final class BatteryService extends SystemService {
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
+ if (mDockBatterySupported) {
+ dockIcon = getDockIconLocked(mBatteryProps.dockBatteryLevel);
+
+ intent.putExtra(BatteryManager.EXTRA_DOCK_STATUS, mBatteryProps.dockBatteryStatus);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_HEALTH, mBatteryProps.dockBatteryHealth);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_PRESENT, mBatteryProps.dockBatteryPresent);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_LEVEL, mBatteryProps.dockBatteryLevel);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_SCALE, BATTERY_SCALE);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_ICON_SMALL, dockIcon);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_PLUGGED, mDockPlugType);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, mBatteryProps.dockBatteryVoltage);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE,
+ mBatteryProps.dockBatteryTemperature);
+ intent.putExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY,
+ mBatteryProps.dockBatteryTechnology);
+
+ // EEPAD legacy data
+ intent.putExtra("usb_wakeup", mBatteryProps.chargerUsbOnline);
+ intent.putExtra("ac_online", mBatteryProps.chargerAcOnline);
+ intent.putExtra("dock_ac_online", mBatteryProps.chargerDockAcOnline);
+ }
+
+
if (DEBUG) {
- Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
- ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
+ String msg = "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
+ ", scale:" + BATTERY_SCALE +
+ ", status:" + mBatteryProps.batteryStatus +
", health:" + mBatteryProps.batteryHealth +
", present:" + mBatteryProps.batteryPresent +
", voltage: " + mBatteryProps.batteryVoltage +
", temperature: " + mBatteryProps.batteryTemperature +
", technology: " + mBatteryProps.batteryTechnology +
- ", AC powered:" + mBatteryProps.chargerAcOnline +
- ", USB powered:" + mBatteryProps.chargerUsbOnline +
- ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
- ", icon:" + icon + ", invalid charger:" + mInvalidCharger +
- ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent);
+ ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent;
+
+ if (mDockBatterySupported) {
+ msg += ", dock_level:" + mBatteryProps.dockBatteryLevel +
+ ", dock_status:" + mBatteryProps.dockBatteryStatus +
+ ", dock_health:" + mBatteryProps.dockBatteryHealth +
+ ", dock_present:" + mBatteryProps.dockBatteryPresent +
+ ", dock_voltage: " + mBatteryProps.dockBatteryVoltage +
+ ", dock_temperature: " + mBatteryProps.dockBatteryTemperature +
+ ", dock_technology: " + mBatteryProps.dockBatteryTechnology;
+ }
+ msg += ", AC powered:" + mBatteryProps.chargerAcOnline;
+ if (mDockBatterySupported) {
+ msg += ", Dock AC powered:" + mBatteryProps.chargerDockAcOnline;
+ }
+ msg += ", USB powered:" + mBatteryProps.chargerUsbOnline +
+ ", Wireless powered:" + mBatteryProps.chargerWirelessOnline;
+ msg += ", icon:" + icon;
+ if (mDockBatterySupported) {
+ msg += ", dock_icon:" + dockIcon;
+ }
+ msg += ", invalid charger:" + mInvalidCharger;
+
+ Slog.d(TAG, msg);
}
mHandler.post(new Runnable() {
@@ -616,6 +827,22 @@ public final class BatteryService extends SystemService {
}
}
+ private int getDockIconLocked(int level) {
+ if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
+ return com.android.internal.R.drawable.stat_sys_battery_charge;
+ } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+ return com.android.internal.R.drawable.stat_sys_battery;
+ } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
+ || mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
+ if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
+ && mBatteryProps.dockBatteryLevel >= 100) {
+ return com.android.internal.R.drawable.stat_sys_battery_charge;
+ }
+ return com.android.internal.R.drawable.stat_sys_battery;
+ }
+ return com.android.internal.R.drawable.stat_sys_battery_unknown;
+ }
+
private void dumpInternal(PrintWriter pw, String[] args) {
synchronized (mLock) {
if (args == null || args.length == 0 || "-a".equals(args[0])) {
@@ -624,6 +851,9 @@ public final class BatteryService extends SystemService {
pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
}
pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
+ if (mDockBatterySupported) {
+ pw.println(" Dock AC powered: " + mBatteryProps.chargerDockAcOnline);
+ }
pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
@@ -635,7 +865,15 @@ public final class BatteryService extends SystemService {
pw.println(" voltage: " + mBatteryProps.batteryVoltage);
pw.println(" temperature: " + mBatteryProps.batteryTemperature);
pw.println(" technology: " + mBatteryProps.batteryTechnology);
-
+ if (mDockBatterySupported) {
+ pw.println(" dock_status: " + mBatteryProps.dockBatteryStatus);
+ pw.println(" dock_health: " + mBatteryProps.dockBatteryHealth);
+ pw.println(" dock_present: " + mBatteryProps.dockBatteryPresent);
+ pw.println(" dock_level: " + mBatteryProps.dockBatteryLevel);
+ pw.println(" dock_voltage: " + mBatteryProps.dockBatteryVoltage);
+ pw.println(" dock_temperature: " + mBatteryProps.dockBatteryTemperature);
+ pw.println(" dock_technology: " + mBatteryProps.dockBatteryTechnology);
+ }
} else if ("unplug".equals(args[0])) {
if (!mUpdatesStopped) {
mLastBatteryProps.set(mBatteryProps);
@@ -661,6 +899,8 @@ public final class BatteryService extends SystemService {
boolean update = true;
if ("ac".equals(key)) {
mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
+ } else if (mDockBatterySupported && "dockac".equals(key)) {
+ mBatteryProps.chargerDockAcOnline = Integer.parseInt(value) != 0;
} else if ("usb".equals(key)) {
mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
} else if ("wireless".equals(key)) {
@@ -669,6 +909,10 @@ public final class BatteryService extends SystemService {
mBatteryProps.batteryStatus = Integer.parseInt(value);
} else if ("level".equals(key)) {
mBatteryProps.batteryLevel = Integer.parseInt(value);
+ } else if (mDockBatterySupported && "dockstatus".equals(key)) {
+ mBatteryProps.dockBatteryStatus = Integer.parseInt(value);
+ } else if (mDockBatterySupported && "docklevel".equals(key)) {
+ mBatteryProps.dockBatteryLevel = Integer.parseInt(value);
} else if ("invalid".equals(key)) {
mInvalidCharger = Integer.parseInt(value);
} else {
@@ -701,7 +945,12 @@ public final class BatteryService extends SystemService {
}
} else {
pw.println("Dump current battery state, or:");
- pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ if (mDockBatterySupported) {
+ pw.println(" set [ac|dockac|usb|wireless|status|level|dockstatus" +
+ "|docklevel|invalid] <value>");
+ } else {
+ pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ }
pw.println(" unplug");
pw.println(" reset");
}
@@ -720,53 +969,159 @@ public final class BatteryService extends SystemService {
}
};
+ private synchronized void updateLedPulse() {
+ mLed.updateLightsLocked();
+ }
+
+ private boolean shouldShowBatteryFullyChargedNotificationLocked() {
+ return mShowBatteryFullyChargedNotification && mPlugType != 0
+ && mBatteryProps.batteryLevel == BATTERY_SCALE
+ && !mIsShowingBatteryFullyChargedNotification;
+ }
+
+ private void showBatteryFullyChargedNotificationLocked() {
+ NotificationManager nm = mContext.getSystemService(NotificationManager.class);
+ Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+ PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
+ intent, 0, null, UserHandle.CURRENT);
+
+ CharSequence title = mContext.getText(
+ com.android.internal.R.string.notify_battery_fully_charged_title);
+ CharSequence message = mContext.getText(
+ com.android.internal.R.string.notify_battery_fully_charged_text);
+
+ Notification notification = new Notification.Builder(mContext)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_battery_charge)
+ .setWhen(0)
+ .setOngoing(false)
+ .setAutoCancel(true)
+ .setTicker(title)
+ .setDefaults(0) // please be quiet
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(message)
+ .setStyle(new Notification.BigTextStyle().bigText(message))
+ .setContentIntent(pi)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build();
+
+ nm.notifyAsUser(null, com.android.internal.R.string.notify_battery_fully_charged_title,
+ notification, UserHandle.ALL);
+ mIsShowingBatteryFullyChargedNotification = true;
+ }
+
+ private boolean shouldClearBatteryFullyChargedNotificationLocked() {
+ return mIsShowingBatteryFullyChargedNotification &&
+ (mPlugType == 0 || mBatteryProps.batteryLevel < BATTERY_SCALE);
+ }
+
+ private void clearBatteryFullyChargedNotificationLocked() {
+ NotificationManager nm = mContext.getSystemService(NotificationManager.class);
+ nm.cancel(com.android.internal.R.string.notify_battery_fully_charged_title);
+ mIsShowingBatteryFullyChargedNotification = false;
+ }
+
private final class Led {
private final Light mBatteryLight;
- private final int mBatteryLowARGB;
- private final int mBatteryMediumARGB;
- private final int mBatteryFullARGB;
private final int mBatteryLedOn;
private final int mBatteryLedOff;
public Led(Context context, LightsManager lights) {
mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
- mBatteryLowARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryLowARGB);
- mBatteryMediumARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
- mBatteryFullARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryFullARGB);
+ // Does the Device support changing battery LED colors?
+ mMultiColorLed = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_multiColorBatteryLed);
+
+ // Is the notification LED brightness changeable ?
+ mAdjustableNotificationLedBrightness = context.getResources().getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness);
+
+ // Does the Device have multiple LEDs ?
+ mMultipleNotificationLeds = context.getResources().getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds);
+
mBatteryLedOn = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLedOn);
mBatteryLedOff = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLedOff);
}
+ private boolean isHvdcpPresent() {
+ File mChargerTypeFile = new File("/sys/class/power_supply/usb/type");
+ FileReader fileReader;
+ BufferedReader br;
+ String type;
+ boolean ret = false;
+
+ if (!mChargerTypeFile.exists()) {
+ // Device does not support HVDCP
+ return ret;
+ }
+
+ try {
+ fileReader = new FileReader(mChargerTypeFile);
+ br = new BufferedReader(fileReader);
+ type = br.readLine();
+ if (type.regionMatches(true, 0, "USB_HVDCP", 0, 9))
+ ret = true;
+ br.close();
+ fileReader.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failure in reading charger type", e);
+ }
+
+ return ret;
+ }
+
/**
* Synchronize on BatteryService.
*/
public void updateLightsLocked() {
+ // mBatteryProps could be null on startup (called by SettingsObserver)
+ if (mBatteryProps == null) {
+ Slog.w(TAG, "updateLightsLocked: mBatteryProps is null; skipping");
+ return;
+ }
+
final int level = mBatteryProps.batteryLevel;
final int status = mBatteryProps.batteryStatus;
- if (level < mLowBatteryWarningLevel) {
+ if (!mLightEnabled) {
+ // No lights if explicitly disabled
+ mBatteryLight.turnOff();
+ } else if (level < mLowBatteryWarningLevel) {
+ mBatteryLight.setModes(mNotificationLedBrightnessLevel,
+ mMultipleLedsEnabled);
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
- // Solid red when battery is charging
+ // Battery is charging and low
mBatteryLight.setColor(mBatteryLowARGB);
- } else {
- // Flash red when battery is low and not charging
+ } else if (mLedPulseEnabled) {
+ // Battery is low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
mBatteryLedOn, mBatteryLedOff);
+ } else {
+ // "Pulse low battery light" is disabled, no lights.
+ mBatteryLight.turnOff();
}
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL) {
+ mBatteryLight.setModes(mNotificationLedBrightnessLevel,
+ mMultipleLedsEnabled);
if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
- // Solid green when full or charging and nearly full
+ // Battery is full or charging and nearly full
mBatteryLight.setColor(mBatteryFullARGB);
} else {
- // Solid orange when charging and halfway full
- mBatteryLight.setColor(mBatteryMediumARGB);
+ if (isHvdcpPresent()) {
+ // Blinking orange if HVDCP charger
+ mBatteryLight.setFlashing(mBatteryMediumARGB, Light.LIGHT_FLASH_TIMED,
+ mBatteryLedOn, mBatteryLedOn);
+ } else {
+ // Battery is charging and halfway full
+ mBatteryLight.setColor(mBatteryMediumARGB);
+ }
}
} else {
// No lights if not charging and not low
@@ -787,7 +1142,12 @@ public final class BatteryService extends SystemService {
}
}
- private final class BinderService extends Binder {
+ private final class BinderService extends IBatteryService.Stub {
+ @Override
+ public boolean isDockBatterySupported() throws RemoteException {
+ return getLocalService(BatteryManagerInternal.class).isDockBatterySupported();
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -833,10 +1193,130 @@ public final class BatteryService extends SystemService {
}
@Override
+ public int getDockPlugType() {
+ synchronized (mLock) {
+ return mDockPlugType;
+ }
+ }
+
+ @Override
+ public int getDockBatteryLevel() {
+ synchronized (mLock) {
+ return mBatteryProps.dockBatteryLevel;
+ }
+ }
+
+ @Override
+ public boolean getDockBatteryLevelLow() {
+ synchronized (mLock) {
+ return mDockBatteryLevelLow;
+ }
+ }
+
+ @Override
public int getInvalidCharger() {
synchronized (mLock) {
return mInvalidCharger;
}
}
+
+ @Override
+ public boolean isDockBatterySupported() {
+ synchronized (mLock) {
+ return mDockBatterySupported;
+ }
+ }
+ }
+
+ class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+
+ // Battery light enabled
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.BATTERY_LIGHT_ENABLED), false, this, UserHandle.USER_ALL);
+
+ // Low battery pulse
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.BATTERY_LIGHT_PULSE), false, this, UserHandle.USER_ALL);
+
+ // Notification LED brightness
+ if (mAdjustableNotificationLedBrightness) {
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL),
+ false, this, UserHandle.USER_ALL);
+ }
+
+ // Multiple LEDs enabled
+ if (mMultipleNotificationLeds) {
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_MULTIPLE_LEDS_ENABLE),
+ false, this, UserHandle.USER_ALL);
+ }
+
+ // Light colors
+ if (mMultiColorLed) {
+ // Register observer if we have a multi color led
+ resolver.registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.BATTERY_LIGHT_LOW_COLOR),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.BATTERY_LIGHT_MEDIUM_COLOR),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.BATTERY_LIGHT_FULL_COLOR),
+ false, this, UserHandle.USER_ALL);
+ }
+
+ update();
+ }
+
+ @Override public void onChange(boolean selfChange) {
+ update();
+ }
+
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ Resources res = mContext.getResources();
+
+ // Battery light enabled
+ mLightEnabled = CMSettings.System.getInt(resolver,
+ CMSettings.System.BATTERY_LIGHT_ENABLED, 1) != 0;
+
+ // Low battery pulse
+ mLedPulseEnabled = CMSettings.System.getInt(resolver,
+ CMSettings.System.BATTERY_LIGHT_PULSE, 1) != 0;
+
+ // Light colors
+ mBatteryLowARGB = CMSettings.System.getInt(resolver,
+ CMSettings.System.BATTERY_LIGHT_LOW_COLOR, res.getInteger(
+ com.android.internal.R.integer.config_notificationsBatteryLowARGB));
+ mBatteryMediumARGB = CMSettings.System.getInt(resolver,
+ CMSettings.System.BATTERY_LIGHT_MEDIUM_COLOR, res.getInteger(
+ com.android.internal.R.integer.config_notificationsBatteryMediumARGB));
+ mBatteryFullARGB = CMSettings.System.getInt(resolver,
+ CMSettings.System.BATTERY_LIGHT_FULL_COLOR, res.getInteger(
+ com.android.internal.R.integer.config_notificationsBatteryFullARGB));
+
+ // Notification LED brightness
+ if (mAdjustableNotificationLedBrightness) {
+ mNotificationLedBrightnessLevel = CMSettings.System.getInt(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
+ LIGHT_BRIGHTNESS_MAXIMUM);
+ }
+
+ // Multiple LEDs enabled
+ if (mMultipleNotificationLeds) {
+ mMultipleLedsEnabled = CMSettings.System.getInt(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_MULTIPLE_LEDS_ENABLE,
+ mMultipleNotificationLeds ? 1 : 0) != 0;
+ }
+
+ updateLedPulse();
+ }
}
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index d5c4a41..5a76227 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,16 +21,14 @@ package com.android.server;
import android.Manifest;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothHeadset;
import android.bluetooth.IBluetoothManager;
import android.bluetooth.IBluetoothManagerCallback;
-import android.bluetooth.IBluetoothProfileServiceConnection;
import android.bluetooth.IBluetoothStateChangeCallback;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -63,7 +64,7 @@ import java.util.Map;
class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
@@ -80,8 +81,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int ERROR_RESTART_TIME_MS = 3000;
//Maximum msec to delay MESSAGE_USER_SWITCHED
private static final int USER_SWITCHED_TIME_MS = 200;
- // Delay for the addProxy function in msec
- private static final int ADD_PROXY_DELAY_MS = 100;
private static final int MESSAGE_ENABLE = 1;
private static final int MESSAGE_DISABLE = 2;
@@ -98,8 +97,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
private static final int MESSAGE_USER_SWITCHED = 300;
- private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
- private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
private static final int MAX_SAVE_RETRIES=3;
private static final int MAX_ERROR_RESTART_RETRIES=6;
@@ -151,11 +148,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private final BluetoothHandler mHandler;
private int mErrorRecoveryRetryCounter;
private final int mSystemUiUid;
-
- // Save a ProfileServiceConnections object for each of the bound
- // bluetooth profile services
- private final Map <Integer, ProfileServiceConnections> mProfileServices =
- new HashMap <Integer, ProfileServiceConnections>();
+ private boolean mIntentPending = false;
private void registerForAirplaneMode(IntentFilter filter) {
final ContentResolver resolver = mContext.getContentResolver();
@@ -619,7 +612,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
return true;
}
- public boolean enable() {
+ public boolean enable(String callingPackage) {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
Log.w(TAG,"enable(): not allowed for non-active and non system user");
@@ -633,6 +626,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
" mBinding = " + mBinding);
}
+ AppOpsManager appOps = (AppOpsManager) mContext
+ .getSystemService(Context.APP_OPS_SERVICE);
+ int callingUid = Binder.getCallingUid();
+ if (appOps.noteOp(AppOpsManager.OP_BLUETOOTH_CHANGE, callingUid,
+ callingPackage) != AppOpsManager.MODE_ALLOWED)
+ return false;
+
synchronized(mReceiver) {
mQuietEnableExternal = false;
mEnableExternal = true;
@@ -707,69 +707,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
return mBluetoothGatt;
}
- @Override
- public boolean bindBluetoothProfileService(int bluetoothProfile,
- IBluetoothProfileServiceConnection proxy) {
- if (!mEnable) {
- if (DBG) {
- Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
- ", while Bluetooth was disabled");
- }
- return false;
- }
- synchronized (mProfileServices) {
- ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
- if (psc == null) {
- if (DBG) {
- Log.d(TAG, "Creating new ProfileServiceConnections object for"
- + " profile: " + bluetoothProfile);
- }
-
- if (bluetoothProfile != BluetoothProfile.HEADSET) return false;
-
- Intent intent = new Intent(IBluetoothHeadset.class.getName());
- psc = new ProfileServiceConnections(intent);
- if (!psc.bindService()) return false;
-
- mProfileServices.put(new Integer(bluetoothProfile), psc);
- }
- }
-
- // Introducing a delay to give the client app time to prepare
- Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
- addProxyMsg.arg1 = bluetoothProfile;
- addProxyMsg.obj = proxy;
- mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
- return true;
- }
-
- @Override
- public void unbindBluetoothProfileService(int bluetoothProfile,
- IBluetoothProfileServiceConnection proxy) {
- synchronized (mProfileServices) {
- ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
- if (psc == null) {
- return;
- }
- psc.removeProxy(proxy);
- }
- }
-
- private void unbindAllBluetoothProfileServices() {
- synchronized (mProfileServices) {
- for (Integer i : mProfileServices.keySet()) {
- ProfileServiceConnections psc = mProfileServices.get(i);
- try {
- mContext.unbindService(psc);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
- }
- psc.removeAllProxies();
- }
- mProfileServices.clear();
- }
- }
-
/**
* Send enable message and set adapter name and address. Called when the boot phase becomes
* PHASE_SYSTEM_SERVICES_READY.
@@ -795,148 +732,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0));
}
- /**
- * This class manages the clients connected to a given ProfileService
- * and maintains the connection with that service.
- */
- final private class ProfileServiceConnections implements ServiceConnection,
- IBinder.DeathRecipient {
- final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
- new RemoteCallbackList <IBluetoothProfileServiceConnection>();
- IBinder mService;
- ComponentName mClassName;
- Intent mIntent;
- boolean mInvokingProxyCallbacks = false;
-
- ProfileServiceConnections(Intent intent) {
- mService = null;
- mClassName = null;
- mIntent = intent;
- }
-
- private boolean bindService() {
- if (mIntent != null && mService == null &&
- doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
- Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
- msg.obj = this;
- mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
- return true;
- }
- Log.w(TAG, "Unable to bind with intent: " + mIntent);
- return false;
- }
-
- private void addProxy(IBluetoothProfileServiceConnection proxy) {
- mProxies.register(proxy);
- if (mService != null) {
- try{
- proxy.onServiceConnected(mClassName, mService);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to connect to proxy", e);
- }
- } else {
- if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
- Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
- msg.obj = this;
- mHandler.sendMessage(msg);
- }
- }
- }
-
- private void removeProxy(IBluetoothProfileServiceConnection proxy) {
- if (proxy != null) {
- if (mProxies.unregister(proxy)) {
- try {
- proxy.onServiceDisconnected(mClassName);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to disconnect proxy", e);
- }
- }
- } else {
- Log.w(TAG, "Trying to remove a null proxy");
- }
- }
-
- private void removeAllProxies() {
- onServiceDisconnected(mClassName);
- mProxies.kill();
- }
-
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- // remove timeout message
- mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
- mService = service;
- mClassName = className;
- try {
- mService.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to linkToDeath", e);
- }
-
- if (mInvokingProxyCallbacks) {
- Log.e(TAG, "Proxy callbacks already in progress.");
- return;
- }
- mInvokingProxyCallbacks = true;
-
- final int n = mProxies.beginBroadcast();
- try {
- for (int i = 0; i < n; i++) {
- try {
- mProxies.getBroadcastItem(i).onServiceConnected(className, service);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to connect to proxy", e);
- }
- }
- } finally {
- mProxies.finishBroadcast();
- mInvokingProxyCallbacks = false;
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (mService == null) return;
- mService.unlinkToDeath(this, 0);
- mService = null;
- mClassName = null;
-
- if (mInvokingProxyCallbacks) {
- Log.e(TAG, "Proxy callbacks already in progress.");
- return;
- }
- mInvokingProxyCallbacks = true;
-
- final int n = mProxies.beginBroadcast();
- try {
- for (int i = 0; i < n; i++) {
- try {
- mProxies.getBroadcastItem(i).onServiceDisconnected(className);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to disconnect from proxy", e);
- }
- }
- } finally {
- mProxies.finishBroadcast();
- mInvokingProxyCallbacks = false;
- }
- }
-
- @Override
- public void binderDied() {
- if (DBG) {
- Log.w(TAG, "Profile service for profile: " + mClassName
- + " died.");
- }
- onServiceDisconnected(mClassName);
- // Trigger rebind
- Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
- msg.obj = this;
- mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
- }
- }
-
private void sendBluetoothStateCallback(boolean isUp) {
try {
int n = mStateChangeCallbacks.beginBroadcast();
@@ -1258,28 +1053,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
break;
}
- case MESSAGE_ADD_PROXY_DELAYED:
- {
- ProfileServiceConnections psc = mProfileServices.get(
- new Integer(msg.arg1));
- if (psc == null) {
- break;
- }
- IBluetoothProfileServiceConnection proxy =
- (IBluetoothProfileServiceConnection) msg.obj;
- psc.addProxy(proxy);
- break;
- }
- case MESSAGE_BIND_PROFILE_SERVICE:
- {
- ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
- removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
- if (psc == null) {
- break;
- }
- psc.bindService();
- break;
- }
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
@@ -1483,20 +1256,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mState = BluetoothAdapter.STATE_TURNING_ON;
}
- waitForOnOff(true, false);
+ waitForMonitoredOnOff(true, false);
if (mState == BluetoothAdapter.STATE_TURNING_ON) {
bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
}
- unbindAllBluetoothProfileServices();
// disable
handleDisable();
// Pbap service need receive STATE_TURNING_OFF intent to close
bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
BluetoothAdapter.STATE_TURNING_OFF);
- waitForOnOff(false, true);
+ waitForMonitoredOnOff(false, true);
bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
BluetoothAdapter.STATE_OFF);
@@ -1666,7 +1438,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
unbindAndFinish();
sendBleStateChanged(prevState, newState);
// Don't broadcast as it has already been broadcast before
- isStandardBroadcast = false;
+ if(!mIntentPending) {
+ isStandardBroadcast = false;
+ } else {
+ mIntentPending = false;
+ }
}
} else if (!intermediate_off) {
@@ -1695,6 +1471,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
// Broadcast as STATE_OFF
newState = BluetoothAdapter.STATE_OFF;
sendBrEdrDownCallback();
+ if(!isBleAppPresent()){
+ isStandardBroadcast = false;
+ mIntentPending = true;
+ } else {
+ mIntentPending = false;
+ isStandardBroadcast = true;
+ }
}
} else if (newState == BluetoothAdapter.STATE_ON) {
boolean isUp = (newState==BluetoothAdapter.STATE_ON);
@@ -1711,15 +1494,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
sendBleStateChanged(prevState, newState);
}
+ if( newState == BluetoothAdapter.STATE_TURNING_ON
+ && prevState == BluetoothAdapter.STATE_BLE_ON) {
+ mEnable = true;
+ }
+
if (isStandardBroadcast) {
if (prevState == BluetoothAdapter.STATE_BLE_ON) {
// Show prevState of BLE_ON as OFF to standard users
prevState = BluetoothAdapter.STATE_OFF;
}
+ else if (prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
+ // show prevState to TURNING_OFF
+ prevState = BluetoothAdapter.STATE_TURNING_OFF;
+ }
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
}
}
@@ -1759,6 +1552,48 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
return false;
}
+ /**
+ * if on is true, wait for state become ON
+ * if off is true, wait for state become OFF
+ * if both on and off are false, wait for state not ON
+ */
+ private boolean waitForMonitoredOnOff(boolean on, boolean off) {
+ int i = 0;
+ while (i < 10) {
+ synchronized(mConnection) {
+ try {
+ if (mBluetooth == null) break;
+ if (on) {
+ if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
+ if (mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
+ bluetoothStateChangeHandler(BluetoothAdapter.STATE_BLE_TURNING_ON,
+ BluetoothAdapter.STATE_BLE_ON);
+ }
+ } else if (off) {
+ if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
+ if (mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
+ bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
+ BluetoothAdapter.STATE_BLE_ON);
+ }
+ } else {
+ if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getState()", e);
+ break;
+ }
+ }
+ if (on || off) {
+ SystemClock.sleep(800);
+ } else {
+ SystemClock.sleep(50);
+ }
+ i++;
+ }
+ Log.e(TAG,"waitForOnOff time out");
+ return false;
+ }
+
private void sendDisableMsg() {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 75f5c15..2a47460 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,6 +71,7 @@ import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.Uri;
+import android.net.wifi.WifiDevice;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileUtils;
@@ -132,6 +133,7 @@ import com.android.server.net.LockdownVpnTracker;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
+import cyanogenmod.providers.CMSettings;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -221,6 +223,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private INetworkPolicyManager mPolicyManager;
private String mCurrentTcpBufferSizes;
+ private int mCurrentTcpDelayedAckSegments;
+ private int mCurrentTcpUserCfg;
private static final int ENABLED = 1;
private static final int DISABLED = 0;
@@ -642,13 +646,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
// setup our unique device name
- if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
+ String hostname = CMSettings.Secure.getString(context.getContentResolver(),
+ CMSettings.Secure.DEVICE_HOSTNAME);
+ if (TextUtils.isEmpty(hostname) &&
+ TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
String id = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ANDROID_ID);
if (id != null && id.length() > 0) {
String name = new String("android-").concat(id);
SystemProperties.set("net.hostname", name);
}
+ } else {
+ SystemProperties.set("net.hostname", hostname);
}
// read our default dns server ip
@@ -1742,6 +1751,34 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private void updateTcpDelayedAck(NetworkAgentInfo nai) {
+ if (isDefaultNetwork(nai) == false) {
+ return;
+ }
+
+ int segments = nai.linkProperties.getTcpDelayedAckSegments();
+ int usercfg = nai.linkProperties.getTcpUserCfg();
+
+ if (segments != mCurrentTcpDelayedAckSegments) {
+ try {
+ FileUtils.stringToFile("/sys/kernel/ipv4/tcp_delack_seg",
+ String.valueOf(segments));
+ mCurrentTcpDelayedAckSegments = segments;
+ } catch (IOException e) {
+ // optional
+ }
+ }
+
+ if (usercfg != mCurrentTcpUserCfg) {
+ try {
+ FileUtils.stringToFile("/sys/kernel/ipv4/tcp_use_usercfg",
+ String.valueOf(usercfg));
+ mCurrentTcpUserCfg = usercfg;
+ } catch (IOException e) {
+ // optional
+ }
+ }
+ }
private void flushVmDnsCache() {
/*
* Tell the VMs to toss their DNS caches
@@ -2593,6 +2630,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ public List<WifiDevice> getTetherConnectedSta() {
+ if (isTetheringSupported()) {
+ return mTethering.getTetherConnectedSta();
+ } else {
+ return null;
+ }
+ }
+
// javadoc from interface
public int tether(String iface) {
ConnectivityManager.enforceTetherChangePermission(mContext);
@@ -3963,6 +4008,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// updateMtu(lp, null);
// }
updateTcpBufferSizes(networkAgent);
+ updateTcpDelayedAck(networkAgent);
// TODO: deprecate and remove mDefaultDns when we can do so safely. See http://b/18327075
// In L, we used it only when the network had Internet access but provided no DNS servers.
@@ -4287,6 +4333,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
+ updateTcpDelayedAck(newNetwork);
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
@@ -4520,7 +4567,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- if (unneeded(nai)) {
+ if (unneeded(nai) && nai != newNetwork) {
if (DBG) log("Reaping " + nai.name());
teardownUnneededNetwork(nai);
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index a057ac9..71650c3 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -796,6 +796,12 @@ public class DeviceIdleController extends SystemService
return isPowerSaveWhitelistExceptIdleAppInternal(name);
}
+ @Override public int getIdleStateDetailed() {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ return mState;
+ }
+
@Override public boolean isPowerSaveWhitelistApp(String name) {
return isPowerSaveWhitelistAppInternal(name);
}
@@ -1269,7 +1275,7 @@ public class DeviceIdleController extends SystemService
void scheduleReportActiveLocked(String activeReason, int activeUid) {
Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
- mState == STATE_IDLE ? 1 : 0, activeReason);
+ ((mState == STATE_IDLE) || (mState == STATE_IDLE_MAINTENANCE)) ? 1 : 0, activeReason);
mHandler.sendMessage(msg);
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 5b1f2f2..8bb158e 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -11,6 +11,10 @@ option java_package com.android.server
# It lets us count the total amount of time between charges and the discharge level
2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
+# dock battery
+2738 dock_battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
+2739 dock_battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3)
+
# ---------------------------
# PowerManagerService.java
@@ -34,7 +38,8 @@ option java_package com.android.server
2731 power_soft_sleep_requested (savedwaketimems|2)
#
-# Leave IDs through 2739 for more power logs (2730 used by battery_discharge above)
+# Leave IDs through 2739 for more power logs (2730 used by battery_discharge and
+# 2738-2739 used by dock battery above)
#
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6d07a57..6e7a750 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -36,6 +36,9 @@ import com.android.server.pm.UserManagerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.wm.WindowManagerService;
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -90,6 +93,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.text.style.SuggestionSpan;
@@ -139,6 +143,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import cyanogenmod.providers.CMSettings;
+
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
/**
* This class provides a system service that manages input methods.
*/
@@ -196,6 +205,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ processQSChangedLocked();
+ }
+ };
+
// All known input methods. mMethodMap also serves as the global
// lock for this class.
final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
@@ -482,6 +498,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this, userId);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this, userId);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.STATUS_BAR_IME_SWITCHER),
+ false, new ContentObserver(mHandler) {
+ public void onChange(boolean selfChange) {
+ updateFromSettingsLocked(true);
+ }
+ }, userId);
+
mRegistered = true;
}
@@ -938,6 +962,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}, filter);
LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl(mHandler));
+ QSUtils.registerObserverForQSChanges(mContext, mQSListener);
}
private void resetDefaultImeLocked(Context context) {
@@ -1090,8 +1115,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mStatusBar = statusBar;
statusBar.setIconVisibility("ime", false);
updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
- mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
- com.android.internal.R.bool.show_ongoing_ime_switcher);
if (mShowOngoingImeSwitcherForPhones) {
mWindowManagerService.setOnHardKeyboardStatusChangeListener(
mHardKeyboardListener);
@@ -1814,6 +1837,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mImeSwitcherNotification.build(), UserHandle.ALL);
mNotificationShown = true;
}
+ publishImeSelectorCustomTile(imi);
} else {
if (mNotificationShown && mNotificationManager != null) {
if (DEBUG) {
@@ -1823,6 +1847,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
com.android.internal.R.string.select_input_method, UserHandle.ALL);
mNotificationShown = false;
}
+ unpublishImeSelectorCustomTile();
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -1929,6 +1954,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// There is no longer an input method set, so stop any current one.
unbindCurrentMethodLocked(true, false);
}
+ // code to disable the CM Phone IME switcher with config_show_cmIMESwitcher set = false
+ try {
+ mShowOngoingImeSwitcherForPhones = CMSettings.System.getInt(mContext.getContentResolver(),
+ CMSettings.System.STATUS_BAR_IME_SWITCHER) == 1;
+ } catch (CMSettings.CMSettingNotFoundException e) {
+ mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
+ com.android.internal.R.bool.config_show_cmIMESwitcher);
+ }
// Here is not the perfect place to reset the switching controller. Ideally
// mSwitchingController and mSettings should be able to share the same state.
// TODO: Make sure that mSwitchingController and mSettings are sharing the
@@ -3544,6 +3577,69 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ private void publishImeSelectorCustomTile(InputMethodInfo imi) {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = new UserHandle(userId);
+ final int icon = QSUtils.getDynamicQSTileResIconId(mContext, userId,
+ QSConstants.DYNAMIC_TILE_IME_SELECTOR);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(mContext, userId,
+ QSConstants.DYNAMIC_TILE_IME_SELECTOR);
+ final Context resourceContext = QSUtils.getQSTileContext(mContext, userId);
+ CharSequence inputMethodName = null;
+ if (mCurrentSubtype != null) {
+ inputMethodName = mCurrentSubtype.getDisplayName(mContext,
+ imi.getPackageName(), imi.getServiceInfo().applicationInfo);
+ }
+ final CharSequence label = inputMethodName == null ? contentDesc : inputMethodName;
+
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(label.toString())
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setOnClickIntent(mImeSwitchPendingIntent)
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_IME_SELECTOR,
+ InputMethodManagerService.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishImeSelectorCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_IME_SELECTOR,
+ InputMethodManagerService.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void processQSChangedLocked() {
+ final int userId = UserHandle.myUserId();
+ final boolean isIMEVisible = ((mImeWindowVis & (InputMethodService.IME_ACTIVE)) != 0)
+ && (mWindowManagerService.isHardKeyboardAvailable()
+ || (mImeWindowVis & (InputMethodService.IME_VISIBLE)) != 0);
+ InputMethodInfo imi = null;
+ synchronized (mMethodMap) {
+ if (mCurMethodId != null) {
+ imi = mMethodMap.get(mCurMethodId);
+ }
+ }
+ if (shouldShowImeSwitcherLocked(isIMEVisible ? 1 : 0)) {
+ publishImeSelectorCustomTile(imi);
+ } else {
+ unpublishImeSelectorCustomTile();
+ }
+ }
+
// TODO: Cache the state for each user and reset when the cached user is removed.
private static class InputMethodFileManager {
private static final String SYSTEM_PATH = "system";
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 468ead0..ebe8759 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -64,6 +64,7 @@ import android.location.Geofence;
import android.location.IGpsGeofenceHardware;
import android.location.IGpsMeasurementsListener;
import android.location.IGpsNavigationMessageListener;
+import android.location.GeoFenceParams;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
import android.location.ILocationListener;
@@ -90,6 +91,28 @@ import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.location.FlpHardwareProvider;
+import com.android.server.location.FusedProxy;
+import com.android.server.location.GeocoderProxy;
+import com.android.server.location.GeofenceProxy;
+import com.android.server.location.GeofenceManager;
+import com.android.server.location.GeoFencerBase;
+import com.android.server.location.GeoFencerProxy;
+import com.android.server.location.GpsLocationProvider;
+import com.android.server.location.LocationBlacklist;
+import com.android.server.location.LocationFudger;
+import com.android.server.location.LocationProviderInterface;
+import com.android.server.location.LocationProviderProxy;
+import com.android.server.location.LocationRequestStatistics;
+import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
+import com.android.server.location.LocationRequestStatistics.PackageStatistics;
+import com.android.server.location.MockProvider;
+import com.android.server.location.PassiveProvider;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -154,6 +177,11 @@ public class LocationManagerService extends ILocationManager.Stub {
private LocationFudger mLocationFudger;
private GeofenceManager mGeofenceManager;
private PackageManager mPackageManager;
+ private String mComboNlpPackageName;
+ private String mComboNlpReadyMarker;
+ private String mComboNlpScreenMarker;
+ private String mGeoFencerPackageName;
+ private GeoFencerBase mGeoFencer;
private PowerManager mPowerManager;
private UserManager mUserManager;
private GeocoderProxy mGeocodeProvider;
@@ -509,6 +537,15 @@ public class LocationManagerService extends ILocationManager.Stub {
Slog.e(TAG, "no geocoder provider found");
}
+ mGeoFencerPackageName = resources.getString(
+ com.android.internal.R.string.config_geofenceProvider);
+ if (mGeoFencerPackageName != null &&
+ mPackageManager.resolveService(new Intent(mGeoFencerPackageName), 0) != null){
+ mGeoFencer = GeoFencerProxy.getGeoFencerProxy(mContext, mGeoFencerPackageName);
+ } else {
+ mGeoFencer = null;
+ }
+
// bind to fused hardware provider if supported
// in devices without support, requesting an instance of FlpHardwareProvider will raise an
// exception, so make sure we only do that when supported
@@ -562,6 +599,13 @@ public class LocationManagerService extends ILocationManager.Stub {
Slog.e(TAG, "Unable to bind ActivityRecognitionProxy.");
}
+ mComboNlpPackageName = resources.getString(
+ com.android.internal.R.string.config_comboNetworkLocationProvider);
+ if (mComboNlpPackageName != null) {
+ mComboNlpReadyMarker = mComboNlpPackageName + ".nlp:ready";
+ mComboNlpScreenMarker = mComboNlpPackageName + ".nlp:screen";
+ }
+
String[] testProviderStrings = resources.getStringArray(
com.android.internal.R.array.config_testLocationProviders);
for (String testProviderString : testProviderStrings) {
@@ -1614,9 +1658,11 @@ public class LocationManagerService extends ILocationManager.Stub {
checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
synchronized (mLock) {
- Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
+ Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
packageName, workSource, hideFromAppOps);
- requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
+ if (receiver != null) {
+ requestLocationUpdatesLocked(sanitizedRequest, receiver, pid, uid, packageName);
+ }
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -1675,7 +1721,9 @@ public class LocationManagerService extends ILocationManager.Stub {
// providers may use public location API's, need to clear identity
long identity = Binder.clearCallingIdentity();
try {
- removeUpdatesLocked(receiver);
+ if (receiver != null) {
+ removeUpdatesLocked(receiver);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1814,8 +1862,20 @@ public class LocationManagerService extends ILocationManager.Stub {
}
long identity = Binder.clearCallingIdentity();
try {
- mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
- uid, packageName);
+ if (mGeoFencer != null) {
+ long expiration;
+ if (sanitizedRequest.getExpireAt() == Long.MAX_VALUE) {
+ expiration = -1; // -1 means forever
+ } else {
+ expiration = sanitizedRequest.getExpireAt() - SystemClock.elapsedRealtime();
+ }
+ mGeoFencer.add(new GeoFenceParams(uid, geofence.getLatitude(),
+ geofence.getLongitude(), geofence.getRadius(),
+ expiration, intent, packageName));
+ } else {
+ mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
+ allowedResolutionLevel, uid, packageName);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1831,7 +1891,11 @@ public class LocationManagerService extends ILocationManager.Stub {
// geo-fence manager uses the public location API, need to clear identity
long identity = Binder.clearCallingIdentity();
try {
- mGeofenceManager.removeFence(geofence, intent);
+ if (mGeoFencer != null) {
+ mGeoFencer.remove(intent);
+ } else {
+ mGeofenceManager.removeFence(geofence, intent);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2332,6 +2396,70 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
return mMockProviders.containsKey(provider);
}
+
+ }
+
+ private Location screenLocationLocked(Location location, String provider) {
+ if (isMockProvider(LocationManager.NETWORK_PROVIDER)) {
+ return location;
+ }
+ LocationProviderProxy providerProxy =
+ (LocationProviderProxy)mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
+ if (mComboNlpPackageName == null || providerProxy == null ||
+ false == provider.equals(LocationManager.NETWORK_PROVIDER) ||
+ isMockProvider(LocationManager.NETWORK_PROVIDER)) {
+ return location;
+ }
+
+ String connectedNlpPackage = providerProxy.getConnectedPackageName();
+ if (connectedNlpPackage == null || !connectedNlpPackage.equals(mComboNlpPackageName)) {
+ return location;
+ }
+
+ Bundle extras = location.getExtras();
+ boolean isBeingScreened = false;
+ if (extras == null) {
+ extras = new Bundle();
+ }
+
+ if (!extras.containsKey(mComboNlpReadyMarker)) {
+ // see if Combo Nlp is a passive listener
+ ArrayList<UpdateRecord> records =
+ mRecordsByProvider.get(LocationManager.PASSIVE_PROVIDER);
+ if (records != null) {
+ for (UpdateRecord r : records) {
+ if (r.mReceiver.mPackageName.equals(mComboNlpPackageName)) {
+ if (!isBeingScreened) {
+ isBeingScreened = true;
+ extras.putBoolean(mComboNlpScreenMarker, true);
+ }
+ // send location to Combo Nlp for screening
+ if (!r.mReceiver.callLocationChangedLocked(location)) {
+ Slog.w(TAG, "RemoteException calling onLocationChanged on "
+ + r.mReceiver);
+ } else {
+ if (D) {
+ Log.d(TAG, "Sending location for screening");
+ }
+ }
+ }
+ }
+ }
+ if (isBeingScreened) {
+ return null;
+ }
+ if (D) {
+ Log.d(TAG, "Not screening locations");
+ }
+ } else {
+ if (D) {
+ Log.d(TAG, "This location is marked as ready for broadcast");
+ }
+ // clear the ready marker
+ extras.remove(mComboNlpReadyMarker);
+ }
+
+ return location;
}
private void handleLocationChanged(Location location, boolean passive) {
@@ -2350,6 +2478,10 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
if (isAllowedByCurrentUserSettingsLocked(provider)) {
if (!passive) {
+ location = screenLocationLocked(location, provider);
+ if (location == null) {
+ return;
+ }
// notify passive provider of the new location
mPassiveProvider.updateLocation(myLocation);
}
@@ -2655,6 +2787,10 @@ public class LocationManagerService extends ILocationManager.Stub {
mGeofenceManager.dump(pw);
+ if (mGeoFencer != null) {
+ mGeoFencer.dump(pw, "");
+ }
+
if (mEnabledProviders.size() > 0) {
pw.println(" Enabled Providers:");
for (String i : mEnabledProviders) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 45e7b5e..274adf8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -58,6 +58,11 @@ import com.android.server.LockSettingsStorage.CredentialHash;
import java.util.Arrays;
import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import cyanogenmod.providers.CMSettings;
+
/**
* Keeps the lock pattern/password data and related settings for each user.
* Used by LockPatternUtils. Needs to be a service because Settings app also needs
@@ -70,6 +75,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final String TAG = "LockSettingsService";
+ private static final String DEFAULT_PASSWORD = "default_password";
+
private final Context mContext;
private final LockSettingsStorage mStorage;
@@ -78,6 +85,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private LockPatternUtils mLockPatternUtils;
private boolean mFirstCallToVold;
private IGateKeeperService mGateKeeperService;
+ private static String mSavePassword = DEFAULT_PASSWORD;
private interface CredentialUtil {
void setCredential(String credential, String savedCredential, int userId)
@@ -371,6 +379,25 @@ public class LockSettingsService extends ILockSettings.Stub {
return mStorage.hasPattern(userId);
}
+ public void retainPassword(String password) {
+ if (LockPatternUtils.isDeviceEncryptionEnabled()) {
+ if (password != null)
+ mSavePassword = password;
+ else
+ mSavePassword = DEFAULT_PASSWORD;
+ }
+ }
+
+ public void sanitizePassword() {
+ if (LockPatternUtils.isDeviceEncryptionEnabled()) {
+ mSavePassword = DEFAULT_PASSWORD;
+ }
+ }
+
+ public String getPassword() {
+ return mSavePassword;
+ }
+
private void setKeystorePassword(String password, int userHandle) {
final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final KeyStore ks = KeyStore.getInstance();
@@ -425,6 +452,10 @@ public class LockSettingsService extends ILockSettings.Stub {
}
+ public byte getLockPatternSize(int userId) {
+ return mStorage.getLockPatternSize(userId);
+ }
+
@Override
public void setLockPattern(String pattern, String savedCredential, int userId)
throws RemoteException {
@@ -542,8 +573,10 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public byte[] toHash(String pattern, int userId) {
+ final byte lockPatternSize = getLockPatternSize(userId);
return LockPatternUtils.patternToHash(
- LockPatternUtils.stringToPattern(pattern));
+ LockPatternUtils.stringToPattern(pattern, lockPatternSize),
+ lockPatternSize);
}
@Override
@@ -557,6 +590,8 @@ public class LockSettingsService extends ILockSettings.Stub {
&& shouldReEnrollBaseZero) {
setLockPattern(pattern, patternToVerify, userId);
}
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK)
+ retainPassword(pattern);
return response;
@@ -565,7 +600,10 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public VerifyCredentialResponse checkPassword(String password, int userId)
throws RemoteException {
- return doVerifyPassword(password, false, 0, userId);
+ VerifyCredentialResponse response = doVerifyPassword(password, false, 0, userId);
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK)
+ retainPassword(password);
+ return response;
}
@Override
@@ -777,7 +815,11 @@ public class LockSettingsService extends ILockSettings.Stub {
Secure.LOCK_PATTERN_ENABLED,
Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
Secure.LOCK_PATTERN_VISIBLE,
- Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
+ Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+ CMSettings.Secure.LOCK_PASS_TO_SECURITY_VIEW,
+ Secure.LOCK_PATTERN_SIZE,
+ Secure.LOCK_DOTS_VISIBLE,
+ Secure.LOCK_SHOW_ERROR_PATH,
};
// Reading these settings needs the contacts permission
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index de48e71..1b42dfe 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.os.RemoteException;
+import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
import android.content.ContentValues;
@@ -29,6 +31,7 @@ import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.widget.LockPatternUtils;
import java.io.File;
import java.io.IOException;
@@ -328,6 +331,7 @@ class LockSettingsStorage {
mStoredCredentialType = hash == null
? CredentialHash.TYPE_NONE
: CredentialHash.TYPE_PATTERN;
+
writeFile(getLockPatternFilename(userId), hash);
clearPasswordHash(userId);
}
@@ -348,9 +352,22 @@ class LockSettingsStorage {
writeFile(getLockPasswordFilename(userId), null);
}
+ public byte getLockPatternSize(int userId) {
+ long size = Long.valueOf(readKeyValue(Settings.Secure.LOCK_PATTERN_SIZE, "-1", userId));
+ if (size > 0 && size < 128) {
+ return (byte) size;
+ }
+ return LockPatternUtils.PATTERN_SIZE_DEFAULT;
+ }
+
+ public boolean isDefaultSize(int userId) {
+ return getLockPatternSize(userId) == LockPatternUtils.PATTERN_SIZE_DEFAULT;
+ }
+
@VisibleForTesting
String getLockPatternFilename(int userId) {
- return getLockCredentialFilePathForUser(userId, LOCK_PATTERN_FILE);
+ String baseFileName = LOCK_PATTERN_FILE;
+ return getLockCredentialFilePathForUser(userId, baseFileName);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/LockSettingsStrongAuth.java b/services/core/java/com/android/server/LockSettingsStrongAuth.java
index c023f4a..5add4c0 100644
--- a/services/core/java/com/android/server/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/LockSettingsStrongAuth.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.os.Looper;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
@@ -47,6 +48,12 @@ public class LockSettingsStrongAuth {
private final ArrayList<IStrongAuthTracker> mStrongAuthTrackers = new ArrayList<>();
private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
+ private final Handler mHandler;
+
+ public LockSettingsStrongAuth() {
+ mHandler = new Handler(Looper.getMainLooper(), mHandlerCallback);
+ }
+
private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
@@ -145,9 +152,9 @@ public class LockSettingsStrongAuth {
requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
}
- private final Handler mHandler = new Handler() {
+ private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
- public void handleMessage(Message msg) {
+ public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_TRACKER:
handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj);
@@ -162,6 +169,7 @@ public class LockSettingsStrongAuth {
handleRemoveUser(msg.arg1);
break;
}
+ return true;
}
};
}
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index 1653db9..23556c0 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -34,6 +34,9 @@ import java.io.IOException;
public class MasterClearReceiver extends BroadcastReceiver {
private static final String TAG = "MasterClear";
+ /* {@hide} */
+ public static final String EXTRA_WIPE_MEDIA = "wipe_media";
+
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
@@ -54,7 +57,8 @@ public class MasterClearReceiver extends BroadcastReceiver {
@Override
public void run() {
try {
- RecoverySystem.rebootWipeUserData(context, shutdown, reason);
+ boolean wipeMedia = intent.getBooleanExtra(EXTRA_WIPE_MEDIA, false);
+ RecoverySystem.rebootWipeUserData(context, shutdown, reason, wipeMedia);
Log.wtf(TAG, "Still running after master clear?!");
} catch (IOException e) {
Slog.e(TAG, "Can't perform master clear/factory reset", e);
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 5e67414..4847de3 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1093,8 +1093,10 @@ class MountService extends IMountService.Stub
final long destroy = Long.parseLong(cooked[6]);
final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
- dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
- + " " + ident + " " + create + " " + run + " " + destroy);
+ if (dropBox != null) {
+ dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
+ + " " + ident + " " + create + " " + run + " " + destroy);
+ }
final VolumeRecord rec = findRecordForPath(path);
if (rec != null) {
@@ -1111,8 +1113,10 @@ class MountService extends IMountService.Stub
final long time = Long.parseLong(cooked[3]);
final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
- dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path)
- + " " + bytes + " " + time);
+ if (dropBox != null) {
+ dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path)
+ + " " + bytes + " " + time);
+ }
final VolumeRecord rec = findRecordForPath(path);
if (rec != null) {
@@ -2400,7 +2404,7 @@ class MountService extends IMountService.Stub
}
}
- public int encryptStorage(int type, String password) {
+ private int encryptStorageExtended(int type, String password, boolean wipe) {
if (TextUtils.isEmpty(password) && type != StorageManager.CRYPT_TYPE_DEFAULT) {
throw new IllegalArgumentException("password cannot be empty");
}
@@ -2430,6 +2434,22 @@ class MountService extends IMountService.Stub
return 0;
}
+ /** Encrypt Storage given a password.
+ * @param type The password type.
+ * @param password The password to be used in encryption.
+ */
+ public int encryptStorage(int type, String password) {
+ return encryptStorageExtended(type, password, false);
+ }
+
+ /** Encrypt Storage given a password after wiping it.
+ * @param type The password type.
+ * @param password The password to be used in encryption.
+ */
+ public int encryptWipeStorage(int type, String password) {
+ return encryptStorageExtended(type, password, true);
+ }
+
/** Set the password for encrypting the master key.
* @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
* @param password The password to set.
@@ -2444,9 +2464,13 @@ class MountService extends IMountService.Stub
Slog.i(TAG, "changing encryption password...");
}
+ LockSettingsService lockSettings = new LockSettingsService(mContext);
+ String currentPassword = lockSettings.getPassword();
+
try {
NativeDaemonEvent event = mCryptConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type],
- new SensitiveArg(password));
+ new SensitiveArg(currentPassword), new SensitiveArg(password));
+ lockSettings.sanitizePassword();
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
// Encryption failed
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index ba9279c..fd42b0a 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -170,6 +170,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
public static final int InterfaceDnsServerInfo = 615;
public static final int RouteChange = 616;
public static final int StrictCleartext = 617;
+ public static final int InterfaceMessage = 618;
}
static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
@@ -520,6 +521,21 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
/**
+ * Notify our observers of a change in the data activity state of the interface
+ */
+ private void notifyInterfaceMessage(String message) {
+ final int length = mObservers.beginBroadcast();
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceMessageRecevied(message);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
+ }
+ mObservers.finishBroadcast();
+ }
+
+ /**
* Prepare native daemon once connected, enabling modules and pushing any
* existing in-memory rules.
*/
@@ -789,6 +805,22 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
throw new IllegalStateException(errorMessage);
// break;
+ case NetdResponseCode.InterfaceMessage:
+ /*
+ * An message arrived in network interface.
+ * Format: "NNN IfaceMessage <3>AP-STA-CONNECTED 00:08:22:64:9d:84
+ */
+ if (cooked.length < 3 || !cooked[1].equals("IfaceMessage")) {
+ throw new IllegalStateException(errorMessage);
+ }
+ Slog.d(TAG, "onEvent: "+ raw);
+ if(cooked[4] != null) {
+ notifyInterfaceMessage(cooked[3] + " " + cooked[4]);
+ } else {
+ notifyInterfaceMessage(cooked[3]);
+ }
+ return true;
+ // break;
case NetdResponseCode.InterfaceClassActivity:
/*
* An network interface class state changed (active/idle)
@@ -806,7 +838,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
timestampNanos = SystemClock.elapsedRealtimeNanos();
}
boolean isActive = cooked[2].equals("active");
- notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
+ notifyInterfaceClassActivity(cooked[3] == null ? 0 : Integer.parseInt(cooked[3]),
isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
: DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false);
return true;
diff --git a/services/core/java/com/android/server/PermissionDialog.java b/services/core/java/com/android/server/PermissionDialog.java
new file mode 100644
index 0000000..0f337b8
--- /dev/null
+++ b/services/core/java/com/android/server/PermissionDialog.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Message;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+public class PermissionDialog extends BasePermissionDialog {
+ private final static String TAG = "PermissionDialog";
+
+ private final AppOpsService mService;
+ private final String mPackageName;
+ private final int mCode;
+ private View mView;
+ private CheckBox mChoice;
+ private int mUid;
+ final CharSequence[] mOpLabels;
+ private Context mContext;
+
+ // Event 'what' codes
+ static final int ACTION_ALLOWED = 0x2;
+ static final int ACTION_IGNORED = 0x4;
+ static final int ACTION_IGNORED_TIMEOUT = 0x8;
+
+ // 15s timeout, then we automatically dismiss the permission
+ // dialog. Otherwise, it may cause watchdog timeout sometimes.
+ static final long DISMISS_TIMEOUT = 1000 * 15 * 1;
+
+ public PermissionDialog(Context context, AppOpsService service,
+ int code, int uid, String packageName) {
+ super(context);
+
+ mContext = context;
+ Resources res = context.getResources();
+
+ mService = service;
+ mCode = code;
+ mPackageName = packageName;
+ mUid = uid;
+ mOpLabels = res.getTextArray(
+ com.android.internal.R.array.app_ops_labels);
+
+ setCancelable(false);
+
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ res.getString(com.android.internal.R.string.allow), mHandler.obtainMessage(ACTION_ALLOWED));
+
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ res.getString(com.android.internal.R.string.deny), mHandler.obtainMessage(ACTION_IGNORED));
+
+ setTitle(res.getString(com.android.internal.R.string.privacy_guard_dialog_title));
+ WindowManager.LayoutParams attrs = getWindow().getAttributes();
+ attrs.setTitle("Permission info: " + getAppName(mPackageName));
+ attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
+ | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ getWindow().setAttributes(attrs);
+
+ mView = getLayoutInflater().inflate(
+ com.android.internal.R.layout.permission_confirmation_dialog,
+ null);
+ TextView tv = (TextView) mView.findViewById(
+ com.android.internal.R.id.permission_text);
+ mChoice = (CheckBox) mView.findViewById(
+ com.android.internal.R.id.permission_remember_choice_checkbox);
+ String name = getAppName(mPackageName);
+ if(name == null)
+ name = mPackageName;
+ tv.setText(mContext.getString(com.android.internal.R.string.privacy_guard_dialog_summary,
+ name, mOpLabels[mCode]));
+ setView(mView);
+
+ // After the timeout, pretend the user clicked the quit button
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT), DISMISS_TIMEOUT);
+ }
+
+ private String getAppName(String packageName) {
+ ApplicationInfo appInfo = null;
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ appInfo = pm.getApplicationInfo(packageName,
+ PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (final NameNotFoundException e) {
+ return null;
+ }
+ if(appInfo != null) {
+ return (String)pm.getApplicationLabel(appInfo);
+ }
+ return null;
+ }
+
+ private final Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ int mode;
+ boolean remember = mChoice.isChecked();
+ switch(msg.what) {
+ case ACTION_ALLOWED:
+ mode = AppOpsManager.MODE_ALLOWED;
+ break;
+ case ACTION_IGNORED:
+ mode = AppOpsManager.MODE_IGNORED;
+ break;
+ default:
+ mode = AppOpsManager.MODE_IGNORED;
+ remember = false;
+ }
+ mService.notifyOperation(mCode, mUid, mPackageName, mode,
+ remember);
+ dismiss();
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/PermissionDialogReqQueue.java b/services/core/java/com/android/server/PermissionDialogReqQueue.java
new file mode 100644
index 0000000..ee94427
--- /dev/null
+++ b/services/core/java/com/android/server/PermissionDialogReqQueue.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PermissionDialogReqQueue {
+ public PermissionDialog getDialog() {
+ return mDialog;
+ }
+
+ public void setDialog(PermissionDialog mDialog) {
+ this.mDialog = mDialog;
+ }
+
+ public final static class PermissionDialogReq {
+ public void set(int res) {
+ synchronized (this) {
+ mHasResult = true;
+ mResult = res;
+ notifyAll();
+ }
+ }
+
+ public int get() {
+ synchronized (this) {
+ while (!mHasResult) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ return mResult;
+ }
+
+ boolean mHasResult = false;
+ int mResult;
+ }
+
+ private PermissionDialog mDialog;
+ private List<PermissionDialogReq> resultList;
+
+ public PermissionDialogReqQueue() {
+ mDialog = null;
+ resultList = new ArrayList<PermissionDialogReq>();
+ }
+
+ public void register(PermissionDialogReq res) {
+ synchronized (this) {
+ resultList.add(res);
+ }
+ }
+
+ public void notifyAll(int mode) {
+ synchronized (this) {
+ while (resultList.size() != 0) {
+ PermissionDialogReq res = resultList.get(0);
+ res.set(mode);
+ resultList.remove(0);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index cd61347..2d94370 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -18,6 +18,7 @@ package com.android.server;
import android.app.ActivityManager;
import android.content.pm.FeatureInfo;
+import android.content.pm.Signature;
import android.os.*;
import android.os.Process;
import android.util.ArrayMap;
@@ -99,6 +100,9 @@ public class SystemConfig {
// URL-handling state upon factory reset.
final ArraySet<String> mLinkedApps = new ArraySet<>();
+ final ArrayMap<Signature, ArraySet<String>> mSignatureAllowances
+ = new ArrayMap<Signature, ArraySet<String>>();
+
public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
@@ -144,6 +148,10 @@ public class SystemConfig {
return mLinkedApps;
}
+ public ArrayMap<Signature, ArraySet<String>> getSignatureAllowances() {
+ return mSignatureAllowances;
+ }
+
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
@@ -290,6 +298,43 @@ public class SystemConfig {
perms.add(perm);
XmlUtils.skipCurrentTag(parser);
+ } else if ("allow-permission".equals(name)) {
+ String perm = parser.getAttributeValue(null, "name");
+ if (perm == null) {
+ Slog.w(TAG,
+ "<allow-permission> without name at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String signature = parser.getAttributeValue(null, "signature");
+ if (signature == null) {
+ Slog.w(TAG,
+ "<allow-permission> without signature at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ Signature sig = null;
+ try {
+ sig = new Signature(signature);
+ } catch (IllegalArgumentException e) {
+ // sig will be null so we will log it below
+ }
+ if (sig != null) {
+ ArraySet<String> perms = mSignatureAllowances.get(sig);
+ if (perms == null) {
+ perms = new ArraySet<String>();
+ mSignatureAllowances.put(sig, perms);
+ }
+ perms.add(perm);
+ } else {
+ Slog.w(TAG,
+ "<allow-permission> with bad signature at "
+ + parser.getPositionDescription());
+ }
+ XmlUtils.skipCurrentTag(parser);
+
} else if ("library".equals(name) && !onlyFeatures) {
String lname = parser.getAttributeValue(null, "name");
String lfile = parser.getAttributeValue(null, "file");
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 19a4851..71ff6e9 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -159,7 +159,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private String[] mDataConnectionApn;
- private ArrayList<String> mConnectedApns;
+ private ArrayList<String>[] mConnectedApns;
private LinkProperties[] mDataConnectionLinkProperties;
@@ -292,11 +292,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mContext = context;
mBatteryStats = BatteryStatsService.getService();
- mConnectedApns = new ArrayList<String>();
int numPhones = TelephonyManager.getDefault().getPhoneCount();
if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones);
mNumPhones = numPhones;
+ mConnectedApns = new ArrayList[numPhones];
mCallState = new int[numPhones];
mDataActivity = new int[numPhones];
mDataConnectionState = new int[numPhones];
@@ -314,6 +314,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
mCellInfo = new ArrayList<List<CellInfo>>();
for (int i = 0; i < numPhones; i++) {
+ mConnectedApns[i] = new ArrayList<String>();
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
mDataConnectionState[i] = TelephonyManager.DATA_UNKNOWN;
@@ -336,7 +337,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
location.fillInNotifierBundle(mCellLocation[i]);
}
}
- mConnectedApns = new ArrayList<String>();
mAppOps = mContext.getSystemService(AppOpsManager.class);
}
@@ -1057,18 +1057,21 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
+ if (VDBG) {
+ log(" mConnectedApns[" + phoneId + "]=" + mConnectedApns[phoneId].toString());
+ }
boolean modified = false;
if (state == TelephonyManager.DATA_CONNECTED) {
- if (!mConnectedApns.contains(apnType)) {
- mConnectedApns.add(apnType);
+ if (!mConnectedApns[phoneId].contains(apnType)) {
+ mConnectedApns[phoneId].add(apnType);
if (mDataConnectionState[phoneId] != state) {
mDataConnectionState[phoneId] = state;
modified = true;
}
}
} else {
- if (mConnectedApns.remove(apnType)) {
- if (mConnectedApns.isEmpty()) {
+ if (mConnectedApns[phoneId].remove(apnType)) {
+ if (mConnectedApns[phoneId].isEmpty()) {
mDataConnectionState[phoneId] = state;
modified = true;
} else {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 772a15c..22529a3 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -42,6 +42,8 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Date;
+import java.text.SimpleDateFormat;
/** This class calls its monitor every minute. Killing this process if they don't return **/
public class Watchdog extends Thread {
@@ -80,6 +82,7 @@ public class Watchdog extends Thread {
int mPhonePid;
IActivityController mController;
boolean mAllowRestart = true;
+ SimpleDateFormat mTraceDateFormat = new SimpleDateFormat("dd_MMM_HH_mm_ss.SSS");
/**
* Used for checking status of handle threads and scheduling monitor callbacks.
@@ -428,9 +431,22 @@ public class Watchdog extends Thread {
dumpKernelStackTraces();
}
- // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log
- doSysRq('w');
- doSysRq('l');
+ String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
+ String traceFileNameAmendment = "_SystemServer_WDT" + mTraceDateFormat.format(new Date());
+
+ if (tracesPath != null && tracesPath.length() != 0) {
+ File traceRenameFile = new File(tracesPath);
+ String newTracesPath;
+ int lpos = tracesPath.lastIndexOf (".");
+ if (-1 != lpos)
+ newTracesPath = tracesPath.substring (0, lpos) + traceFileNameAmendment + tracesPath.substring (lpos);
+ else
+ newTracesPath = tracesPath + traceFileNameAmendment;
+ traceRenameFile.renameTo(new File(newTracesPath));
+ tracesPath = newTracesPath;
+ }
+
+ final File newFd = new File(tracesPath);
// Try to add the error to the dropbox, but assuming that the ActivityManager
// itself may be deadlocked. (which has happened, causing this statement to
@@ -439,7 +455,7 @@ public class Watchdog extends Thread {
public void run() {
mActivity.addErrorToDropBox(
"watchdog", null, "system_server", null, null,
- subject, null, stack, null);
+ subject, null, newFd, null);
}
};
dropboxThread.start();
@@ -447,6 +463,24 @@ public class Watchdog extends Thread {
dropboxThread.join(2000); // wait up to 2 seconds for it to return.
} catch (InterruptedException ignored) {}
+ // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log
+ Slog.e(TAG, "Triggering SysRq for system_server watchdog");
+ doSysRq('w');
+ doSysRq('l');
+
+ // At times, when user space watchdog traces don't give an indication on
+ // which component held a lock, because of which other threads are blocked,
+ // (thereby causing Watchdog), crash the device to analyze RAM dumps
+ boolean crashOnWatchdog = SystemProperties
+ .getBoolean("persist.sys.crashOnWatchdog", false);
+ if (crashOnWatchdog) {
+ // wait until the above blocked threads be dumped into kernel log
+ SystemClock.sleep(3000);
+
+ // now try to crash the target
+ doSysRq('c');
+ }
+
IActivityController controller;
synchronized (this) {
controller = mController;
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index e0e6070..3b52fce 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -22,6 +22,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
+import android.os.SystemProperties;
import android.os.UEventObserver;
import android.util.Slog;
import android.media.AudioManager;
@@ -66,6 +67,8 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
private static final String NAME_H2W = "h2w";
private static final String NAME_USB_AUDIO = "usb_audio";
+ private static final String NAME_EMU_AUDIO = "semu_audio";
+ private static final String NAME_SAMSUNG_USB_AUDIO = "dock";
private static final String NAME_HDMI_AUDIO = "hdmi_audio";
private static final String NAME_HDMI = "hdmi";
@@ -330,7 +333,8 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
FileReader file = new FileReader(uei.getSwitchStatePath());
int len = file.read(buffer, 0, 1024);
file.close();
- curState = Integer.valueOf((new String(buffer, 0, len)).trim());
+ curState = validateSwitchState(
+ Integer.valueOf((new String(buffer, 0, len)).trim()));
if (curState > 0) {
updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);
@@ -345,14 +349,23 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
}
// At any given time accessories could be inserted
- // one on the board, one on the dock and one on HDMI:
- // observe three UEVENTs
+ // one on the board, one on the dock, one on the
+ // samsung dock and one on HDMI:
+ // observe all UEVENTs that have valid switch supported
+ // by the Kernel
for (int i = 0; i < mUEventInfo.size(); ++i) {
UEventInfo uei = mUEventInfo.get(i);
startObserving("DEVPATH="+uei.getDevPath());
}
}
+ private int validateSwitchState(int state) {
+ // Some drivers, namely HTC headset ones, add additional bits to
+ // the switch state. As we only are able to deal with the states
+ // 0, 1 and 2, mask out all the other bits
+ return state & 0x3;
+ }
+
private List<UEventInfo> makeObservedUEventList() {
List<UEventInfo> retVal = new ArrayList<UEventInfo>();
UEventInfo uei;
@@ -375,6 +388,19 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
Slog.w(TAG, "This kernel does not have usb audio support");
}
+ // Monitor Motorola EMU audio jack
+ uei = new UEventInfo(NAME_EMU_AUDIO, BIT_USB_HEADSET_ANLG, 0, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ }
+
+ // Monitor Samsung USB audio
+ uei = new UEventInfo(NAME_SAMSUNG_USB_AUDIO, BIT_USB_HEADSET_DGTL,
+ BIT_USB_HEADSET_ANLG, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ }
+
// Monitor HDMI
//
// If the kernel has support for the "hdmi_audio" switch, use that. It will be
@@ -405,7 +431,14 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
try {
String devPath = event.get("DEVPATH");
String name = event.get("SWITCH_NAME");
- int state = Integer.parseInt(event.get("SWITCH_STATE"));
+ if (SystemProperties.getBoolean("tcmd.whisper", false) &&
+ (name.equals("CAR") || name.equals("DESK"))) {
+ // Motorola dock - ignore this event and don't change
+ // the audio routing just because we're docked.
+ // Let only the dock emu audio jack sensing do that.
+ return;
+ }
+ int state = validateSwitchState(Integer.parseInt(event.get("SWITCH_STATE")));
synchronized (mLock) {
updateStateLocked(devPath, name, state);
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 3c6de07..1e0cf0a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -528,6 +528,7 @@ public class AccountManagerService
@Override
public String getPassword(Account account) {
+ android.util.SeempLog.record(14);
int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getPassword: " + account
@@ -627,6 +628,7 @@ public class AccountManagerService
@Override
public String getUserData(Account account, String key) {
+ android.util.SeempLog.record(15);
final int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
String msg = String.format("getUserData( account: %s, key: %s, callerUid: %s, pid: %s",
@@ -1199,6 +1201,7 @@ public class AccountManagerService
@Override
public void removeAccount(IAccountManagerResponse response, Account account,
boolean expectActivityLaunch) {
+ android.util.SeempLog.record(17);
removeAccountAsUser(
response,
account,
@@ -1587,6 +1590,7 @@ public class AccountManagerService
@Override
public void setPassword(Account account, String password) {
+ android.util.SeempLog.record(18);
final int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "setAuthToken: " + account
@@ -1651,6 +1655,7 @@ public class AccountManagerService
@Override
public void clearPassword(Account account) {
+ android.util.SeempLog.record(19);
final int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "clearPassword: " + account
@@ -1677,6 +1682,7 @@ public class AccountManagerService
@Override
public void setUserData(Account account, String key, String value) {
+ android.util.SeempLog.record(20);
final int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "setUserData: " + account
@@ -2116,6 +2122,7 @@ public class AccountManagerService
public void addAccount(final IAccountManagerResponse response, final String accountType,
final String authTokenType, final String[] requiredFeatures,
final boolean expectActivityLaunch, final Bundle optionsIn) {
+ android.util.SeempLog.record(16);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccount: accountType " + accountType
+ ", response " + response
@@ -2369,6 +2376,7 @@ public class AccountManagerService
@Override
public void editProperties(IAccountManagerResponse response, final String accountType,
final boolean expectActivityLaunch) {
+ android.util.SeempLog.record(21);
final int callingUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "editProperties: accountType " + accountType
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 970f1b5..db3d474 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -121,6 +121,10 @@ public final class ActiveServices {
// at the same time.
final int mMaxStartingBackground;
+ // Flag to reschedule the services during app launch. Disable by default.
+ private static final boolean SERVICE_RESCHEDULE
+ = SystemProperties.getBoolean("ro.am.reschedule_service", false);
+
final SparseArray<ServiceMap> mServiceMap = new SparseArray<>();
/**
@@ -1229,6 +1233,14 @@ public final class ActiveServices {
r.pendingStarts.add(0, si);
long dur = SystemClock.uptimeMillis() - si.deliveredTime;
dur *= 2;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG,"Can add more delay !!!"
+ +" si.deliveredTime "+si.deliveredTime
+ +" dur "+dur
+ +" si.deliveryCount "+si.deliveryCount
+ +" si.doneExecutingCount "+si.doneExecutingCount
+ +" allowCancel "+allowCancel);
+ }
if (minDuration < dur) minDuration = dur;
if (resetTime < dur) resetTime = dur;
} else {
@@ -1241,6 +1253,13 @@ public final class ActiveServices {
}
r.totalRestartCount++;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration
+ +" resetTime "+resetTime+" now "+now
+ +" r.restartDelay "+r.restartDelay
+ +" r.restartTime+resetTime "+(r.restartTime+resetTime)
+ +" allowCancel "+allowCancel);
+ }
if (r.restartDelay == 0) {
r.restartCount++;
r.restartDelay = minDuration;
@@ -1262,6 +1281,14 @@ public final class ActiveServices {
}
r.nextRestartTime = now + r.restartDelay;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration
+ +" resetTime "+resetTime+" now "+now
+ +" r.restartDelay "+r.restartDelay
+ +" r.restartTime+resetTime "+(r.restartTime+resetTime)
+ +" r.nextRestartTime "+r.nextRestartTime
+ +" allowCancel "+allowCancel);
+ }
// Make sure that we don't end up restarting a bunch of services
// all at the same time.
@@ -1304,6 +1331,15 @@ public final class ActiveServices {
r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Slog.w(TAG, "Scheduling restart of crashed service "
+ r.shortName + " in " + r.restartDelay + "ms");
+
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ for (int i=mRestartingServices.size()-1; i>=0; i--) {
+ ServiceRecord r2 = mRestartingServices.get(i);
+ Slog.w(TAG,"Restarting list - i "+i+" r2.nextRestartTime "
+ +r2.nextRestartTime+" r2.name "+r2.name);
+ }
+ }
+
EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
r.userId, r.shortName, r.restartDelay);
@@ -1324,7 +1360,31 @@ public final class ActiveServices {
return;
}
try {
- bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
+ if(SERVICE_RESCHEDULE == true) {
+ boolean shouldDelay = false;
+ ActivityRecord top_rc = null;
+ ActivityStack stack = mAm.getFocusedStack();
+ if(stack != null) {
+ top_rc = stack.topRunningActivityLocked(null);
+ }
+ if(top_rc != null) {
+ if(!top_rc.nowVisible && !r.shortName.contains(top_rc.packageName)) {
+ shouldDelay = true;
+ }
+ }
+ if(!shouldDelay) {
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
+ } else {
+ if (DEBUG_DELAYED_SERVICE) {
+ Slog.v(TAG, "Reschedule service restart due to app launch"
+ +" r.shortName "+r.shortName+" r.app = "+r.app);
+ }
+ r.resetRestartCounter();
+ scheduleServiceRestartLocked(r, true);
+ }
+ } else {
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
+ }
} catch (TransactionTooLargeException e) {
// Ignore, it's been logged and nothing upstack cares.
}
@@ -1378,7 +1438,7 @@ public final class ActiveServices {
return null;
}
- if (!whileRestarting && r.restartDelay > 0) {
+ if (!whileRestarting && r.restartDelay > 0 && mRestartingServices.contains(r)) {
// If waiting for a restart, then do nothing.
return null;
}
@@ -1547,6 +1607,11 @@ public final class ActiveServices {
if (newService) {
app.services.remove(r);
r.app = null;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG, " Failed to create Service !!!! ."
+ +"This will introduce huge delay... "
+ +r.shortName + " in " + r.restartDelay + "ms");
+ }
}
// Retry.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ba916ad..1014395 100644..100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2006-2008 The Android Open Source Project
- *
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
+ * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
* 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
@@ -52,6 +54,7 @@ import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
+import android.content.res.ThemeConfig;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
@@ -72,6 +75,7 @@ import android.util.DebugUtils;
import android.util.SparseIntArray;
import android.view.Display;
+import android.view.InflateException;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.AssistUtils;
@@ -178,6 +182,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.ThemeConfig;
import android.net.Proxy;
import android.net.ProxyInfo;
import android.net.Uri;
@@ -259,6 +264,10 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+
+import org.cyanogenmod.internal.util.ThemeUtils;
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -292,6 +301,11 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
private static final String TAG_VISIBLE_BEHIND = TAG + POSTFIX_VISIBLE_BEHIND;
+ private static final String ACTION_POWER_OFF_ALARM =
+ "org.codeaurora.alarm.action.POWER_OFF_ALARM";
+
+ private static final String POWER_OFF_ALARM = "powerOffAlarm";
+
/** Control over CPU and battery monitoring */
// write battery stats every 30 minutes.
static final long BATTERY_STATS_TIME = 30 * 60 * 1000;
@@ -398,6 +412,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// How many bytes to write into the dropbox log before truncating
static final int DROPBOX_MAX_SIZE = 256 * 1024;
+ static final String PROP_REFRESH_THEME = "sys.refresh_theme";
+
// Access modes for handleIncomingUser.
static final int ALLOW_NON_FULL = 0;
static final int ALLOW_NON_FULL_IN_PROFILE = 1;
@@ -411,6 +427,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// Necessary ApplicationInfo flags to mark an app as persistent
private static final int PERSISTENT_MASK =
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
+ private boolean mHomeKilled = false;
+ private String mHomeProcessName = null;
// Delay to disable app launch boost
@@ -501,6 +519,8 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
String mDeviceOwnerName;
+ SimpleDateFormat mTraceDateFormat = new SimpleDateFormat("dd_MMM_HH_mm_ss.SSS");
+
public class PendingAssistExtras extends Binder implements Runnable {
public final ActivityRecord activity;
public final Bundle extras;
@@ -1028,6 +1048,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean mLaunchWarningShown = false;
Context mContext;
+ Context mUiContext;
int mFactoryTest;
@@ -1240,6 +1261,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean foregroundActivities;
}
+ private Map<Integer, Object[]> mForegroundActivitiesList = new HashMap<Integer, Object[]>();
final RemoteCallbackList<IProcessObserver> mProcessObservers = new RemoteCallbackList<>();
ProcessChangeItem[] mActiveProcessChanges = new ProcessChangeItem[5];
@@ -1381,6 +1403,10 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
static final int APP_BOOST_DEACTIVATE_MSG = 58;
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
+ static final int POST_PRIVACY_NOTIFICATION_MSG = 60;
+ static final int CANCEL_PRIVACY_NOTIFICATION_MSG = 61;
+ static final int POST_COMPONENT_PROTECTED_MSG = 62;
+ static final int CANCEL_PROTECTED_APP_NOTIFICATION = 63;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1390,6 +1416,16 @@ public final class ActivityManagerService extends ActivityManagerNative
CompatModeDialog mCompatModeDialog;
long mLastMemUsageReportTime = 0;
+ // Min aging threshold in milliseconds to consider a B-service
+ int mMinBServiceAgingTime =
+ SystemProperties.getInt("ro.sys.fw.bservice_age", 5000);
+ // Threshold for B-services when in memory pressure
+ int mBServiceAppThreshold =
+ SystemProperties.getInt("ro.sys.fw.bservice_limit", 5);
+ // Enable B-service aging propagation on memory pressure.
+ boolean mEnableBServicePropagation =
+ SystemProperties.getBoolean("ro.sys.fw.bservice_enable", false);
+
/**
* Flag whether the current user is a "monkey", i.e. whether
* the UI is driven by a UI automation tool.
@@ -1443,7 +1479,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
if (mShowDialogs && !mSleeping && !mShuttingDown) {
- Dialog d = new AppErrorDialog(mContext,
+ Dialog d = new AppErrorDialog(getUiContext(),
ActivityManagerService.this, res, proc);
d.show();
proc.crashDialog = d;
@@ -1478,7 +1514,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mShowDialogs) {
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
- mContext, proc, (ActivityRecord)data.get("activity"),
+ getUiContext(), proc, (ActivityRecord)data.get("activity"),
msg.arg1 != 0);
d.show();
proc.anrDialog = d;
@@ -1504,7 +1540,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
AppErrorResult res = (AppErrorResult) data.get("result");
if (mShowDialogs && !mSleeping && !mShuttingDown) {
- Dialog d = new StrictModeViolationDialog(mContext,
+ Dialog d = new StrictModeViolationDialog(getUiContext(),
ActivityManagerService.this, res, proc);
d.show();
proc.crashDialog = d;
@@ -1518,7 +1554,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} break;
case SHOW_FACTORY_ERROR_MSG: {
Dialog d = new FactoryErrorDialog(
- mContext, msg.getData().getCharSequence("msg"));
+ getUiContext(), msg.getData().getCharSequence("msg"));
d.show();
ensureBootCompleted();
} break;
@@ -1529,7 +1565,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!app.waitedForDebugger) {
Dialog d = new AppWaitingForDebuggerDialog(
ActivityManagerService.this,
- mContext, app);
+ getUiContext(), app);
app.waitDialog = d;
app.waitedForDebugger = true;
d.show();
@@ -2076,6 +2112,152 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
} break;
+ case POST_PRIVACY_NOTIFICATION_MSG: {
+ INotificationManager inm = NotificationManager.getService();
+ if (inm == null) {
+ return;
+ }
+
+ ActivityRecord root = (ActivityRecord)msg.obj;
+ ProcessRecord process = root.app;
+ if (process == null) {
+ return;
+ }
+
+ try {
+ Context context = mContext.createPackageContext(process.info.packageName, 0);
+ String text = mContext.getString(R.string.privacy_guard_notification_detail,
+ context.getApplicationInfo().loadLabel(context.getPackageManager()));
+ String title = mContext.getString(R.string.privacy_guard_notification);
+
+ Intent infoIntent = new Intent(Settings.ACTION_APP_OPS_DETAILS_SETTINGS,
+ Uri.fromParts("package", root.packageName, null));
+
+ Notification notification = new Notification();
+ notification.icon = com.android.internal.R.drawable.stat_notify_privacy_guard;
+ notification.when = 0;
+ notification.flags = Notification.FLAG_ONGOING_EVENT;
+ notification.priority = Notification.PRIORITY_LOW;
+ notification.defaults = 0;
+ notification.sound = null;
+ notification.vibrate = null;
+ notification.setLatestEventInfo(mContext,
+ title, text,
+ PendingIntent.getActivityAsUser(mContext, 0, infoIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT, null,
+ new UserHandle(root.userId)));
+
+ try {
+ int[] outId = new int[1];
+ inm.enqueueNotificationWithTag("android", "android", null,
+ R.string.privacy_guard_notification,
+ notification, outId, root.userId);
+ } catch (RuntimeException e) {
+ Slog.w(ActivityManagerService.TAG,
+ "Error showing notification for privacy guard", e);
+ } catch (RemoteException e) {
+ }
+ } catch (NameNotFoundException e) {
+ Slog.w(TAG, "Unable to create context for privacy guard notification", e);
+ }
+ } break;
+ case CANCEL_PRIVACY_NOTIFICATION_MSG: {
+ INotificationManager inm = NotificationManager.getService();
+ if (inm == null) {
+ return;
+ }
+ try {
+ inm.cancelNotificationWithTag("android", null,
+ R.string.privacy_guard_notification, msg.arg1);
+ } catch (RuntimeException e) {
+ Slog.w(ActivityManagerService.TAG,
+ "Error canceling notification for service", e);
+ } catch (RemoteException e) {
+ }
+ } break;
+ case POST_COMPONENT_PROTECTED_MSG: {
+ INotificationManager inm = NotificationManager.getService();
+ if (inm == null) {
+ return;
+ }
+
+ Intent targetIntent = (Intent) msg.obj;
+ if (targetIntent == null) {
+ return;
+ }
+
+ int targetUserId = targetIntent.getIntExtra(
+ "com.android.settings.PROTECTED_APPS_USER_ID", mCurrentUserId);
+ // Resolve for labels and whatnot
+ ActivityInfo root = resolveActivityInfo(targetIntent, targetIntent.getFlags(),
+ targetUserId);
+
+ if (root == null) {
+ Slog.w(ActivityManagerService.TAG,
+ "No activity info found for given intent " + targetIntent.toString());
+ return;
+ }
+
+ try {
+ Intent protectedAppIntent = new Intent();
+ protectedAppIntent.setComponent(
+ new ComponentName("com.android.settings",
+ "com.android.settings.applications.ProtectedAppsActivity"));
+ protectedAppIntent.putExtra(
+ "com.android.settings.PROTECTED_APP_TARGET_INTENT",
+ targetIntent);
+ Context context = mContext.createPackageContext("com.android.settings", 0);
+ String title = mContext.getString(
+ com.android.internal.R.string
+ .notify_package_component_protected_title);
+ String text = mContext.getString(
+ com.android.internal.R.string
+ .notify_package_component_protected_text,
+ root.applicationInfo.loadLabel(mContext.getPackageManager()));
+ Notification notification = new Notification.Builder(context)
+ .setSmallIcon(com.android.internal.R.drawable.stat_notify_protected)
+ .setWhen(0)
+ .setTicker(title)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color
+ .system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setDefaults(Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_MAX)
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+ protectedAppIntent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+ new UserHandle(mCurrentUserId)))
+ .build();
+ try {
+ int[] outId = new int[1];
+ inm.enqueueNotificationWithTag("android", "android", null,
+ R.string.notify_package_component_protected_title,
+ notification, outId, mCurrentUserId);
+ } catch (RuntimeException e) {
+ Slog.w(ActivityManagerService.TAG,
+ "Error showing notification for protected app component", e);
+ } catch (RemoteException e) {
+ }
+ } catch (NameNotFoundException e) {
+ Slog.w(TAG, "Unable to create context for protected app notification", e);
+ }
+ } break;
+ case CANCEL_PROTECTED_APP_NOTIFICATION: {
+ INotificationManager inm = NotificationManager.getService();
+ if (inm == null) {
+ return;
+ }
+ try {
+ inm.cancelNotificationWithTag("android", null,
+ R.string.notify_package_component_protected_title, msg.arg1);
+ } catch (RuntimeException e) {
+ Slog.w(ActivityManagerService.TAG,
+ "Error canceling notification for service", e);
+ } catch (RemoteException e) {
+ }
+ } break;
}
}
};
@@ -2624,6 +2806,15 @@ public final class ActivityManagerService extends ActivityManagerNative
-1, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
+ private Context getUiContext() {
+ synchronized (this) {
+ if (mUiContext == null && mBooted) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+ }
+
/**
* Initialize the application bind args. These are passed to each
* process when the bindApplication() IPC is sent to the process. They're
@@ -3358,6 +3549,13 @@ public final class ActivityManagerService extends ActivityManagerNative
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
+ //Check if zygote should refresh its fonts
+ boolean refreshTheme = false;
+ if (SystemProperties.getBoolean(PROP_REFRESH_THEME, false)) {
+ SystemProperties.set(PROP_REFRESH_THEME, "false");
+ refreshTheme = true;
+ }
+
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
if (requiredAbi == null) {
requiredAbi = Build.SUPPORTED_ABIS[0];
@@ -3382,7 +3580,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
- app.info.dataDir, entryPointArgs);
+ app.info.dataDir, refreshTheme, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -3510,6 +3708,15 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
+ /**
+ * If system is power off alarm boot mode, we need to start alarm UI.
+ */
+ void startAlarmActivityLocked() {
+ Intent intent = new Intent(ACTION_POWER_OFF_ALARM);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ }
+
private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
ActivityInfo ai = null;
ComponentName comp = intent.getComponent();
@@ -3893,7 +4100,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (sourceRecord == null) {
throw new SecurityException("Called with bad activity token: " + resultTo);
}
- if (!sourceRecord.info.packageName.equals("android")) {
+ if (!sourceRecord.info.packageName.equals("android") &&
+ !sourceRecord.info.packageName.equals("org.cyanogenmod.resolver")) {
throw new SecurityException(
"Must be called from an activity that is declared in the android package");
}
@@ -4099,8 +4307,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (debug) {
Slog.v(TAG, "Next matching activity: found current " + r.packageName
+ "/" + r.info.name);
- Slog.v(TAG, "Next matching activity: next is " + aInfo.packageName
- + "/" + aInfo.name);
+ Slog.v(TAG, "Next matching activity: next is " + ((aInfo == null)
+ ? "null" : aInfo.packageName + "/" + aInfo.name));
}
break;
}
@@ -4184,6 +4392,9 @@ public final class ActivityManagerService extends ActivityManagerNative
callingUid = task.mCallingUid;
callingPackage = task.mCallingPackage;
intent = task.intent;
+ if (task.origActivity != null) {
+ intent.setComponent(task.origActivity);
+ }
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
userId = task.userId;
}
@@ -4719,7 +4930,12 @@ public final class ActivityManagerService extends ActivityManagerNative
app.thread.asBinder() == thread.asBinder()) {
boolean doLowMem = app.instrumentationClass == null;
boolean doOomAdj = doLowMem;
+ boolean homeRestart = false;
if (!app.killedByAm) {
+ if (mHomeProcessName != null && app.processName.equals(mHomeProcessName)) {
+ mHomeKilled = true;
+ homeRestart = true;
+ }
Slog.i(TAG, "Process " + app.processName + " (pid " + pid
+ ") has died");
mAllowLowerMemLevel = true;
@@ -4740,6 +4956,13 @@ public final class ActivityManagerService extends ActivityManagerNative
if (doLowMem) {
doLowMemReportIfNeededLocked(app);
}
+ if (mHomeKilled && homeRestart) {
+ Intent intent = getHomeIntent();
+ ActivityInfo aInfo = mStackSupervisor.resolveActivity(intent, null, 0, null, 0);
+ startProcessLocked(aInfo.processName, aInfo.applicationInfo, true, 0,
+ "activity", null, false, false, true);
+ homeRestart = false;
+ }
} else if (app.pid != pid) {
// A new process has already been started.
Slog.i(TAG, "Process " + app.processName + " (pid " + pid
@@ -4976,6 +5199,9 @@ public final class ActivityManagerService extends ActivityManagerNative
} else if (app.crashing) {
Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
return;
+ } else if (app.killedByAm) {
+ Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
+ return;
}
// In case we come through here for the same app before completing
@@ -5090,6 +5316,20 @@ public final class ActivityManagerService extends ActivityManagerNative
annotation != null ? "ANR " + annotation : "ANR",
info.toString());
+ //Set the trace file name to app name + current date format to avoid overrinding trace file
+ String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
+ if (tracesPath != null && tracesPath.length() != 0) {
+ File traceRenameFile = new File(tracesPath);
+ String newTracesPath;
+ int lpos = tracesPath.lastIndexOf (".");
+ if (-1 != lpos)
+ newTracesPath = tracesPath.substring (0, lpos) + "_" + app.processName + "_" + mTraceDateFormat.format(new Date()) + tracesPath.substring (lpos);
+ else
+ newTracesPath = tracesPath + "_" + app.processName;
+
+ traceRenameFile.renameTo(new File(newTracesPath));
+ }
+
// Bring up the infamous App Not Responding dialog
Message msg = Message.obtain();
HashMap<String, Object> map = new HashMap<String, Object>();
@@ -5112,7 +5352,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void run() {
synchronized (ActivityManagerService.this) {
- final Dialog d = new LaunchWarningWindow(mContext, cur, next);
+ final Dialog d = new LaunchWarningWindow(getUiContext(), cur, next);
d.show();
mUiHandler.postDelayed(new Runnable() {
@Override
@@ -6323,14 +6563,16 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void keyguardGoingAway(boolean disableWindowAnimations,
- boolean keyguardGoingToNotificationShade) {
+ boolean keyguardGoingToNotificationShade,
+ boolean keyguardShowingMedia) {
enforceNotIsolatedCaller("keyguardGoingAway");
final long token = Binder.clearCallingIdentity();
try {
synchronized (this) {
if (DEBUG_LOCKSCREEN) logLockScreen("");
mWindowManager.keyguardGoingAway(disableWindowAnimations,
- keyguardGoingToNotificationShade);
+ keyguardGoingToNotificationShade,
+ keyguardShowingMedia);
if (mLockScreenShown == LOCK_SCREEN_SHOWN) {
mLockScreenShown = LOCK_SCREEN_HIDDEN;
updateSleepIfNeededLocked();
@@ -6396,6 +6638,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}, dumpheapFilter);
+ ThemeUtils.registerThemeChangeReceiver(mContext, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ });
+
// Let system services know.
mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -6447,7 +6696,7 @@ public final class ActivityManagerService extends ActivityManagerNative
},
0, null, null,
new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false,
+ AppOpsManager.OP_BOOT_COMPLETED, null, true, false,
MY_PID, Process.SYSTEM_UID, userId);
}
}
@@ -6587,6 +6836,18 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ public String getCallingPackageForBroadcast(boolean foreground) {
+ BroadcastQueue queue = foreground ? mFgBroadcastQueue : mBgBroadcastQueue;
+ BroadcastRecord r = queue.getProcessingBroadcast();
+ if (r != null) {
+ return r.callerPackage;
+ } else {
+ Log.e(TAG, "Broadcast sender is only retrievable in the onReceive");
+ }
+ return null;
+ }
+
+
private ActivityRecord getCallingRecordLocked(IBinder token) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
@@ -9549,6 +9810,7 @@ public final class ActivityManagerService extends ActivityManagerNative
checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
+ boolean importantCaller = false;
// In this case the provider instance already exists, so we can
// return it right away.
conn = incProviderCountLocked(r, cpr, token, stable);
@@ -9558,6 +9820,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// make sure to count it as being accessed and thus
// back up on the LRU list. This is good because
// content providers are often expensive to start.
+ importantCaller = true;
checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
updateLruProcessLocked(cpr.proc, false, null);
checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
@@ -9570,36 +9833,37 @@ public final class ActivityManagerService extends ActivityManagerNative
"com.android.providers.calendar/.CalendarProvider2")) {
Slog.v(TAG, "****************** KILLING "
+ cpr.name.flattenToShortString());
- Process.killProcess(cpr.proc.pid);
+ cpr.proc.kill("test killing calendar provider", true);
}
}
- checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
- boolean success = updateOomAdjLocked(cpr.proc);
- maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
- checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
- if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
- // NOTE: there is still a race here where a signal could be
- // pending on the process even though we managed to update its
- // adj level. Not sure what to do about this, but at least
- // the race is now smaller.
+
+ boolean success = !cpr.proc.killedByAm;
+ if (success) {
+ checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
+ success = updateOomAdjLocked(cpr.proc);
+ maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
+ checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
+ if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
+ }
+
+ // There is still a race here where a signal could be pending on
+ // the process even though we managed to update its adj level.
+ // We check this case for perceptible app but exclude persistent
+ // because it should not be killed normally.
+ if (success && importantCaller && r != null && !r.persistent
+ && r.pid != cpr.proc.pid && !cpr.proc.persistent) {
+ success = ProcessList.isAlive(cpr.proc.pid, true);
+ }
+
if (!success) {
- // Uh oh... it looks like the provider's process
- // has been killed on us. We need to wait for a new
- // process to be started, and make sure its death
- // doesn't kill our process.
+ // It looks like the provider's process has been killed.
+ // We need to wait for a new process to be started,
+ // and make sure its death doesn't kill caller process.
Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
- + " is crashing; detaching " + r);
- boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- checkTime(startTime, "getContentProviderImpl: before appDied");
- appDiedLocked(cpr.proc);
- checkTime(startTime, "getContentProviderImpl: after appDied");
- if (!lastRef) {
- // This wasn't the last ref our process had on
- // the provider... we have now been killed, bail.
- return null;
- }
- providerRunning = false;
- conn = null;
+ + " is gone; waiting it to restart for " + r);
+ cpr.provider = null;
+ cpr.launchingApp = cpr.proc;
+ mLaunchingProviders.add(cpr);
}
}
@@ -10265,7 +10529,13 @@ public final class ActivityManagerService extends ActivityManagerNative
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.persistent = true;
- app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
+
+ // The Adj score defines an order of processes to be killed.
+ // If a process is shared by multiple apps, maxAdj must be set by the highest
+ // prioritized app to avoid being killed.
+ if (app.maxAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
+ app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
+ }
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
@@ -10703,6 +10973,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public void requestBugReport() {
enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
+ mContext.sendBroadcast(new Intent("android.intent.action.BUGREPORT_STARTED"));
SystemProperties.set("ctl.start", "bugreport");
}
@@ -10780,9 +11051,15 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
}
+ final int anrPid = proc.pid;
mHandler.post(new Runnable() {
@Override
public void run() {
+ if (anrPid != proc.pid) {
+ Slog.i(TAG, "Ignoring stale ANR (occurred in " + anrPid +
+ ", but current pid is " + proc.pid + ")");
+ return;
+ }
appNotResponding(proc, activity, parent, aboveSystem, annotation);
}
});
@@ -11002,6 +11279,18 @@ public final class ActivityManagerService extends ActivityManagerNative
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"registerProcessObserver()");
synchronized (this) {
+ for (Integer key : mForegroundActivitiesList.keySet()) {
+ Object[] o = mForegroundActivitiesList.get(key);
+ if (o.length == 3) {
+ try {
+ observer.onForegroundActivitiesChanged((int) o[0],
+ (int) o[1], (boolean) o[2]);
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
mProcessObservers.register(observer);
}
}
@@ -11890,6 +12179,12 @@ public final class ActivityManagerService extends ActivityManagerNative
mBooting = true;
startHomeActivityLocked(mCurrentUserId, "systemReady");
+ // start the power off alarm by boot mode
+ boolean isAlarmBoot = SystemProperties.getBoolean("ro.alarm_boot", false);
+ if (isAlarmBoot) {
+ startAlarmActivityLocked();
+ }
+
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
@@ -12005,6 +12300,28 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private void sendAppFailureBroadcast(String pkgName) {
+ Intent intent = new Intent(cyanogenmod.content.Intent.ACTION_APP_FAILURE,
+ (pkgName != null)? Uri.fromParts("package", pkgName, null) : null);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ }
+
+ /**
+ * A possible theme crash is one that throws one of the following exceptions
+ * {@link android.content.res.Resources.NotFoundException}
+ * {@link android.view.InflateException}
+ *
+ * @param exceptionClassName
+ * @return True if exceptionClassName is one of the above exceptions
+ */
+ private boolean isPossibleThemeCrash(String exceptionClassName) {
+ if (Resources.NotFoundException.class.getName().equals(exceptionClassName) ||
+ InflateException.class.getName().equals(exceptionClassName)) {
+ return true;
+ }
+ return false;
+ }
+
private boolean handleAppCrashLocked(ProcessRecord app, String reason,
String shortMsg, String longMsg, String stackTrace) {
long now = SystemClock.uptimeMillis();
@@ -12015,6 +12332,9 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
crashTime = null;
}
+
+ if (isPossibleThemeCrash(shortMsg)) sendAppFailureBroadcast(app.info.packageName);
+
if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
// This process loses!
Slog.w(TAG, "Process " + app.info.processName
@@ -12814,6 +13134,9 @@ public final class ActivityManagerService extends ActivityManagerNative
|| (!allUids && app.uid != callingUid)) {
continue;
}
+ if (app.processName.equals("system")) {
+ continue;
+ }
if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
// Generate process state info for running application
ActivityManager.RunningAppProcessInfo currApp =
@@ -15669,6 +15992,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mProcessesOnHold.remove(app);
if (app == mHomeProcess) {
+ mHomeProcessName = mHomeProcess.processName;
mHomeProcess = null;
}
if (app == mPreviousProcess) {
@@ -17324,6 +17648,9 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
ci = new Configuration(mConfiguration);
ci.userSetLocale = false;
+ if (ci.themeConfig == null) {
+ ci.themeConfig = ThemeConfig.getBootTheme(mContext.getContentResolver());
+ }
}
return ci;
}
@@ -17413,6 +17740,11 @@ public final class ActivityManagerService extends ActivityManagerNative
values.locale));
}
+ if (values.themeConfig != null) {
+ saveThemeResourceLocked(values.themeConfig,
+ !values.themeConfig.equals(mConfiguration.themeConfig));
+ }
+
mConfigurationSeq++;
if (mConfigurationSeq <= 0) {
mConfigurationSeq = 1;
@@ -17468,6 +17800,10 @@ public final class ActivityManagerService extends ActivityManagerNative
null, AppOpsManager.OP_NONE, null, false, false,
MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
+ // if locale changed, time format may have changed
+ final int is24Hour = android.text.format.DateFormat.is24HourFormat(mContext) ? 1 : 0;
+ mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+ // now send general broadcast
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
if (!mProcessesReady) {
@@ -17565,6 +17901,14 @@ public final class ActivityManagerService extends ActivityManagerNative
return srec.launchedFromPackage;
}
+ private void saveThemeResourceLocked(ThemeConfig t, boolean isDiff){
+ if(isDiff) {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Configuration.THEME_PKG_CONFIGURATION_PERSISTENCE_PROPERTY, t.toJson(),
+ UserHandle.USER_CURRENT);
+ }
+ }
+
// =========================================================
// LIFETIME MANAGEMENT
// =========================================================
@@ -17724,6 +18068,10 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_TOP;
+ if(app == mHomeProcess) {
+ mHomeKilled = false;
+ mHomeProcessName = mHomeProcess.processName;
+ }
} else if (app.instrumentationClass != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -17759,6 +18107,14 @@ public final class ActivityManagerService extends ActivityManagerNative
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
+
+ if (mHomeKilled && app.processName.equals(mHomeProcessName)) {
+ adj = ProcessList.PERSISTENT_PROC_ADJ;
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.cached = false;
+ app.empty = false;
+ app.adjType = "top-activity";
+ }
}
// Examine all activities if not already foreground.
@@ -18694,6 +19050,18 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean success = true;
if (app.curRawAdj != app.setRawAdj) {
+ String seempStr = "app_uid=" + app.uid
+ + ",app_pid=" + app.pid + ",oom_adj=" + app.curAdj
+ + ",setAdj=" + app.setAdj + ",hasShownUi=" + (app.hasShownUi ? 1 : 0)
+ + ",cached=" + (app.cached ? 1 : 0)
+ + ",fA=" + (app.foregroundActivities ? 1 : 0)
+ + ",fS=" + (app.foregroundServices ? 1 : 0)
+ + ",systemNoUi=" + (app.systemNoUi ? 1 : 0)
+ + ",curSchedGroup=" + app.curSchedGroup
+ + ",curProcState=" + app.curProcState + ",setProcState=" + app.setProcState
+ + ",killed=" + (app.killed ? 1 : 0) + ",killedByAm=" + (app.killedByAm ? 1 : 0)
+ + ",debugging=" + (app.debugging ? 1 : 0);
+ android.util.SeempLog.record_str(385, seempStr);
app.setRawAdj = app.curRawAdj;
}
@@ -18869,6 +19237,12 @@ public final class ActivityManagerService extends ActivityManagerNative
item.changes |= changes;
item.processState = app.repProcState;
item.foregroundActivities = app.repForegroundActivities;
+ if (item.foregroundActivities) {
+ Object[] o = new Object[]{item.pid, item.uid, item.foregroundActivities};
+ mForegroundActivitiesList.put(item.pid, o);
+ } else if (!item.foregroundActivities && mForegroundActivitiesList.get(item.pid) != null) {
+ mForegroundActivitiesList.remove(item.pid);
+ }
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
"Item " + Integer.toHexString(System.identityHashCode(item))
+ " " + app.toShortString() + ": changes=" + item.changes
@@ -19148,8 +19522,39 @@ public final class ActivityManagerService extends ActivityManagerNative
int nextCachedAdj = curCachedAdj+1;
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextEmptyAdj = curEmptyAdj+2;
+ ProcessRecord selectedAppRecord = null;
+ long serviceLastActivity = 0;
+ int numBServices = 0;
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
+ if (mEnableBServicePropagation && app.serviceb
+ && (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
+ numBServices++;
+ for (int s = app.services.size() - 1; s >= 0; s--) {
+ ServiceRecord sr = app.services.valueAt(s);
+ if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + app.processName
+ + " serviceb = " + app.serviceb + " s = " + s + " sr.lastActivity = "
+ + sr.lastActivity + " packageName = " + sr.packageName
+ + " processName = " + sr.processName);
+ if (SystemClock.uptimeMillis() - sr.lastActivity
+ < mMinBServiceAgingTime) {
+ if (DEBUG_OOM_ADJ) {
+ Slog.d(TAG,"Not aged enough!!!");
+ }
+ continue;
+ }
+ if (serviceLastActivity == 0) {
+ serviceLastActivity = sr.lastActivity;
+ selectedAppRecord = app;
+ } else if (sr.lastActivity < serviceLastActivity) {
+ serviceLastActivity = sr.lastActivity;
+ selectedAppRecord = app;
+ }
+ }
+ }
+ if (DEBUG_OOM_ADJ && selectedAppRecord != null) Slog.d(TAG,
+ "Identified app.processName = " + selectedAppRecord.processName
+ + " app.pid = " + selectedAppRecord.pid);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
@@ -19258,6 +19663,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
}
+ if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel)
+ && (selectedAppRecord != null)) {
+ ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
+ ProcessList.CACHED_APP_MAX_ADJ);
+ selectedAppRecord.setAdj = selectedAppRecord.curAdj;
+ if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + selectedAppRecord.processName
+ + " app.pid = " + selectedAppRecord.pid + " is moved to higher adj");
+ }
mNumServiceProcs = mNewNumServiceProcs;
@@ -20274,7 +20687,7 @@ public final class ActivityManagerService extends ActivityManagerNative
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID,
+ AppOpsManager.OP_BOOT_COMPLETED, null, true, false, MY_PID, Process.SYSTEM_UID,
userId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6e34876..f439966 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -25,6 +25,7 @@ import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
+import android.text.TextUtils;
import android.util.ArraySet;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -40,6 +41,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AppGlobals;
+import android.app.AppOpsManager;
import android.app.IActivityController;
import android.app.ResultInfo;
import android.app.ActivityManager.RunningTaskInfo;
@@ -67,6 +69,11 @@ import android.util.EventLog;
import android.util.Slog;
import android.view.Display;
+import com.android.server.LocalServices;
+
+import cyanogenmod.power.PerformanceManagerInternal;
+import cyanogenmod.providers.CMSettings;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -264,6 +271,10 @@ final class ActivityStack {
}
}
+ private final PerformanceManagerInternal mPerf;
+ private static final String PROTECTED_APPS_TARGET_VALIDATION_COMPONENT =
+ "com.android.settings/com.android.settings.applications.ProtectedAppsActivity";
+
final Handler mHandler;
final class ActivityStackHandler extends Handler {
@@ -362,6 +373,7 @@ final class ActivityStack {
mCurrentUser = mService.mCurrentUserId;
mRecentTasks = recentTasks;
mOverrideConfig = Configuration.EMPTY;
+ mPerf = LocalServices.getService(PerformanceManagerInternal.class);
}
boolean okToShowLocked(ActivityRecord r) {
@@ -941,10 +953,13 @@ final class ActivityStack {
r.userId, System.identityHashCode(r), r.shortComponentName,
mPausingActivity != null
? mPausingActivity.shortComponentName : "(none)");
- if (r.finishing && r.state == ActivityState.PAUSING) {
- if (DEBUG_PAUSE) Slog.v(TAG,
- "Executing finish of failed to pause activity: " + r);
- finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
+ if (r.state == ActivityState.PAUSING) {
+ r.state = ActivityState.PAUSED;
+ if (r.finishing) {
+ if (DEBUG_PAUSE) Slog.v(TAG,
+ "Executing finish of failed to pause activity: " + r);
+ finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
+ }
}
}
}
@@ -1130,6 +1145,9 @@ final class ActivityStack {
// When resuming an activity, require it to call requestVisibleBehind() again.
mActivityContainer.mActivityDisplay.setVisibleBehindActivity(null);
}
+
+ updatePrivacyGuardNotificationLocked(next);
+ updateProtectedAppNotificationLocked(next);
}
private void setVisible(ActivityRecord r, boolean visible) {
@@ -1682,6 +1700,11 @@ final class ActivityStack {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
+ // Some activities may want to alter the system power management
+ if (mStackSupervisor.mPerf != null) {
+ mStackSupervisor.mPerf.activityResumed(next.intent);
+ }
+
// If we are currently pausing an activity, then don't do anything
// until that is done.
if (!mStackSupervisor.allPausedActivitiesComplete()) {
@@ -1814,6 +1837,11 @@ final class ActivityStack {
mWindowManager.prepareAppTransition(prev.task == next.task
? AppTransition.TRANSIT_ACTIVITY_CLOSE
: AppTransition.TRANSIT_TASK_CLOSE, false);
+ if (prev.task != next.task) {
+ if (mStackSupervisor.mPerf != null) {
+ mStackSupervisor.mPerf.cpuBoost(2000 * 1000);
+ }
+ }
}
mWindowManager.setAppWillBeHidden(prev.appToken);
mWindowManager.setAppVisibility(prev.appToken, false);
@@ -1829,6 +1857,11 @@ final class ActivityStack {
: next.mLaunchTaskBehind
? AppTransition.TRANSIT_TASK_OPEN_BEHIND
: AppTransition.TRANSIT_TASK_OPEN, false);
+ if (prev.task != next.task) {
+ if (mStackSupervisor.mPerf != null) {
+ mStackSupervisor.mPerf.cpuBoost(2000 * 1000);
+ }
+ }
}
}
if (false) {
@@ -2071,6 +2104,42 @@ final class ActivityStack {
updateTaskMovement(task, true);
}
+ private final void updateProtectedAppNotificationLocked(ActivityRecord next) {
+ ComponentName componentName = ComponentName.unflattenFromString(next.shortComponentName);
+ if (TextUtils.equals(componentName.flattenToString(),
+ PROTECTED_APPS_TARGET_VALIDATION_COMPONENT)) {
+ Message msg = mService.mHandler.obtainMessage(
+ ActivityManagerService.CANCEL_PROTECTED_APP_NOTIFICATION, next);
+ msg.sendToTarget();
+ }
+ }
+
+ private final void updatePrivacyGuardNotificationLocked(ActivityRecord next) {
+
+ String privacyGuardPackageName = mStackSupervisor.mPrivacyGuardPackageName;
+ if (privacyGuardPackageName != null && privacyGuardPackageName.equals(next.packageName)) {
+ return;
+ }
+
+ boolean privacy = mService.mAppOpsService.getPrivacyGuardSettingForPackage(
+ next.app.uid, next.packageName);
+ boolean privacyNotification = (CMSettings.Secure.getInt(
+ mService.mContext.getContentResolver(),
+ CMSettings.Secure.PRIVACY_GUARD_NOTIFICATION, 1) == 1);
+
+ if (privacyGuardPackageName != null && !privacy) {
+ Message msg = mService.mHandler.obtainMessage(
+ ActivityManagerService.CANCEL_PRIVACY_NOTIFICATION_MSG, next.userId);
+ msg.sendToTarget();
+ mStackSupervisor.mPrivacyGuardPackageName = null;
+ } else if (privacy && privacyNotification) {
+ Message msg = mService.mHandler.obtainMessage(
+ ActivityManagerService.POST_PRIVACY_NOTIFICATION_MSG, next);
+ msg.sendToTarget();
+ mStackSupervisor.mPrivacyGuardPackageName = next.packageName;
+ }
+ }
+
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
@@ -2620,7 +2689,23 @@ final class ActivityStack {
final String myReason = reason + " adjustFocus";
if (next != r) {
final TaskRecord task = r.task;
- if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
+ boolean adjust = false;
+ if ((next == null || next.task != task) && r.frontOfTask) {
+ if (task.isOverHomeStack() && task == topTask()) {
+ adjust = true;
+ } else {
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord tr = mTaskHistory.get(taskNdx);
+ if (tr.getTopActivity() != null) {
+ break;
+ } else if (tr.isOverHomeStack()) {
+ adjust = true;
+ break;
+ }
+ }
+ }
+ }
+ if (adjust) {
// For non-fullscreen stack, we want to move the focus to the next visible
// stack to prevent the home screen from moving to the top and obscuring
// other visible stacks.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 17a86ca..cf49e15 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -101,12 +101,12 @@ import android.util.ArraySet;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
-
import android.util.SparseIntArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.InputEvent;
import android.view.Surface;
+
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -118,6 +118,7 @@ import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.WindowManagerService;
+import cyanogenmod.power.PerformanceManagerInternal;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -273,6 +274,15 @@ public final class ActivityStackSupervisor implements DisplayListener {
* setWindowManager is called. **/
private boolean mLeanbackOnlyDevice;
+ PowerManager mPm;
+
+ PerformanceManagerInternal mPerf;
+
+ /**
+ * Is the privacy guard currently enabled? Shared between ActivityStacks
+ */
+ String mPrivacyGuardPackageName = null;
+
/**
* We don't want to allow the device to go to sleep while in the process
* of launching an activity. This is primarily to allow alarm intent
@@ -344,14 +354,25 @@ public final class ActivityStackSupervisor implements DisplayListener {
mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
}
+ private void launchBoost() {
+ if (mPerf == null) {
+ mPerf = LocalServices.getService(PerformanceManagerInternal.class);
+ }
+ if (mPerf == null) {
+ Slog.e(TAG, "PerformanceManager not ready!");
+ } else {
+ mPerf.launchBoost();
+ }
+ }
+
/**
* At the time when the constructor runs, the power manager has not yet been
* initialized. So we initialize our wakelocks afterwards.
*/
void initPowerManagement() {
- PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
- mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
- mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*launch*");
+ mPm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
+ mGoingToSleep = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
+ mLaunchingActivity = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*launch*");
mLaunchingActivity.setReferenceCounted(false);
}
@@ -511,7 +532,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
ActivityRecord r = getHomeActivity();
- if (r != null) {
+ // Only resume home activity if isn't finishing.
+ if (r != null && !r.finishing) {
mService.setFocusedActivityLocked(r, reason);
return resumeTopActivitiesLocked(mHomeStack, prev, null);
}
@@ -949,6 +971,23 @@ public final class ActivityStackSupervisor implements DisplayListener {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
+
+ try {
+ //TODO: This needs to be a flushed out API in the future.
+ if (intent.getComponent() != null && AppGlobals.getPackageManager()
+ .isComponentProtected(callingPackage, intent.getComponent(), userId)) {
+ Message msg = mService.mHandler.obtainMessage(
+ ActivityManagerService.POST_COMPONENT_PROTECTED_MSG);
+ //Store start flags, userid
+ intent.setFlags(startFlags);
+ intent.putExtra("com.android.settings.PROTECTED_APPS_USER_ID", userId);
+ msg.obj = intent;
+ mService.mHandler.sendMessage(msg);
+ return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY;
+ }
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
int callingPid;
@@ -1429,6 +1468,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
(container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
container.mActivityDisplay.mDisplayId)));
+ /* Acquire perf lock during new app launch */
+ launchBoost();
}
ActivityRecord sourceRecord = null;
@@ -1481,6 +1522,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
// We couldn't find a class that can handle the given Intent.
// That's the end of that!
+ final Uri data = intent.getData();
+ final String strData = data != null ? data.toSafeString() : null;
+ EventLog.writeEvent(EventLogTags.AM_INTENT_NOT_RESOLVED, callingPackage,
+ intent.getAction(), intent.getType(), strData, intent.getFlags());
+
err = ActivityManager.START_INTENT_NOT_RESOLVED;
}
@@ -2674,8 +2720,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack.finishDisabledPackageActivitiesLocked(
packageName, filterByClasses, doit, evenPersistent, userId)) {
@@ -2774,6 +2819,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options, String reason) {
+ ActivityRecord top = task.stack.topRunningActivityLocked(null);
+ /* App is launching from recent apps and it's a new process */
+ if(top != null && top.state == ActivityState.DESTROYED) {
+ launchBoost();
+ }
+
if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
mUserLeaving = true;
}
@@ -3055,11 +3106,16 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
final ActivityRecord ar = stack.findTaskLocked(r);
if (ar != null) {
+ if (ar.state == ActivityState.DESTROYED) {
+ launchBoost();
+ }
return ar;
}
}
}
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found");
+ launchBoost();
+
return null;
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 62768c3..5fd3510 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006-2007 The Android Open Source Project
+ * Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,6 +51,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.DockBatteryStatsImpl;
+
import com.android.internal.os.PowerProfile;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -75,6 +78,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
static IBatteryStats sService;
final BatteryStatsImpl mStats;
+ // The dock stats only collect statistics about battery (no wakelocks, no counters, ...),
+ // just the dock battery history
+ final DockBatteryStatsImpl mDockStats;
final BatteryStatsHandler mHandler;
Context mContext;
PowerManagerInternal mPowerManagerInternal;
@@ -167,6 +173,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
// BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
mStats = new BatteryStatsImpl(systemDir, handler, mHandler);
+ mDockStats = new DockBatteryStatsImpl(systemDir, handler, mHandler);
}
public void publish(Context context) {
@@ -196,6 +203,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
synchronized (mStats) {
mStats.shutdownLocked();
}
+ synchronized (mDockStats) {
+ mDockStats.shutdownLocked();
+ }
}
public static IBatteryStats getService() {
@@ -231,6 +241,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK);
}
+ /**
+ * @return the current dock statistics object, which may be modified
+ * to reflect events that affect battery usage. You must lock the
+ * stats object before doing anything with it.
+ * @hide
+ */
+ public BatteryStatsImpl getActiveDockStatistics() {
+ return mDockStats;
+ }
+
// These are for direct use by the activity manager...
/**
@@ -327,6 +347,48 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ /** @hide */
+ public byte[] getDockStatistics() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ //Slog.i("foo", "SENDING DOCK BATTERY INFO:");
+ //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
+ Parcel out = Parcel.obtain();
+ mDockStats.writeToParcel(out, 0);
+ byte[] data = out.marshall();
+ out.recycle();
+ return data;
+ }
+
+ /** @hide */
+ public ParcelFileDescriptor getDockStatisticsStream() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ //Slog.i("foo", "SENDING DOCK BATTERY INFO:");
+ //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
+ Parcel out = Parcel.obtain();
+ mDockStats.writeToParcel(out, 0);
+ byte[] data = out.marshall();
+ out.recycle();
+ try {
+ return ParcelFileDescriptor.fromData(data, "dock-battery-stats");
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to create shared memory", e);
+ return null;
+ }
+ }
+
+ public void resetStatistics() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.RESET_BATTERY_STATS, null);
+ synchronized (mStats) {
+ mStats.resetAllStatsCmdLocked();
+ }
+ synchronized (mDockStats) {
+ mDockStats.resetAllStatsCmdLocked();
+ }
+ }
+
public long computeBatteryTimeRemaining() {
synchronized (mStats) {
long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
@@ -901,6 +963,31 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return mStats.getAwakeTimePlugged();
}
+ /** @hide */
+ public boolean isOnDockBattery() {
+ return mDockStats.isOnBattery();
+ }
+
+ /** @hide */
+ public void setDockBatteryState(int status, int health, int plugType, int level,
+ int temp, int volt) {
+ enforceCallingPermission();
+ mDockStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+ }
+
+ /** @hide */
+ public long getAwakeTimeDockBattery() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ return mDockStats.getAwakeTimeBattery();
+ }
+
+ public long getAwakeTimeDockPlugged() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ return mDockStats.getAwakeTimePlugged();
+ }
+
public void enforceCallingPermission() {
if (Binder.getCallingPid() == Process.myPid()) {
return;
@@ -1065,6 +1152,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
} else if ("--reset".equals(arg)) {
synchronized (mStats) {
mStats.resetAllStatsCmdLocked();
+ mDockStats.resetAllStatsCmdLocked();
pw.println("Battery stats reset.");
noOutput = true;
}
@@ -1073,6 +1161,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
updateExternalStats("dump", UPDATE_ALL);
synchronized (mStats) {
mStats.writeSyncLocked();
+ mDockStats.writeSyncLocked();
pw.println("Battery stats written.");
noOutput = true;
}
@@ -1176,19 +1265,44 @@ public final class BatteryStatsService extends IBatteryStats.Stub
+ mStats.mCheckinFile.getBaseFile(), e);
}
}
+ if (mDockStats.mCheckinFile.exists()) {
+ try {
+ byte[] raw = mDockStats.mCheckinFile.readFully();
+ if (raw != null) {
+ Parcel in = Parcel.obtain();
+ in.unmarshall(raw, 0, raw.length);
+ in.setDataPosition(0);
+ DockBatteryStatsImpl checkinStats = new DockBatteryStatsImpl(
+ null, mStats.mHandler, null);
+ checkinStats.readSummaryFromParcel(in);
+ in.recycle();
+ checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
+ historyStart);
+ mDockStats.mCheckinFile.delete();
+ return;
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "Failure reading dock checkin file "
+ + mDockStats.mCheckinFile.getBaseFile(), e);
+ }
+ }
}
}
synchronized (mStats) {
mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
+ mDockStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
if (writeData) {
mStats.writeAsyncLocked();
+ mDockStats.writeAsyncLocked();
}
}
} else {
synchronized (mStats) {
mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
+ mDockStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
if (writeData) {
mStats.writeAsyncLocked();
+ mDockStats.writeAsyncLocked();
}
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 6de8579..589a4b8 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -142,6 +142,11 @@ public final class BroadcastQueue {
*/
BroadcastRecord mPendingBroadcast = null;
+ /**
+ * Intent broadcast that we are currently processing
+ */
+ BroadcastRecord mCurrentBroadcast = null;
+
/**
* The receiver index that is pending, to restart the broadcast if needed.
*/
@@ -636,6 +641,10 @@ public final class BroadcastQueue {
.sendToTarget();
}
+ BroadcastRecord getProcessingBroadcast() {
+ return mCurrentBroadcast;
+ }
+
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
@@ -656,6 +665,7 @@ public final class BroadcastQueue {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
+ mCurrentBroadcast = r;
final int N = r.receivers.size();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
@@ -669,6 +679,7 @@ public final class BroadcastQueue {
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
+ mCurrentBroadcast = null;
}
// Now take care of the next serialized one...
@@ -714,6 +725,7 @@ public final class BroadcastQueue {
return;
}
r = mOrderedBroadcasts.get(0);
+ mCurrentBroadcast = r;
boolean forceReceive = false;
// Ensure that even if something goes awry with the timeout
@@ -784,6 +796,7 @@ public final class BroadcastQueue {
// ... and on to the next...
addBroadcastToHistoryLocked(r);
mOrderedBroadcasts.remove(0);
+ mCurrentBroadcast = null;
r = null;
looped = true;
continue;
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 9a645df..33fa714 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -78,6 +78,8 @@ option java_package com.android.server.am
30036 am_provider_lost_process (User|1|5),(Package Name|3),(UID|1|5),(Name|3)
# The activity manager gave up on a new process taking too long to start
30037 am_process_start_timeout (User|1|5),(PID|1|5),(UID|1|5),(Process Name|3)
+# The activity manager was unable to resolve the intent to an Activity
+30038 am_intent_not_resolved (Calling Package Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
# Unhandled exception
30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5)
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index afde322..055e33e 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -20,11 +20,14 @@ import android.app.ActivityManager;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import com.android.internal.R;
+import cyanogenmod.providers.CMSettings;
/**
* Helper to manage showing/hiding a image to notify them that they are entering
@@ -45,25 +48,32 @@ public class LockTaskNotify {
mHandler = new H();
}
+ private boolean hasNavigationBar() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_showNavigationBar)
+ || CMSettings.Secure.getIntForUser(mContext.getContentResolver(),
+ CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1;
+ }
+
public void showToast(int lockTaskModeState) {
mHandler.obtainMessage(H.SHOW_TOAST, lockTaskModeState, 0 /* Not used */).sendToTarget();
}
public void handleShowToast(int lockTaskModeState) {
- String text = null;
+ final int textResId;
if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) {
- text = mContext.getString(R.string.lock_to_app_toast_locked);
- } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED) {
- text = mContext.getString(mAccessibilityManager.isEnabled()
- ? R.string.lock_to_app_toast_accessible : R.string.lock_to_app_toast);
- }
- if (text == null) {
- return;
+ textResId = R.string.lock_to_app_toast_locked;
+ } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED &&
+ mAccessibilityManager.isEnabled() && hasNavigationBar()) {
+ textResId = R.string.lock_to_app_toast_accessible;
+ } else {
+ textResId = hasNavigationBar()
+ ? R.string.lock_to_app_toast : R.string.lock_to_app_toast_no_navbar;
}
if (mLastToast != null) {
mLastToast.cancel();
}
- mLastToast = makeAllUserToastAndShow(text);
+ mLastToast = makeAllUserToastAndShow(mContext.getString(textResId));
}
public void show(boolean starting) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 0e24952..9c9a421 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -32,6 +32,7 @@ import com.android.server.wm.WindowManagerService;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.SystemProperties;
+import android.os.Process;
import android.net.LocalSocketAddress;
import android.net.LocalSocket;
import android.util.Slog;
@@ -133,7 +134,17 @@ final class ProcessList {
// we have no limit on the number of service, visible, foreground, or other such
// processes and the number of those processes does not count against the cached
// process limit.
- static final int MAX_CACHED_APPS = 32;
+ static final int MAX_CACHED_APPS = SystemProperties.getInt("ro.sys.fw.bg_apps_limit",32);
+ static final boolean USE_TRIM_SETTINGS =
+ SystemProperties.getBoolean("ro.sys.fw.use_trim_settings",false);
+ static final int EMPTY_APP_PERCENT = SystemProperties.getInt("ro.sys.fw.empty_app_percent",50);
+ static final int TRIM_EMPTY_PERCENT =
+ SystemProperties.getInt("ro.sys.fw.trim_empty_percent",100);
+ static final int TRIM_CACHE_PERCENT =
+ SystemProperties.getInt("ro.sys.fw.trim_cache_percent",100);
+ static final long TRIM_ENABLE_MEMORY =
+ SystemProperties.getLong("ro.sys.fw.trim_enable_memory",1073741824);
+ public static boolean allowTrim() { return Process.getTotalMemory() < TRIM_ENABLE_MEMORY ; }
// We allow empty processes to stick around for at most 30 minutes.
static final long MAX_EMPTY_TIME = 30*60*1000;
@@ -143,11 +154,25 @@ final class ProcessList {
// The number of empty apps at which we don't consider it necessary to do
// memory trimming.
- static final int TRIM_EMPTY_APPS = MAX_EMPTY_APPS/2;
+ public static int computeTrimEmptyApps() {
+ if (USE_TRIM_SETTINGS && allowTrim()) {
+ return MAX_EMPTY_APPS*TRIM_EMPTY_PERCENT/100;
+ } else {
+ return MAX_EMPTY_APPS/2;
+ }
+ }
+ static final int TRIM_EMPTY_APPS = computeTrimEmptyApps();
// The number of cached at which we don't consider it necessary to do
// memory trimming.
- static final int TRIM_CACHED_APPS = (MAX_CACHED_APPS-MAX_EMPTY_APPS)/3;
+ public static int computeTrimCachedApps() {
+ if (USE_TRIM_SETTINGS && allowTrim()) {
+ return MAX_CACHED_APPS*TRIM_CACHE_PERCENT/100;
+ } else {
+ return (MAX_CACHED_APPS-MAX_EMPTY_APPS)/3;
+ }
+ }
+ static final int TRIM_CACHED_APPS = computeTrimCachedApps();
// Threshold of number of cached+empty where we consider memory critical.
static final int TRIM_CRITICAL_THRESHOLD = 3;
@@ -172,6 +197,17 @@ final class ProcessList {
FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
};
+
+ // These are the low-end OOM level limits for 32bit 1 GB RAM
+ private final int[] mOomMinFreeLow32Bit = new int[] {
+ 12288, 18432, 24576,
+ 36864, 43008, 49152
+ };
+ // These are the high-end OOM level limits for 32bit 1 GB RAM
+ private final int[] mOomMinFreeHigh32Bit = new int[] {
+ 61440, 76800, 92160,
+ 107520, 137660, 174948
+ };
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
private final int[] mOomMinFreeLow = new int[] {
@@ -240,15 +276,24 @@ final class ProcessList {
Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
}
+ // We've now baked in the increase to the basic oom values above, since
+ // they seem to be useful more generally for devices that are tight on
+ // memory than just for 64 bit. This should probably have some more
+ // tuning done, so not deleting it quite yet...
final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;
for (int i=0; i<mOomAdj.length; i++) {
int low = mOomMinFreeLow[i];
int high = mOomMinFreeHigh[i];
if (is64bit) {
+ Slog.i("XXXXXX", "choosing minFree values for 64 Bit");
// Increase the high min-free levels for cached processes for 64-bit
if (i == 4) high = (high*3)/2;
else if (i == 5) high = (high*7)/4;
+ } else {
+ Slog.i("XXXXXX", "choosing minFree values for 32 Bit");
+ low = mOomMinFreeLow32Bit[i];
+ high = mOomMinFreeHigh32Bit[i];
}
mOomMinFree[i] = (int)(low + ((high-low)*scale));
}
@@ -308,7 +353,11 @@ final class ProcessList {
}
public static int computeEmptyProcessLimit(int totalProcessLimit) {
- return totalProcessLimit/2;
+ if(USE_TRIM_SETTINGS && allowTrim()) {
+ return totalProcessLimit*EMPTY_APP_PERCENT/100;
+ } else {
+ return totalProcessLimit/2;
+ }
}
private static String buildOomTag(String prefix, String space, int val, int base) {
@@ -671,16 +720,15 @@ final class ProcessList {
}
private static void writeLmkd(ByteBuffer buf) {
-
for (int i = 0; i < 3; i++) {
if (sLmkdSocket == null) {
- if (openLmkdSocket() == false) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
- continue;
+ if (openLmkdSocket() == false) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
}
+ continue;
+ }
}
try {
@@ -698,4 +746,55 @@ final class ProcessList {
}
}
}
+
+ private static final int[] PROCESS_STATS_FORMAT;
+ static {
+ PROCESS_STATS_FORMAT = new int[31];
+ java.util.Arrays.fill(PROCESS_STATS_FORMAT, android.os.Process.PROC_SPACE_TERM);
+ // Process name enclosed in parentheses
+ PROCESS_STATS_FORMAT[1] |= android.os.Process.PROC_PARENS;
+ // Process state (D/R/S/T/Z)
+ PROCESS_STATS_FORMAT[2] |= android.os.Process.PROC_OUT_STRING;
+ // Bit mask of pending signals
+ PROCESS_STATS_FORMAT[30] |= android.os.Process.PROC_OUT_STRING;
+ }
+
+ static boolean isAlive(int pid, boolean noisy) {
+ final String[] procStats = new String[2];
+ final String stat = "/proc/" + pid + "/stat";
+ if (android.os.Process.readProcFile(stat, PROCESS_STATS_FORMAT,
+ procStats, null, null)) {
+ if ("Z".equals(procStats[0])) {
+ if (noisy) {
+ Slog.i(TAG, pid + " is zombie state");
+ }
+ return false;
+ }
+ try {
+ int pendingSignals = Integer.parseInt(procStats[1]);
+ if ((pendingSignals & (1 << 8)) != 0) {
+ if (noisy) {
+ Slog.i(TAG, pid + " has pending signal 9");
+ }
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Unknown pending signals " + procStats[1] + " of " + pid);
+ }
+ } else {
+ boolean exists = false;
+ try {
+ exists = libcore.io.Libcore.os.access(stat, android.system.OsConstants.F_OK);
+ } catch (android.system.ErrnoException e) {
+ exists = e.errno != android.system.OsConstants.ENOENT;
+ }
+ if (!exists) {
+ if (noisy) {
+ Slog.i(TAG, stat + " does not exist");
+ }
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 4e42c5c..33f1a1c 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -438,6 +438,18 @@ final class ProcessRecord {
}
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
+ String seempStr = "app_uid=" + uid
+ + ",app_pid=" + pid + ",oom_adj=" + curAdj
+ + ",setAdj=" + setAdj + ",hasShownUi=" + (hasShownUi ? 1 : 0)
+ + ",cached=" + (cached ? 1 : 0)
+ + ",fA=" + (foregroundActivities ? 1 : 0)
+ + ",fS=" + (foregroundServices ? 1 : 0)
+ + ",systemNoUi=" + (systemNoUi ? 1 : 0)
+ + ",curSchedGroup=" + curSchedGroup
+ + ",curProcState=" + curProcState + ",setProcState=" + setProcState
+ + ",killed=" + (killed ? 1 : 0) + ",killedByAm=" + (killedByAm ? 1 : 0)
+ + ",debugging=" + (debugging ? 1 : 0);
+ android.util.SeempLog.record_str(386, seempStr);
if (thread == null) {
final ProcessStats.ProcessState origBase = baseProcessTracker;
if (origBase != null) {
@@ -464,6 +476,18 @@ final class ProcessRecord {
}
public void makeInactive(ProcessStatsService tracker) {
+ String seempStr = "app_uid=" + uid
+ + ",app_pid=" + pid + ",oom_adj=" + curAdj
+ + ",setAdj=" + setAdj + ",hasShownUi=" + (hasShownUi ? 1 : 0)
+ + ",cached=" + (cached ? 1 : 0)
+ + ",fA=" + (foregroundActivities ? 1 : 0)
+ + ",fS=" + (foregroundServices ? 1 : 0)
+ + ",systemNoUi=" + (systemNoUi ? 1 : 0)
+ + ",curSchedGroup=" + curSchedGroup
+ + ",curProcState=" + curProcState + ",setProcState=" + setProcState
+ + ",killed=" + (killed ? 1 : 0) + ",killedByAm=" + (killedByAm ? 1 : 0)
+ + ",debugging=" + (debugging ? 1 : 0);
+ android.util.SeempLog.record_str(387, seempStr);
thread = null;
final ProcessStats.ProcessState origBase = baseProcessTracker;
if (origBase != null) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 152ff30..92643ba 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -35,6 +35,7 @@ import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -59,6 +60,7 @@ import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioPort;
+import android.media.AudioRecord;
import android.media.AudioRoutesInfo;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioRoutesObserver;
@@ -125,6 +127,8 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
+import cyanogenmod.providers.CMSettings;
+
/**
* The implementation of the volume manager service.
* <p>
@@ -171,6 +175,27 @@ public class AudioService extends IAudioService.Stub {
// the platform type affects volume and silent mode behavior
private final int mPlatformType;
+ private static final ArrayList<MediaPlayerInfo> mMediaPlayers =
+ new ArrayList<MediaPlayerInfo>();
+
+ private class MediaPlayerInfo {
+ private String mPackageName;
+ private boolean mIsfocussed;
+ public MediaPlayerInfo(String packageName, boolean isfocussed) {
+ mPackageName = packageName;
+ mIsfocussed = isfocussed;
+ }
+ public boolean isFocussed() {
+ return mIsfocussed;
+ }
+ public void setFocus(boolean focus) {
+ mIsfocussed = focus;
+ }
+ public String getPackageName() {
+ return mPackageName;
+ }
+ }
+
private boolean isPlatformVoice() {
return mPlatformType == AudioSystem.PLATFORM_VOICE;
}
@@ -384,6 +409,15 @@ public class AudioService extends IAudioService.Stub {
* @see System#MUTE_STREAMS_AFFECTED */
private int mMuteAffectedStreams;
+ /** @see #handleHotwordInput **/
+ private Object mHotwordInputLock = new Object();
+
+ /** The package name of the application that is
+ * currently using the HOTWORD input.
+ */
+ // protected by mHotwordInputLock
+ private String mHotwordAudioInputPackage;
+
/**
* NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
* mVibrateSetting is just maintained during deprecation period but vibration policy is
@@ -424,6 +458,11 @@ public class AudioService extends IAudioService.Stub {
private final ArrayMap<String, DeviceListSpec> mConnectedDevices = new ArrayMap<>();
+ private String mA2dpConnectedDevice = ""; //Used for BT a2dp connection
+ //Add connected A2dp devices in this list
+ private ArrayList<BluetoothDevice> mConnectedBTDevicesList =
+ new ArrayList<BluetoothDevice>();
+
// Forced device usage for communications
private int mForcedUseForComm;
@@ -515,7 +554,6 @@ public class AudioService extends IAudioService.Stub {
// Devices for which the volume is fixed and VolumePanel slider should be disabled
int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
- AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_HDMI_ARC |
AudioSystem.DEVICE_OUT_SPDIF |
AudioSystem.DEVICE_OUT_AUX_LINE;
@@ -527,6 +565,9 @@ public class AudioService extends IAudioService.Stub {
private boolean mDockAudioMediaEnabled = true;
+ private boolean mForceAnalogDeskDock;
+ private boolean mForceAnalogCarDock;
+
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
// Used when safe volume warning message display is requested by setStreamVolume(). In this
@@ -545,11 +586,14 @@ public class AudioService extends IAudioService.Stub {
// If absolute volume is supported in AVRCP device
private boolean mAvrcpAbsVolSupported = false;
+ private boolean mLinkNotificationWithVolume;
+ private final boolean mVoiceCapable;
private static Long mLastDeviceConnectMsgTime = new Long(0);
private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
private long mLoweredFromNormalToVibrateTime;
+ private boolean mVolumeKeysControlRingStream;
// Intent "extra" data keys.
public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName";
@@ -602,6 +646,9 @@ public class AudioService extends IAudioService.Stub {
mForcedUseForComm = AudioSystem.FORCE_NONE;
+ mVoiceCapable = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_voice_capable);
+
createAudioSystemThread();
AudioSystem.setErrorCallback(mAudioSystemCallback);
@@ -628,6 +675,15 @@ public class AudioService extends IAudioService.Stub {
mUseFixedVolume = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
+ mForceAnalogDeskDock = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_forceAnalogDeskDock);
+ mForceAnalogCarDock = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_forceAnalogCarDock);
+
+ // read this in before readPersistedSettings() because updateStreamVolumeAlias needs it
+ mLinkNotificationWithVolume = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1;
+
// must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
// array initialized by updateStreamVolumeAlias()
updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
@@ -658,6 +714,7 @@ public class AudioService extends IAudioService.Stub {
intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ intentFilter.addAction(Intent.ACTION_SHUTDOWN);
// TODO merge orientation and rotation
mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
if (mMonitorOrientation) {
@@ -850,6 +907,100 @@ public class AudioService extends IAudioService.Stub {
}
}
+ /**
+ * @hide
+ */
+ public void addMediaPlayerAndUpdateRemoteController (String packageName) {
+ Log.v(TAG, "addMediaPlayerAndUpdateRemoteController: size of existing list: " +
+ mMediaPlayers.size());
+ boolean playerToAdd = true;
+ if (mMediaPlayers.size() > 0) {
+ final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator();
+ while (rccIterator.hasNext()) {
+ final MediaPlayerInfo player = rccIterator.next();
+ if (packageName.equals(player.getPackageName())) {
+ Log.e(TAG, "Player entry present, no need to add");
+ playerToAdd = false;
+ player.setFocus(true);
+ } else {
+ Log.e(TAG, "Player: " + player.getPackageName()+ "Lost Focus");
+ player.setFocus(false);
+ }
+ }
+ }
+ if (playerToAdd) {
+ Log.e(TAG, "Adding Player: " + packageName + " to available player list");
+ mMediaPlayers.add(new MediaPlayerInfo(packageName, true));
+ }
+ Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName);
+ intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, true);
+ intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true);
+ sendBroadcastToAll(intent);
+ Log.v(TAG, "updating focussed RCC change to RCD: CallingPackageName:"
+ + packageName);
+ }
+
+ /**
+ * @hide
+ */
+ public void updateRemoteControllerOnExistingMediaPlayers() {
+ Log.v(TAG, "updateRemoteControllerOnExistingMediaPlayers: size of Player list: " +
+ mMediaPlayers.size());
+ if (mMediaPlayers.size() > 0) {
+ Log.v(TAG, "Inform RemoteController regarding existing RCC entry");
+ final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator();
+ while (rccIterator.hasNext()) {
+ final MediaPlayerInfo player = rccIterator.next();
+ Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME,
+ player.getPackageName());
+ intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE,
+ player.isFocussed());
+ intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true);
+ sendBroadcastToAll(intent);
+ Log.v(TAG, "updating RCC change: CallingPackageName:" +
+ player.getPackageName());
+ }
+ } else {
+ Log.e(TAG, "No RCC entry present to update");
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void removeMediaPlayerAndUpdateRemoteController (String packageName) {
+ Log.v(TAG, "removeMediaPlayerAndUpdateRemoteController: size of existing list: " +
+ mMediaPlayers.size());
+ boolean playerToRemove = false;
+ int index = -1;
+ if (mMediaPlayers.size() > 0) {
+ final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator();
+ while (rccIterator.hasNext()) {
+ index++;
+ final MediaPlayerInfo player = rccIterator.next();
+ if (packageName.equals(player.getPackageName())) {
+ Log.v(TAG, "Player entry present remove and update RemoteController");
+ playerToRemove = true;
+ break;
+ } else {
+ Log.v(TAG, "Player entry for " + player.getPackageName()+ " is not present");
+ }
+ }
+ }
+ if (playerToRemove) {
+ Log.e(TAG, "Removing Player: " + packageName + " from index" + index);
+ mMediaPlayers.remove(index);
+ }
+ Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName);
+ intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, false);
+ intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, false);
+ sendBroadcastToAll(intent);
+ Log.v(TAG, "Updated List size: " + mMediaPlayers.size());
+ }
+
private void checkAllAliasStreamVolumes() {
synchronized (VolumeStreamState.class) {
int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -943,6 +1094,13 @@ public class AudioService extends IAudioService.Stub {
}
mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
+
+ if (mLinkNotificationWithVolume && mVoiceCapable) {
+ mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING;
+ } else {
+ mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION;
+ }
+
if (updateVolumes) {
mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
caller);
@@ -1013,8 +1171,15 @@ public class AudioService extends IAudioService.Stub {
updateRingerModeAffectedStreams();
readDockAudioSettings(cr);
+
+ mVolumeKeysControlRingStream = CMSettings.System.getIntForUser(cr,
+ CMSettings.System.VOLUME_KEYS_CONTROL_RING_STREAM, 1,
+ UserHandle.USER_CURRENT) == 1;
}
+ mLinkNotificationWithVolume = Settings.Secure.getInt(cr,
+ Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1;
+
mMuteAffectedStreams = System.getIntForUser(cr,
System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
UserHandle.USER_CURRENT);
@@ -1451,6 +1616,46 @@ public class AudioService extends IAudioService.Stub {
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
+ /**
+ * Retrieve the package name of the application that currently controls
+ * the {@link android.media.MediaRecorder.AudioSource#HOTWORD} input.
+ * @return The package name of the application that controls the input
+ * or null if no package currently controls it.
+ */
+ public String getCurrentHotwordInputPackageName() {
+ return mHotwordAudioInputPackage;
+ }
+
+ /**
+ * Handle the change of state of the HOTWORD input.
+ *
+ * When the {@link android.media.MediaRecorder.AudioSource#HOTWORD} input is
+ * in use, send a broadcast to alert the new state and store the name of the current
+ * package that controls the input in mHotwordAudioInputPackage.
+ * @param listening Whether the input is being listened to.
+ */
+ public void handleHotwordInput(boolean listening) {
+ synchronized (mHotwordInputLock) {
+ Intent broadcastIntent = new Intent(Intent.ACTION_HOTWORD_INPUT_CHANGED);
+ String[] packages = mContext.getPackageManager().getPackagesForUid(
+ Binder.getCallingUid());
+ if (packages.length > 0) {
+ if (listening) {
+ mHotwordAudioInputPackage = packages[0];
+ }
+ broadcastIntent.putExtra(Intent.EXTRA_CURRENT_PACKAGE_NAME, packages[0]);
+ }
+ broadcastIntent.putExtra(Intent.EXTRA_HOTWORD_INPUT_STATE,
+ listening ? AudioRecord.RECORDSTATE_RECORDING :
+ AudioRecord.RECORDSTATE_STOPPED);
+ // Set the currently listening package to null if listening has stopped.
+ if (!listening) {
+ mHotwordAudioInputPackage = null;
+ }
+ sendBroadcastToAll(broadcastIntent, Manifest.permission.CAPTURE_AUDIO_HOTWORD);
+ }
+ }
+
/** @see AudioManager#forceVolumeControlStream(int) */
public void forceVolumeControlStream(int streamType, IBinder cb) {
synchronized(mForceControlStreamLock) {
@@ -1503,11 +1708,15 @@ public class AudioService extends IAudioService.Stub {
}
private void sendBroadcastToAll(Intent intent) {
+ sendBroadcastToAll(intent, null);
+ }
+
+ private void sendBroadcastToAll(Intent intent, String receiverPermission) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
final long ident = Binder.clearCallingIdentity();
try {
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL, receiverPermission);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2938,9 +3147,18 @@ public class AudioService extends IAudioService.Stub {
synchronized (mConnectedDevices) {
synchronized (mA2dpAvrcpLock) {
mA2dp = (BluetoothA2dp) proxy;
+ if (mConnectedBTDevicesList.size() > 0) {
+ Log.d(TAG,"A2dp connection list not empty, purge it, size " +
+ mConnectedBTDevicesList.size());
+ mConnectedBTDevicesList.clear();
+ }
+ //In Dual A2dp, we can have two devices connected
deviceList = mA2dp.getConnectedDevices();
- if (deviceList.size() > 0) {
- btDevice = deviceList.get(0);
+ Log.d(TAG, "onServiceConnected: A2dp Service connected: " +
+ deviceList.size());
+ for (int i = 0; i < deviceList.size(); i++) {
+ //Add the device in Connected list
+ btDevice = deviceList.get(i);
int state = mA2dp.getConnectionState(btDevice);
int delay = checkSendBecomingNoisyIntent(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
@@ -3038,6 +3256,10 @@ public class AudioService extends IAudioService.Stub {
case BluetoothProfile.A2DP:
synchronized (mConnectedDevices) {
synchronized (mA2dpAvrcpLock) {
+ Log.d(TAG,"mConnectedBTDevicesList size " + mConnectedBTDevicesList.size());
+ if (mConnectedBTDevicesList.size() > 0) {
+ mConnectedBTDevicesList.clear();
+ }
// Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices
for (int i = 0; i < mConnectedDevices.size(); i++) {
DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
@@ -3394,10 +3616,16 @@ public class AudioService extends IAudioService.Stub {
if (DEBUG_VOL)
Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
return AudioSystem.STREAM_MUSIC;
- } else {
+ } else {
+ if (mVolumeKeysControlRingStream) {
if (DEBUG_VOL)
Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
return AudioSystem.STREAM_RING;
+ } else {
+ if (DEBUG_VOL)
+ Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC b/c default");
+ return AudioSystem.STREAM_MUSIC;
+ }
}
} else if (isAfMusicActiveRecently(0)) {
if (DEBUG_VOL)
@@ -3432,9 +3660,16 @@ public class AudioService extends IAudioService.Stub {
if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
return AudioSystem.STREAM_MUSIC;
} else {
- if (DEBUG_VOL) Log.v(TAG,
- "getActiveStreamType: using STREAM_NOTIFICATION as default");
- return AudioSystem.STREAM_NOTIFICATION;
+ if (mVolumeKeysControlRingStream) {
+ if (DEBUG_VOL)
+ Log.v(TAG,
+ "getActiveStreamType: using STREAM_NOTIFICATION as default");
+ return AudioSystem.STREAM_NOTIFICATION;
+ } else {
+ if (DEBUG_VOL)
+ Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC b/c default");
+ return AudioSystem.STREAM_MUSIC;
+ }
}
}
break;
@@ -3593,10 +3828,41 @@ public class AudioService extends IAudioService.Stub {
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
{
- int delay;
+ int delay = 0;
if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
throw new IllegalArgumentException("invalid profile " + profile);
}
+ /*check the state of the currnt device*/
+ if (state == BluetoothA2dp.STATE_CONNECTING) {
+ Log.d(TAG, "Device is still connecting ");
+ return delay;
+ }
+ if ((mConnectedBTDevicesList.contains(device) &&
+ (state == BluetoothA2dp.STATE_CONNECTED))) {
+ Log.d(TAG, "Device conn is updated again, ignore ");
+ return delay;
+ }
+ if (!mConnectedBTDevicesList.contains(device) &&
+ (state == BluetoothA2dp.STATE_CONNECTED)) {
+ /*add the device in the list*/
+ Log.d(TAG, "Add new connected device in the list: " + device);
+ mConnectedBTDevicesList.add(device);
+ if (mConnectedBTDevicesList.size() > 1) {
+ Log.d(TAG, "Second device connected, add new device ");
+ return delay;
+ }
+ } else if ((state == BluetoothA2dp.STATE_DISCONNECTED) ||
+ (state == BluetoothA2dp.STATE_DISCONNECTING)) {
+ Log.d(TAG, "Device is getting disconnected: " + device);
+ if (mConnectedBTDevicesList.contains(device)) {
+ Log.d(TAG, "Remove the BT device ");
+ mConnectedBTDevicesList.remove(device);
+ }
+ if (mConnectedBTDevicesList.size() > 0) {
+ Log.d(TAG, "Not all are disconnected ");
+ return delay;
+ }
+ }
synchronized (mConnectedDevices) {
if (profile == BluetoothProfile.A2DP) {
delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
@@ -4480,6 +4746,10 @@ public class AudioService extends IAudioService.Stub {
Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
+ mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.VOLUME_LINK_NOTIFICATION), false, this);
+ mContentResolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.VOLUME_KEYS_CONTROL_RING_STREAM), false, this);
}
@Override
@@ -4498,6 +4768,17 @@ public class AudioService extends IAudioService.Stub {
setRingerModeInt(getRingerModeInternal(), false);
}
readDockAudioSettings(mContentResolver);
+
+ boolean linkNotificationWithVolume = Settings.Secure.getInt(mContentResolver,
+ Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1;
+ if (linkNotificationWithVolume != mLinkNotificationWithVolume) {
+ mLinkNotificationWithVolume = linkNotificationWithVolume;
+ createStreamStates();
+ updateStreamVolumeAlias(true, TAG);
+ }
+ mVolumeKeysControlRingStream = CMSettings.System.getIntForUser(mContentResolver,
+ CMSettings.System.VOLUME_KEYS_CONTROL_RING_STREAM, 1,
+ UserHandle.USER_CURRENT) == 1;
}
}
}
@@ -4610,11 +4891,12 @@ public class AudioService extends IAudioService.Stub {
// introduction of a delay for transient disconnections of docks when
// power is rapidly turned off/on, this message will be canceled if
// we reconnect the dock under a preset delay
- makeA2dpDeviceUnavailableLater(address, BTA2DP_DOCK_TIMEOUT_MILLIS);
+ makeA2dpDeviceUnavailableLater(btDevice.getAddress(), BTA2DP_DOCK_TIMEOUT_MILLIS);
// the next time isConnected is evaluated, it will be false for the dock
}
} else {
- makeA2dpDeviceUnavailableNow(address);
+ Log.d(TAG, "All devices are disconneted, update Policymanager ");
+ makeA2dpDeviceUnavailableNow(btDevice.getAddress());
}
synchronized (mCurAudioRoutes) {
if (mCurAudioRoutes.bluetoothName != null) {
@@ -4624,21 +4906,24 @@ public class AudioService extends IAudioService.Stub {
}
}
} else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+ //This function is not implemented
+ mA2dpConnectedDevice = "BluetoothA2dp"; // Add this String
if (btDevice.isBluetoothDock()) {
// this could be a reconnection after a transient disconnection
cancelA2dpDeviceTimeout();
- mDockAddress = address;
+ mDockAddress = mA2dpConnectedDevice;
} else {
// this could be a connection of another A2DP device before the timeout of
// a dock: cancel the dock timeout, and make the dock unavailable now
if(hasScheduledA2dpDockTimeout()) {
cancelA2dpDeviceTimeout();
- makeA2dpDeviceUnavailableNow(mDockAddress);
+ makeA2dpDeviceUnavailableNow(btDevice.getAddress());
}
}
- makeA2dpDeviceAvailable(address, btDevice.getName());
+ makeA2dpDeviceAvailable(btDevice.getAddress(), btDevice.getName());
+ //Updated the Router for a2dp device
synchronized (mCurAudioRoutes) {
- String name = btDevice.getAliasName();
+ String name = mA2dpConnectedDevice;
if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
mCurAudioRoutes.bluetoothName = name;
sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
@@ -4655,6 +4940,7 @@ public class AudioService extends IAudioService.Stub {
Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state);
}
if (btDevice == null) {
+ Log.d(TAG, "onSetA2dpSourceConnectionState device is null"); //gasati
return;
}
String address = btDevice.getAddress();
@@ -4738,8 +5024,14 @@ public class AudioService extends IAudioService.Stub {
// Called synchronized on mConnectedDevices
private int checkSendBecomingNoisyIntent(int device, int state) {
int delay = 0;
+ if (mConnectedBTDevicesList.size() > 1) {
+ Log.d(TAG, "checkSendBecomingNoisyIntent on state: " + state);
+ return delay;
+ }
+
if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
int devices = 0;
+ Log.d(TAG, "checkSendBecomingNoisyIntent update the noise");
for (int i = 0; i < mConnectedDevices.size(); i++) {
int dev = mConnectedDevices.valueAt(i).mDeviceType;
if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
@@ -4793,12 +5085,18 @@ public class AudioService extends IAudioService.Stub {
connType = AudioRoutesInfo.MAIN_HEADSET;
intent.setAction(Intent.ACTION_HEADSET_PLUG);
intent.putExtra("microphone", 1);
+ if (state == 1) {
+ startMusicPlayer();
+ }
} else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
device == AudioSystem.DEVICE_OUT_LINE) {
/*do apps care about line-out vs headphones?*/
connType = AudioRoutesInfo.MAIN_HEADPHONES;
intent.setAction(Intent.ACTION_HEADSET_PLUG);
intent.putExtra("microphone", 0);
+ if (state == 1) {
+ startMusicPlayer();
+ }
} else if (device == AudioSystem.DEVICE_OUT_HDMI ||
device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
connType = AudioRoutesInfo.MAIN_HDMI;
@@ -4831,6 +5129,23 @@ public class AudioService extends IAudioService.Stub {
}
}
+ private void startMusicPlayer() {
+ boolean launchPlayer = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.HEADSET_CONNECT_PLAYER, 0, UserHandle.USER_CURRENT) != 0;
+ TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+
+ if (launchPlayer && !tm.isInCall()) {
+ try {
+ Intent playerIntent = new Intent(Intent.ACTION_MAIN);
+ playerIntent.addCategory(Intent.CATEGORY_APP_MUSIC);
+ playerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(playerIntent);
+ } catch (ActivityNotFoundException | IllegalArgumentException e) {
+ Log.w(TAG, "No music player Activity could be found");
+ }
+ }
+ }
+
private void onSetWiredDeviceConnectionState(int device, int state, String address,
String deviceName, String caller) {
if (DEBUG_DEVICES) {
@@ -4962,10 +5277,12 @@ public class AudioService extends IAudioService.Stub {
int config;
switch (dockState) {
case Intent.EXTRA_DOCK_STATE_DESK:
- config = AudioSystem.FORCE_BT_DESK_DOCK;
+ config = mForceAnalogDeskDock ? AudioSystem.FORCE_ANALOG_DOCK :
+ AudioSystem.FORCE_BT_DESK_DOCK;
break;
case Intent.EXTRA_DOCK_STATE_CAR:
- config = AudioSystem.FORCE_BT_CAR_DOCK;
+ config = mForceAnalogCarDock ? AudioSystem.FORCE_ANALOG_DOCK :
+ AudioSystem.FORCE_BT_CAR_DOCK;
break;
case Intent.EXTRA_DOCK_STATE_LE_DESK:
config = AudioSystem.FORCE_ANALOG_DOCK;
@@ -5086,6 +5403,8 @@ public class AudioService extends IAudioService.Stub {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
UserManagerService.getInstance().setSystemControlledUserRestriction(
UserManager.DISALLOW_RECORD_AUDIO, false, userId);
+ } else if (action.equals(Intent.ACTION_SHUTDOWN)) {
+ AudioSystem.setParameters("dev_shutdown=true");
}
}
} // end class AudioServiceBroadcastReceiver
@@ -5159,6 +5478,18 @@ public class AudioService extends IAudioService.Stub {
mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
}
+ public void setRemoteControlClientPlayItem(long uid, int scope) {
+ mMediaFocusControl.setRemoteControlClientPlayItem(uid, scope);
+ }
+
+ public void getRemoteControlClientNowPlayingEntries() {
+ mMediaFocusControl.getRemoteControlClientNowPlayingEntries();
+ }
+
+ public void setRemoteControlClientBrowsedPlayer() {
+ mMediaFocusControl.setRemoteControlClientBrowsedPlayer();
+ }
+
@Override
public void setRemoteStreamVolume(int index) {
enforceVolumeController("set the remote stream volume");
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index f72b598..af880bd 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -335,6 +335,9 @@ public class MediaFocusControl implements OnFinished {
private static final int MSG_RCDISPLAY_INIT_INFO = 9;
private static final int MSG_REEVALUATE_RCD = 10;
private static final int MSG_UNREGISTER_MEDIABUTTONINTENT = 11;
+ private static final int MSG_RCC_SET_BROWSED_PLAYER = 12;
+ private static final int MSG_RCC_SET_PLAY_ITEM = 13;
+ private static final int MSG_RCC_GET_NOW_PLAYING_ENTRIES = 14;
// sendMsg() flags
/** If the msg is already queued, replace it with this one. */
@@ -382,6 +385,22 @@ public class MediaFocusControl implements OnFinished {
(IRemoteVolumeObserver)msg.obj /* rvo */);
break;
+ case MSG_RCC_SET_PLAY_ITEM:
+ Log.d(TAG, "MSG_RCC_SET_PLAY_ITEM: "+ ((Long)msg.obj).longValue());
+ onSetRemoteControlClientPlayItem(msg.arg2 /* scope */,
+ ((Long)msg.obj).longValue() /* uid */);
+ break;
+
+ case MSG_RCC_GET_NOW_PLAYING_ENTRIES:
+ Log.d(TAG, "MSG_RCC_GET_NOW_PLAYING_ENTRIES: ");
+ onGetRemoteControlClientNowPlayingEntries();
+ break;
+
+ case MSG_RCC_SET_BROWSED_PLAYER:
+ Log.d(TAG, "MSG_RCC_SET_BROWSED_PLAYER: ");
+ onSetRemoteControlClientBrowsedPlayer();
+ break;
+
case MSG_RCDISPLAY_INIT_INFO:
// msg.obj is guaranteed to be non null
onRcDisplayInitInfo((IRemoteControlDisplay)msg.obj /*newRcd*/,
@@ -2052,6 +2071,66 @@ public class MediaFocusControl implements OnFinished {
}
}
+ public void setRemoteControlClientPlayItem(long uid, int scope) {
+ sendMsg(mEventHandler, MSG_RCC_SET_PLAY_ITEM, SENDMSG_REPLACE, 0 /* arg1 */,
+ scope /* arg2*/, new Long(uid) /* obj */, 0 /* delay */);
+ }
+
+ private void onSetRemoteControlClientPlayItem(int scope, Long uid) {
+ Log.d(TAG, "onSetRemoteControlClientPlayItem: "+ uid);
+ synchronized(mCurrentRcLock) {
+ if (mCurrentRcClient != null) {
+ try {
+ mCurrentRcClient.setPlayItem(scope, uid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Current valid remote client is dead: "+e);
+ mCurrentRcClient = null;
+ }
+ }
+ }
+ }
+
+ public void getRemoteControlClientNowPlayingEntries() {
+ sendMsg(mEventHandler, MSG_RCC_GET_NOW_PLAYING_ENTRIES, SENDMSG_REPLACE,
+ 0 /* arg1 */, 0 /* arg2 ignored*/, 0 /* obj */, 0 /* delay */);
+ }
+
+ private void onGetRemoteControlClientNowPlayingEntries() {
+ Log.d(TAG, "onGetRemoteControlClientNowPlayingEntries: ");
+ synchronized(mCurrentRcLock) {
+ if (mCurrentRcClient != null) {
+ try {
+ mCurrentRcClient.getNowPlayingEntries();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Current valid remote client is dead: "+e);
+ mCurrentRcClient = null;
+ }
+ }
+ }
+ }
+
+ public void setRemoteControlClientBrowsedPlayer() {
+ Log.d(TAG, "setRemoteControlClientBrowsedPlayer: ");
+ sendMsg(mEventHandler, MSG_RCC_SET_BROWSED_PLAYER, SENDMSG_REPLACE, 0/* arg1 */,
+ 0 /* arg2 ignored*/, 0 /* obj */, 0 /* delay */);
+ }
+
+ private void onSetRemoteControlClientBrowsedPlayer() {
+ Log.d(TAG, "onSetRemoteControlClientBrowsedPlayer: ");
+ PlayerRecord prse = mPRStack.peek();
+ if (prse.getRcc() == null) {
+ Log.d(TAG, "can not proceed with setBrowsedPlayer");
+ } else {
+ Log.d(TAG, "proceed with setBrowsedPlayer");
+ try {
+ Log.d(TAG, "Calling setBrowsedPlayer");
+ prse.getRcc().setBrowsedPlayer();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Current valid remote client is dead: "+ e);
+ }
+ }
+ }
+
// handler for MSG_RCC_NEW_VOLUME_OBS
private void onRegisterVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
synchronized(mPRStack) {
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index a9eaeee..89569ec 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -31,6 +31,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.INetworkManagementService;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.util.Slog;
import com.android.server.net.BaseNetworkObserver;
@@ -90,7 +91,12 @@ public class Nat464Xlat extends BaseNetworkObserver {
(nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
// Only support clat on mobile and wifi for now, because these are the only IPv6-only
// networks we can connect to.
- return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
+ boolean doXlat = SystemProperties.getBoolean("persist.net.doxlat",true);
+ if(!doXlat) {
+ Slog.i(TAG, "Android Xlat is disabled");
+ }
+ return connected && !hasIPv4Address && (((netType == TYPE_MOBILE) && doXlat )
+ || netType == TYPE_WIFI);
}
/**
@@ -125,6 +131,7 @@ public class Nat464Xlat extends BaseNetworkObserver {
}
try {
+ mNMService.unregisterObserver(this);
mNMService.registerObserver(this);
} catch(RemoteException e) {
Slog.e(TAG, "startClat: Can't register interface observer for clat on " + mNetwork);
@@ -233,16 +240,12 @@ public class Nat464Xlat extends BaseNetworkObserver {
}
@Override
- public void interfaceLinkStateChanged(String iface, boolean up) {
+ public void addressUpdated(String iface, LinkAddress clatAddress) {
// Called by the InterfaceObserver on its own thread, so can race with stop().
- if (isStarted() && up && mIface.equals(iface)) {
+ if (isStarted() && mIface.equals(iface) && clatAddress != null) {
Slog.i(TAG, "interface " + iface + " is up, mIsRunning " + mIsRunning + "->true");
if (!mIsRunning) {
- LinkAddress clatAddress = getLinkAddress(iface);
- if (clatAddress == null) {
- return;
- }
mIsRunning = true;
maybeSetIpv6NdOffload(mBaseIface, false);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index c1aaf07..3472db2 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -36,11 +36,17 @@ import android.net.Network;
import android.net.NetworkInfo;
import android.net.NetworkUtils;
import android.net.RouteInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiDevice;
+import android.net.wifi.WifiManager;
import android.os.Binder;
+import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
+import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.SystemProperties;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -64,9 +70,22 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
+
/**
* @hide
@@ -137,12 +156,27 @@ public class Tethering extends BaseNetworkObserver {
private boolean mUsbTetherRequested; // true if USB tethering should be started
// when RNDIS is enabled
+ // Once STA established connection to hostapd, it will be added
+ // to mL2ConnectedDeviceMap. Then after deviceinfo update from dnsmasq,
+ // it will be added to mConnectedDeviceMap
+ private HashMap<String, WifiDevice> mL2ConnectedDeviceMap = new HashMap<String, WifiDevice>();
+ private HashMap<String, WifiDevice> mConnectedDeviceMap = new HashMap<String, WifiDevice>();
+ private static final String dhcpLocation = "/data/misc/dhcp/dnsmasq.leases";
+
+ // Device name polling interval(ms) and max times
+ private static final int DNSMASQ_POLLING_INTERVAL = 1000;
+ private static final int DNSMASQ_POLLING_MAX_TIMES = 10;
+
+ private long mWiFiApInactivityTimeout;
+ private final Handler mHandler;
+
public Tethering(Context context, INetworkManagementService nmService,
INetworkStatsService statsService, Looper looper) {
mContext = context;
mNMService = nmService;
mStatsService = statsService;
mLooper = looper;
+ mHandler = new Handler(mLooper);
mPublicSync = new Object();
@@ -158,6 +192,8 @@ public class Tethering extends BaseNetworkObserver {
filter.addAction(UsbManager.ACTION_USB_STATE);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
+
mContext.registerReceiver(mStateReceiver, filter);
filter = new IntentFilter();
@@ -190,11 +226,17 @@ public class Tethering extends BaseNetworkObserver {
void updateConfiguration() {
String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
com.android.internal.R.array.config_tether_usb_regexs);
- String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_tether_wifi_regexs);
+ String[] tetherableWifiRegexs;
String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs);
+ if (SystemProperties.getInt("persist.fst.rate.upgrade.en", 0) == 1) {
+ tetherableWifiRegexs = new String[] {"bond0"};
+ } else {
+ tetherableWifiRegexs = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_tether_wifi_regexs);
+ }
+
int ifaceTypes[] = mContext.getResources().getIntArray(
com.android.internal.R.array.config_tether_upstream_types);
Collection<Integer> upstreamIfaceTypes = new ArrayList();
@@ -234,6 +276,18 @@ public class Tethering extends BaseNetworkObserver {
sm = new TetherInterfaceSM(iface, mLooper, usb);
mIfaces.put(iface, sm);
sm.start();
+ if (isWifi(iface)) {
+ // check if the user has specified an inactivity timeout for wifi AP and
+ // if so schedule the timeout
+ final WifiManager wm =
+ (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ final WifiConfiguration apConfig = wm.getWifiApConfiguration();
+ mWiFiApInactivityTimeout =
+ apConfig != null ? apConfig.wifiApInactivityTimeout : 0;
+ if (mWiFiApInactivityTimeout > 0 && mL2ConnectedDeviceMap.size() == 0) {
+ scheduleInactivityTimeout();
+ }
+ }
}
} else {
if (isUsb(iface)) {
@@ -243,6 +297,9 @@ public class Tethering extends BaseNetworkObserver {
} else if (sm != null) {
sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
mIfaces.remove(iface);
+ if (isWifi(iface)) {
+ cancelInactivityTimeout();
+ }
}
}
}
@@ -326,6 +383,194 @@ public class Tethering extends BaseNetworkObserver {
}
}
+ public List<WifiDevice> getTetherConnectedSta() {
+ Iterator it;
+ List<WifiDevice> TetherConnectedStaList = new ArrayList<WifiDevice>();
+
+ if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_softap_extention)) {
+ it = mConnectedDeviceMap.keySet().iterator();
+ while(it.hasNext()) {
+ String key = (String)it.next();
+ WifiDevice device = (WifiDevice)mConnectedDeviceMap.get(key);
+ if (VDBG) {
+ Log.d(TAG, "getTetherConnectedSta: addr=" + key + " name=" + device.deviceName);
+ }
+ TetherConnectedStaList.add(device);
+ }
+ }
+
+ return TetherConnectedStaList;
+ }
+
+ private void sendTetherConnectStateChangedBroadcast() {
+ if (!getConnectivityManager().isTetheringSupported()) return;
+
+ Intent broadcast = new Intent(ConnectivityManager.TETHER_CONNECT_STATE_CHANGED);
+ broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
+ mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
+ }
+
+ private boolean readDeviceInfoFromDnsmasq(WifiDevice device) {
+ boolean result = false;
+ FileInputStream fstream = null;
+ String line;
+
+ try {
+ fstream = new FileInputStream(dhcpLocation);
+ DataInputStream in = new DataInputStream(fstream);
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+
+ while ((null != (line = br.readLine())) && (line.length() != 0)) {
+ String[] fields = line.split(" ");
+
+ // 949295 00:0a:f5:6a:bf:70 192.168.43.32 android-93de88df9ec61bac *
+ if (fields.length > 3) {
+ String addr = fields[1];
+ String name = fields[3];
+
+ if (addr.equals(device.deviceAddress)) {
+ device.deviceName = name;
+ result = true;
+ break;
+ }
+ }
+ }
+ } catch (IOException ex) {
+ Log.e(TAG, "readDeviceNameFromDnsmasq: " + ex);
+ } finally {
+ if (fstream != null) {
+ try {
+ fstream.close();
+ } catch (IOException ex) {}
+ }
+ }
+
+ return result;
+ }
+
+ private final Runnable mDisableWifiApRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (VDBG) Log.d(TAG, "Turning off hotpost due to inactivity");
+ final WifiManager wifiManager =
+ (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ wifiManager.setWifiApEnabled(null, false);
+ }
+ };
+
+ private void scheduleInactivityTimeout() {
+ if (mWiFiApInactivityTimeout > 0) {
+ if (VDBG) Log.d(TAG, "scheduleInactivityTimeout: " + mWiFiApInactivityTimeout);
+ mHandler.removeCallbacks(mDisableWifiApRunnable);
+ mHandler.postDelayed(mDisableWifiApRunnable, mWiFiApInactivityTimeout);
+ }
+ }
+
+ private void cancelInactivityTimeout() {
+ if (VDBG) Log.d(TAG, "cancelInactivityTimeout");
+ mHandler.removeCallbacks(mDisableWifiApRunnable);
+ }
+
+ /*
+ * DnsmasqThread is used to read the Device info from dnsmasq.
+ */
+ private static class DnsmasqThread extends Thread {
+ private final Tethering mTethering;
+ private int mInterval;
+ private int mMaxTimes;
+ private WifiDevice mDevice;
+
+ public DnsmasqThread(Tethering tethering, WifiDevice device,
+ int interval, int maxTimes) {
+ super("Tethering");
+ mTethering = tethering;
+ mInterval = interval;
+ mMaxTimes = maxTimes;
+ mDevice = device;
+ }
+
+ public void run() {
+ boolean result = false;
+
+ try {
+ while (mMaxTimes > 0) {
+ result = mTethering.readDeviceInfoFromDnsmasq(mDevice);
+ if (result) {
+ if (DBG) Log.d(TAG, "Successfully poll device info for " + mDevice.deviceAddress);
+ break;
+ }
+
+ mMaxTimes --;
+ Thread.sleep(mInterval);
+ }
+ } catch (Exception ex) {
+ result = false;
+ Log.e(TAG, "Pulling " + mDevice.deviceAddress + "error" + ex);
+ }
+
+ if (!result) {
+ if (DBG) Log.d(TAG, "Pulling timeout, suppose STA uses static ip " + mDevice.deviceAddress);
+ }
+
+ // When STA uses static ip, device info will be unavaiable from dnsmasq,
+ // thus no matter the result is success or failure, we will broadcast the event.
+ // But if the device is not in L2 connected state, it means the hostapd connection is
+ // disconnected before dnsmasq get device info, so in this case, don't broadcast
+ // connection event.
+ WifiDevice other = mTethering.mL2ConnectedDeviceMap.get(mDevice.deviceAddress);
+ if (other != null && other.deviceState == WifiDevice.CONNECTED) {
+ mTethering.mConnectedDeviceMap.put(mDevice.deviceAddress, mDevice);
+ mTethering.sendTetherConnectStateChangedBroadcast();
+ } else {
+ if (DBG) Log.d(TAG, "Device " + mDevice.deviceAddress + "already disconnected, ignoring");
+ }
+ }
+ }
+
+ public void interfaceMessageRecevied(String message) {
+ // if softap extension feature not enabled, do nothing
+ if (!mContext.getResources().getBoolean(com.android.internal.R.bool.config_softap_extention)) {
+ return;
+ }
+
+ if (DBG) Log.d(TAG, "interfaceMessageRecevied: message=" + message);
+
+ try {
+ WifiDevice device = new WifiDevice(message);
+
+ if (device.deviceState == WifiDevice.CONNECTED) {
+ mL2ConnectedDeviceMap.put(device.deviceAddress, device);
+
+ // When hostapd reported STA-connection event, it is possible that device
+ // info can't fetched from dnsmasq, then we start a thread to poll the
+ // device info, the thread will exit after device info avaiable.
+ // For static ip case, dnsmasq don't hold the device info, thus thread
+ // will exit after a timeout.
+ if (readDeviceInfoFromDnsmasq(device)) {
+ mConnectedDeviceMap.put(device.deviceAddress, device);
+ sendTetherConnectStateChangedBroadcast();
+ } else {
+ if (DBG) Log.d(TAG, "Starting poll device info for " + device.deviceAddress);
+ new DnsmasqThread(this, device,
+ DNSMASQ_POLLING_INTERVAL, DNSMASQ_POLLING_MAX_TIMES).start();
+ }
+ cancelInactivityTimeout();
+ } else if (device.deviceState == WifiDevice.DISCONNECTED) {
+ mL2ConnectedDeviceMap.remove(device.deviceAddress);
+ mConnectedDeviceMap.remove(device.deviceAddress);
+ sendTetherConnectStateChangedBroadcast();
+ // schedule inactivity timeout if non-zero and no more devices are connected
+ if (mWiFiApInactivityTimeout > 0 && mL2ConnectedDeviceMap.size() == 0) {
+ scheduleInactivityTimeout();
+ }
+ }
+ } catch (IllegalArgumentException ex) {
+ Log.e(TAG, "WifiDevice IllegalArgument: " + ex);
+ }
+ }
+
public int tether(String iface) {
if (DBG) Log.d(TAG, "Tethering " + iface);
TetherInterfaceSM sm = null;
@@ -453,7 +698,12 @@ public class Tethering extends BaseNetworkObserver {
if (mLastNotificationId != 0) {
if (mLastNotificationId == icon) {
- return;
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_softap_extention)
+ || icon != com.android.internal.R.drawable.stat_sys_tether_wifi) {
+ // if softap extension feature is on, allow to update icon else return.
+ return;
+ }
}
notificationManager.cancelAsUser(null, mLastNotificationId,
UserHandle.ALL);
@@ -526,6 +776,14 @@ public class Tethering extends BaseNetworkObserver {
}
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
updateConfiguration();
+ } else if(action.equals(WIFI_AP_STATE_CHANGED_ACTION)){
+ int wifiApState = intent.getIntExtra("wifi_state", WIFI_AP_STATE_DISABLED);
+ if (DBG) Log.d(TAG, "WIFI_AP_STATE_CHANGED: wifiApState=" + wifiApState);
+ if(wifiApState == WIFI_AP_STATE_ENABLED ||
+ wifiApState == WIFI_AP_STATE_DISABLED) {
+ mConnectedDeviceMap.clear();
+ mL2ConnectedDeviceMap.clear();
+ }
}
}
}
@@ -644,6 +902,10 @@ public class Tethering extends BaseNetworkObserver {
if (tm != null) {
secureSetting = tm.getTetherApnRequired();
}
+ // Allow override of TETHER_DUN_REQUIRED via prop
+ int prop = SystemProperties.getInt("persist.sys.dun.override", -1);
+ secureSetting = ((prop < 3) && (prop >= 0)) ? prop : secureSetting;
+
synchronized (mPublicSync) {
// 2 = not set, 0 = DUN not required, 1 = DUN required
if (secureSetting != 2) {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index e15bca6..1925ed3 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -22,6 +22,8 @@ import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
+import android.content.Context;
+import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -53,18 +55,16 @@ class AutomaticBrightnessController {
// auto-brightness adjustment setting.
private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
- // Period of time in which to consider light samples in milliseconds.
- private static final int AMBIENT_LIGHT_HORIZON = 10000;
-
// Hysteresis constraints for brightening or darkening.
// The recent lux must have changed by at least this fraction relative to the
// current ambient lux before a change will be considered.
private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
- // The intercept used for the weighting calculation. This is used in order to keep all possible
- // weighting values positive.
- private static final int WEIGHTING_INTERCEPT = AMBIENT_LIGHT_HORIZON;
+ // Threshold (in lux) to select between normal and fast debounce time.
+ // If the difference between last sample and weighted value is larger than this value,
+ // fast debounce is used.
+ private static final float BRIGHTENING_FAST_THRESHOLD = 1000f;
// How long the current sensor reading is assumed to be valid beyond the current time.
// This provides a bit of prediction, as well as ensures that the weight for the last sample is
@@ -124,6 +124,7 @@ class AutomaticBrightnessController {
// when adapting to brighter or darker environments. This parameter controls how quickly
// brightness changes occur in response to an observed change in light level that exceeds the
// hysteresis threshold.
+ private final long mBrighteningLightFastDebounceConfig;
private final long mBrighteningLightDebounceConfig;
private final long mDarkeningLightDebounceConfig;
@@ -193,11 +194,26 @@ class AutomaticBrightnessController {
private int mBrightnessAdjustmentSampleOldBrightness;
private float mBrightnessAdjustmentSampleOldGamma;
- public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
+ // Night mode color temperature adjustments
+ private final LiveDisplayController mLiveDisplay;
+
+ // Period of time in which to consider light samples in milliseconds.
+ private int mAmbientLightHorizon;
+
+ // The intercept used for the weighting calculation. This is used in order to keep all possible
+ // weighting values positive.
+ private int mWeightingIntercept;
+
+ private final Context mContext;
+
+ public AutomaticBrightnessController(Context context, Callbacks callbacks, Looper looper,
SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, long brighteningLightDebounceConfig,
- long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig) {
+ long brighteningLightFastDebounceConfig, long darkeningLightDebounceConfig,
+ boolean resetAmbientLuxAfterWarmUpConfig,
+ int ambientLightHorizon, LiveDisplayController ldc) {
+ mContext = context;
mCallbacks = callbacks;
mTwilight = LocalServices.getService(TwilightManager.class);
mSensorManager = sensorManager;
@@ -208,11 +224,15 @@ class AutomaticBrightnessController {
mDozeScaleFactor = dozeScaleFactor;
mLightSensorRate = lightSensorRate;
mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
+ mBrighteningLightFastDebounceConfig = brighteningLightFastDebounceConfig;
mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
+ mLiveDisplay = ldc;
+ mAmbientLightHorizon = ambientLightHorizon;
+ mWeightingIntercept = ambientLightHorizon;
mHandler = new AutomaticBrightnessHandler(looper);
- mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate);
+ mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon);
if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
@@ -256,6 +276,7 @@ class AutomaticBrightnessController {
pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig);
+ pw.println(" mBrighteningLightFastDebounceConfig=" + mBrighteningLightFastDebounceConfig);
pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig);
pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig);
@@ -303,13 +324,14 @@ class AutomaticBrightnessController {
private void handleLightSensorEvent(long time, float lux) {
mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
+ if (DEBUG) Slog.d(TAG, "handleLightSensorEvent: time=" + time + ", lux=" + lux);
applyLightSensorMeasurement(time, lux);
updateAmbientLux(time);
}
private void applyLightSensorMeasurement(long time, float lux) {
mRecentLightSamples++;
- mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON);
+ mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
mAmbientLightRingBuffer.push(time, lux);
// Remember this sample value.
@@ -360,17 +382,17 @@ class AutomaticBrightnessController {
return sum / totalWeight;
}
- private static float calculateWeight(long startDelta, long endDelta) {
+ private float calculateWeight(long startDelta, long endDelta) {
return weightIntegral(endDelta) - weightIntegral(startDelta);
}
- // Evaluates the integral of y = x + WEIGHTING_INTERCEPT. This is always positive for the
+ // Evaluates the integral of y = x + mWeightIntercept. This is always positive for the
// horizon we're looking at and provides a non-linear weighting for light samples.
- private static float weightIntegral(long x) {
- return x * (x * 0.5f + WEIGHTING_INTERCEPT);
+ private float weightIntegral(long x) {
+ return x * (x * 0.5f + mWeightingIntercept);
}
- private long nextAmbientLightBrighteningTransition(long time) {
+ private long nextAmbientLightBrighteningTransition(long time, float ambientLux) {
final int N = mAmbientLightRingBuffer.size();
long earliestValidTime = time;
for (int i = N - 1; i >= 0; i--) {
@@ -379,10 +401,13 @@ class AutomaticBrightnessController {
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
}
- return earliestValidTime + mBrighteningLightDebounceConfig;
+
+ long debounceDelay = mLastObservedLux - ambientLux > BRIGHTENING_FAST_THRESHOLD
+ ? mBrighteningLightFastDebounceConfig : mBrighteningLightDebounceConfig;
+ return earliestValidTime + debounceDelay;
}
- private long nextAmbientLightDarkeningTransition(long time) {
+ private long nextAmbientLightDarkeningTransition(long time, float ambientLux) {
final int N = mAmbientLightRingBuffer.size();
long earliestValidTime = time;
for (int i = N - 1; i >= 0; i--) {
@@ -396,7 +421,7 @@ class AutomaticBrightnessController {
private void updateAmbientLux() {
long time = SystemClock.uptimeMillis();
- mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON);
+ mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
updateAmbientLux(time);
}
@@ -426,13 +451,12 @@ class AutomaticBrightnessController {
updateAutoBrightness(true);
}
- long nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
- long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
float ambientLux = calculateAmbientLux(time);
+ long nextBrightenTransition = nextAmbientLightBrighteningTransition(time, ambientLux);
+ long nextDarkenTransition = nextAmbientLightDarkeningTransition(time, ambientLux);
if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time
|| ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) {
- setAmbientLux(ambientLux);
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: "
+ ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
@@ -440,9 +464,10 @@ class AutomaticBrightnessController {
+ ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer
+ ", mAmbientLux=" + mAmbientLux);
}
+ setAmbientLux(ambientLux);
updateAutoBrightness(true);
- nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
- nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
+ nextBrightenTransition = nextAmbientLightBrighteningTransition(time, ambientLux);
+ nextDarkenTransition = nextAmbientLightDarkeningTransition(time, ambientLux);
}
long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition);
// If one of the transitions is ready to occur, but the total weighted ambient lux doesn't
@@ -478,6 +503,9 @@ class AutomaticBrightnessController {
}
}
+ // Update LiveDisplay with the current lux
+ mLiveDisplay.updateLiveDisplay(mAmbientLux);
+
if (USE_TWILIGHT_ADJUSTMENT) {
TwilightState state = mTwilight.getCurrentState();
if (state != null && state.isNight()) {
@@ -653,8 +681,8 @@ class AutomaticBrightnessController {
private int mEnd;
private int mCount;
- public AmbientLightRingBuffer(long lightSensorRate) {
- mCapacity = (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate);
+ public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) {
+ mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate);
mRingLux = new float[mCapacity];
mRingTime = new long[mCapacity];
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6a6570b..e8a857b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -287,6 +287,8 @@ public final class DisplayManagerService extends SystemService {
mOnlyCore = onlyCore;
}
+ mDisplayPowerController.systemReady();
+
mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 7b49530..ae596cb 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -19,6 +19,7 @@ package com.android.server.display;
import com.android.internal.app.IBatteryStats;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
+import com.android.server.lights.LightsManager;
import android.animation.Animator;
import android.animation.ObjectAnimator;
@@ -124,6 +125,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Battery stats.
private final IBatteryStats mBatteryStats;
+ // The lights service.
+ private final LightsManager mLights;
+
// The sensor manager.
private final SensorManager mSensorManager;
@@ -247,6 +251,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// The controller for the automatic brightness level.
private AutomaticBrightnessController mAutomaticBrightnessController;
+ // The controller for LiveDisplay
+ private final LiveDisplayController mLiveDisplayController;
+
// Animators.
private ObjectAnimator mColorFadeOnAnimator;
private ObjectAnimator mColorFadeOffAnimator;
@@ -262,11 +269,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mCallbacks = callbacks;
mBatteryStats = BatteryStatsService.getService();
+ mLights = LocalServices.getService(LightsManager.class);
mSensorManager = sensorManager;
mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
mBlanker = blanker;
mContext = context;
+ mLiveDisplayController = new LiveDisplayController(context, handler.getLooper());
+
final Resources resources = context.getResources();
final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
@@ -307,10 +317,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
long brighteningLightDebounce = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
+ long brighteningLightFastDebounce = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessBrighteningLightFastDebounce);
long darkeningLightDebounce = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
+ int ambientLightHorizon = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
if (mUseSoftwareAutoBrightnessConfig) {
int[] lux = resources.getIntArray(
@@ -343,12 +357,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (bottom < screenBrightnessRangeMinimum) {
screenBrightnessRangeMinimum = bottom;
}
- mAutomaticBrightnessController = new AutomaticBrightnessController(this,
+ mAutomaticBrightnessController = new AutomaticBrightnessController(mContext, this,
handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
- brighteningLightDebounce, darkeningLightDebounce,
- autoBrightnessResetAmbientLuxAfterWarmUp);
+ brighteningLightDebounce, brighteningLightFastDebounce,
+ darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
+ ambientLightHorizon, mLiveDisplayController);
}
}
@@ -573,6 +588,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else {
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
+ mProximity = PROXIMITY_UNKNOWN;
}
if (mScreenOffBecauseOfProximity
&& mProximity != PROXIMITY_POSITIVE) {
@@ -595,6 +611,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Use zero brightness when screen is off.
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
+ mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(brightness);
+ mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(brightness);
+ }
+
+ // Disable button lights when dozing
+ if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
+ mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(PowerManager.BRIGHTNESS_OFF);
+ mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(PowerManager.BRIGHTNESS_OFF);
}
// Configure auto-brightness.
@@ -692,6 +716,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
+ // Update LiveDisplay now
+ mLiveDisplayController.updateLiveDisplay();
+
// Determine whether the display is ready for use in the newly requested state.
// Note that we do not wait for the brightness ramp animation to complete before
// reporting the display is ready because we only need to ensure the screen is in the
@@ -1131,6 +1158,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController.dump(pw);
}
+ mLiveDisplayController.dump(pw);
}
private static String proximityToString(int state) {
@@ -1192,6 +1220,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
}
+ void systemReady() {
+ mLiveDisplayController.systemReady();
+ }
+
private final class DisplayControllerHandler extends Handler {
public DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
diff --git a/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java b/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java
new file mode 100644
index 0000000..1be474b
--- /dev/null
+++ b/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.server.display;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import android.media.RemoteDisplay;
+import android.os.Handler;
+import android.util.Slog;
+import android.content.Context;
+
+class ExtendedRemoteDisplayHelper {
+ private static final String TAG = "ExtendedRemoteDisplayHelper";
+
+ // ExtendedRemoteDisplay class
+ // ExtendedRemoteDisplay is an enhanced RemoteDisplay. It has
+ // similar interface as RemoteDisplay class
+ private static Class sExtRemoteDisplayClass;
+
+ // Method object for the API ExtendedRemoteDisplay.Listen
+ // ExtendedRemoteDisplay.Listen has the same API signature as
+ // RemoteDisplay.Listen except for an additional argument to pass the
+ // Context
+ private static Method sExtRemoteDisplayListen;
+
+ // Method Object for the API ExtendedRemoteDisplay.Dispose
+ // ExtendedRemoteDisplay.Dispose follows the same API signature as
+ // RemoteDisplay.Dispose
+ private static Method sExtRemoteDisplayDispose;
+
+ static {
+ //Check availability of ExtendedRemoteDisplay runtime
+ try {
+ sExtRemoteDisplayClass = Class.forName("com.qualcomm.wfd.ExtendedRemoteDisplay");
+ } catch (Throwable t) {
+ Slog.i(TAG, "ExtendedRemoteDisplay Not available.");
+ }
+
+ if(sExtRemoteDisplayClass != null) {
+ // If ExtendedRemoteDisplay is available find the methods
+ Slog.i(TAG, "ExtendedRemoteDisplay Is available. Find Methods");
+ try {
+ Class args[] = {
+ String.class,
+ RemoteDisplay.Listener.class,
+ Handler.class, Context.class
+ };
+ sExtRemoteDisplayListen = sExtRemoteDisplayClass.getDeclaredMethod("listen", args);
+ } catch (Throwable t) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.listen Not available.");
+ }
+
+ try {
+ Class args[] = {};
+ sExtRemoteDisplayDispose = sExtRemoteDisplayClass.getDeclaredMethod("dispose", args);
+ } catch (Throwable t) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.dispose Not available.");
+ }
+ }
+ }
+
+ /**
+ * Starts listening for displays to be connected on the specified interface.
+ *
+ * @param iface The interface address and port in the form "x.x.x.x:y".
+ * @param listener The listener to invoke
+ * when displays are connected or disconnected.
+ * @param handler The handler on which to invoke the listener.
+ * @param context The current service context
+ * */
+ public static Object listen(String iface, RemoteDisplay.Listener listener,
+ Handler handler, Context context)
+ {
+ Object extRemoteDisplay = null;
+ Slog.i(TAG, "ExtendedRemoteDisplay.listen");
+
+ if(sExtRemoteDisplayListen != null && sExtRemoteDisplayDispose != null){
+ try {
+ extRemoteDisplay = sExtRemoteDisplayListen.invoke(null,
+ iface, listener, handler, context);
+ } catch (InvocationTargetException e) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.listen - InvocationTargetException");
+ Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(e);
+ }
+ } catch (IllegalAccessException e) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.listen -IllegalAccessException");
+ e.printStackTrace();
+ }
+ }
+ return extRemoteDisplay;
+ }
+
+ /**
+ * Disconnects the remote display and stops listening for new connections.
+ */
+ public static void dispose(Object extRemoteDisplay) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.dispose");
+ try{
+ sExtRemoteDisplayDispose.invoke(extRemoteDisplay);
+ } catch (InvocationTargetException e) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.dispose - InvocationTargetException");
+ Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(e);
+ }
+ } catch (IllegalAccessException e) {
+ Slog.i(TAG, "ExtendedRemoteDisplay.dispose-IllegalAccessException");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Checks if ExtendedRemoteDisplay is available
+ */
+ public static boolean isAvailable()
+ {
+ if(sExtRemoteDisplayClass != null &&
+ sExtRemoteDisplayDispose != null &&
+ sExtRemoteDisplayListen != null) {
+ Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Available.");
+ return true;
+ }
+ Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Not Available.");
+ return false;
+ }
+}
diff --git a/services/core/java/com/android/server/display/LiveDisplayController.java b/services/core/java/com/android/server/display/LiveDisplayController.java
new file mode 100644
index 0000000..938f1a0
--- /dev/null
+++ b/services/core/java/com/android/server/display/LiveDisplayController.java
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.display;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.PowerManagerInternal;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.MathUtils;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+import com.android.server.accessibility.DisplayAdjustmentUtils;
+import com.android.server.twilight.TwilightListener;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
+
+import cyanogenmod.hardware.CMHardwareManager;
+import cyanogenmod.providers.CMSettings;
+import cyanogenmod.util.ColorUtils;
+
+import java.io.PrintWriter;
+
+public class LiveDisplayController {
+
+ private static final String TAG = "LiveDisplay";
+
+ private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 1;
+
+ private static final int OFF_TEMPERATURE = 6500;
+
+ public static final int MODE_OFF = 0;
+ public static final int MODE_NIGHT = 1;
+ public static final int MODE_AUTO = 2;
+ public static final int MODE_OUTDOOR = 3;
+ public static final int MODE_DAY = 4;
+
+ private int mColorTemperature = OFF_TEMPERATURE;
+ private float mCurrentLux = 0.0f;
+
+ private int mHintCounter;
+ private int mMode;
+
+ private boolean mOutdoorMode;
+ private boolean mColorEnhancement;
+ private boolean mLowPower;
+
+ private final Context mContext;
+ private final Handler mHandler;
+
+ private CMHardwareManager mHardware;
+
+ private int mDayTemperature;
+ private int mNightTemperature;
+
+ private boolean mUseOutdoorMode;
+ private boolean mUseColorEnhancement;
+ private boolean mUseLowPower;
+
+ private boolean mOutdoorModeIsSelfManaged;
+
+ private final float[] mColorAdjustment = new float[] { 1.0f, 1.0f, 1.0f };
+ private final float[] mRGB = new float[] { 0.0f, 0.0f, 0.0f };
+
+ private TwilightManager mTwilightManager;
+ private boolean mSunset = false;
+
+ private SettingsObserver mObserver;
+
+ private ValueAnimator mAnimator;
+
+ private int mDefaultDayTemperature;
+ private int mDefaultNightTemperature;
+ private int mDefaultOutdoorLux;
+
+ private boolean mInitialized = false;
+
+ private static final int MSG_UPDATE_LIVE_DISPLAY = 1;
+
+ // Display postprocessing can have power impact. Disable it if powersave mode is on.
+ private boolean mLowPerformance = false;
+ private PowerManagerInternal.LowPowerModeListener mLowPowerModeListener =
+ new PowerManagerInternal.LowPowerModeListener() {
+ @Override
+ public void onLowPowerModeChanged(boolean enabled) {
+ mLowPerformance = enabled;
+ updateLiveDisplay(mCurrentLux);
+ }
+ };
+
+ LiveDisplayController(Context context, Looper looper) {
+ mContext = context;
+ mHandler = new LiveDisplayHandler(looper);
+ }
+
+ void systemReady() {
+ mHardware = CMHardwareManager.getInstance(mContext);
+
+ mDefaultDayTemperature = mContext.getResources().getInteger(
+ org.cyanogenmod.platform.internal.R.integer.config_dayColorTemperature);
+ mDefaultNightTemperature = mContext.getResources().getInteger(
+ org.cyanogenmod.platform.internal.R.integer.config_nightColorTemperature);
+ mDefaultOutdoorLux = mContext.getResources().getInteger(
+ org.cyanogenmod.platform.internal.R.integer.config_outdoorAmbientLux);
+
+ // Counter used to determine when we should tell the user about this feature.
+ // If it's not used after 3 sunsets, we'll show the hint once.
+ mHintCounter = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.LIVE_DISPLAY_HINTED,
+ -3,
+ UserHandle.USER_CURRENT);
+
+ mUseOutdoorMode =
+ mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT);
+ mOutdoorModeIsSelfManaged = mUseOutdoorMode ?
+ mHardware.isSunlightEnhancementSelfManaged() : false;
+
+ mUseLowPower =
+ mHardware.isSupported(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT);
+ if (mUseLowPower) {
+ mLowPower = mHardware.get(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT);
+ }
+
+ mUseColorEnhancement =
+ mHardware.isSupported(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT);
+ if (mUseColorEnhancement) {
+ mColorEnhancement =
+ mHardware.get(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT);
+ }
+
+ updateSettings();
+
+ mObserver = new SettingsObserver();
+ mObserver.register(true);
+
+ PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
+ pmi.registerLowPowerModeObserver(mLowPowerModeListener);
+ mLowPerformance = pmi.getLowPowerModeEnabled();
+
+ mTwilightManager = LocalServices.getService(TwilightManager.class);
+ mTwilightManager.registerListener(mTwilightListener, mHandler);
+
+ mInitialized = true;
+ }
+
+ private void updateSettings() {
+ mDayTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_TEMPERATURE_DAY,
+ mDefaultDayTemperature,
+ UserHandle.USER_CURRENT);
+ mNightTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_TEMPERATURE_NIGHT,
+ mDefaultNightTemperature,
+ UserHandle.USER_CURRENT);
+ mMode = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_TEMPERATURE_MODE,
+ MODE_OFF,
+ UserHandle.USER_CURRENT);
+
+ // Clear the hint forever
+ if (mMode != MODE_OFF) {
+ saveUserHint(1);
+ }
+
+ // Manual color adjustment will be set as a space separated string of float values
+ String colorAdjustmentTemp = CMSettings.System.getStringForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_COLOR_ADJUSTMENT,
+ UserHandle.USER_CURRENT);
+ String[] colorAdjustment = colorAdjustmentTemp == null ?
+ null : colorAdjustmentTemp.split(" ");
+ if (colorAdjustment == null || colorAdjustment.length != 3) {
+ colorAdjustment = new String[] { "1.0", "1.0", "1.0" };
+ }
+ try {
+ mColorAdjustment[0] = Float.parseFloat(colorAdjustment[0]);
+ mColorAdjustment[1] = Float.parseFloat(colorAdjustment[1]);
+ mColorAdjustment[2] = Float.parseFloat(colorAdjustment[2]);
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, e.getMessage(), e);
+ mColorAdjustment[0] = 1.0f;
+ mColorAdjustment[1] = 1.0f;
+ mColorAdjustment[2] = 1.0f;
+ }
+
+ updateLiveDisplay(mCurrentLux);
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private final Uri DISPLAY_TEMPERATURE_DAY_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY);
+ private final Uri DISPLAY_TEMPERATURE_NIGHT_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT);
+ private final Uri DISPLAY_TEMPERATURE_MODE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_MODE);
+ private final Uri DISPLAY_AUTO_OUTDOOR_MODE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE);
+ private final Uri DISPLAY_LOW_POWER_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_LOW_POWER);
+ private final Uri DISPLAY_COLOR_ENHANCE_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_COLOR_ENHANCE);
+ private final Uri DISPLAY_COLOR_ADJUSTMENT_URI =
+ CMSettings.System.getUriFor(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT);
+ public SettingsObserver() {
+ super(mHandler);
+ }
+
+ public void register(boolean register) {
+ final ContentResolver cr = mContext.getContentResolver();
+ if (register) {
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_DAY_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_NIGHT_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_MODE_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_AUTO_OUTDOOR_MODE_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_LOW_POWER_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_COLOR_ENHANCE_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(DISPLAY_COLOR_ADJUSTMENT_URI, false, this, UserHandle.USER_ALL);
+ } else {
+ cr.unregisterContentObserver(this);
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateSettings();
+ }
+ }
+
+ public void updateLiveDisplay() {
+ updateLiveDisplay(mCurrentLux);
+ }
+
+ synchronized void updateLiveDisplay(float lux) {
+ mCurrentLux = lux;
+ mHandler.removeMessages(MSG_UPDATE_LIVE_DISPLAY);
+ mHandler.sendEmptyMessage(MSG_UPDATE_LIVE_DISPLAY);
+ }
+
+ private synchronized void updateColorTemperature(TwilightState twilight) {
+ int temperature = mDayTemperature;
+ if (mMode == MODE_OFF || mLowPerformance) {
+ temperature = OFF_TEMPERATURE;
+ } else if (mMode == MODE_NIGHT) {
+ temperature = mNightTemperature;
+ } else if (mMode == MODE_AUTO) {
+ temperature = getTwilightK(twilight);
+ }
+
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ mAnimator = ValueAnimator.ofInt(mColorTemperature, temperature);
+ mAnimator.setDuration(Math.abs(mColorTemperature - temperature) / 2);
+ mAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setDisplayTemperature((Integer)animation.getAnimatedValue());
+ }
+ });
+ mAnimator.start();
+ }
+
+ private synchronized void setDisplayTemperature(int temperature) {
+ mColorTemperature = temperature;
+
+ final float[] rgb = ColorUtils.temperatureToRGB(temperature);
+
+ if (!mLowPerformance) {
+ rgb[0] *= mColorAdjustment[0];
+ rgb[1] *= mColorAdjustment[1];
+ rgb[2] *= mColorAdjustment[2];
+ }
+
+ if (rgb[0] == mRGB[0] && rgb[1] == mRGB[1] && rgb[2] == mRGB[2]) {
+ // no changes
+ return;
+ }
+
+ System.arraycopy(rgb, 0, mRGB, 0, 3);
+
+ Slog.d(TAG, "Adjust display temperature to " + temperature +
+ "K [r=" + rgb[0] + " g=" + rgb[1] + " b=" + rgb[2] + "]");
+
+ if (mHardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION)) {
+ // Clear this out in case of an upgrade
+ CMSettings.Secure.putStringForUser(mContext.getContentResolver(),
+ CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX,
+ null,
+ UserHandle.USER_CURRENT);
+
+ int max = mHardware.getDisplayColorCalibrationMax();
+ mHardware.setDisplayColorCalibration(new int[] {
+ (int) Math.ceil(rgb[0] * max),
+ (int) Math.ceil(rgb[1] * max),
+ (int) Math.ceil(rgb[2] * max)
+ });
+ screenRefresh();
+ } else {
+ String colorMatrixStr = null;
+ if (rgb[0] != 1.0f || rgb[1] != 1.0f || rgb[2] != 1.0f) {
+ final Float[] colorMatrix = new Float[] {
+ rgb[0], 0.0f, 0.0f, 0.0f,
+ 0.0f, rgb[1], 0.0f, 0.0f,
+ 0.0f, 0.0f, rgb[2], 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f };
+ colorMatrixStr = TextUtils.join(" ", colorMatrix);
+ }
+
+ // For GPU color transform, go thru DisplayAdjustmentUtils in
+ // order to coexist with accessibility settings
+ CMSettings.Secure.putStringForUser(mContext.getContentResolver(),
+ CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX,
+ colorMatrixStr,
+ UserHandle.USER_CURRENT);
+
+ DisplayAdjustmentUtils.applyAdjustments(mContext, UserHandle.USER_CURRENT);
+ }
+ }
+
+ /**
+ * Outdoor mode is optionally enabled when ambient lux > 10000 and it's daytime
+ * Melt faces!
+ *
+ * TODO: Use the camera or RGB sensor to determine if it's really sunlight
+ */
+ private synchronized void updateOutdoorMode(TwilightState twilight) {
+ if (!mUseOutdoorMode) {
+ return;
+ }
+
+ boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE,
+ 1,
+ UserHandle.USER_CURRENT) == 1;
+
+ boolean enabled;
+ if (mOutdoorModeIsSelfManaged) {
+ enabled = value;
+ } else {
+ enabled = !mLowPerformance &&
+ ((mMode == MODE_OUTDOOR) ||
+ (value && mMode == MODE_AUTO &&
+ twilight != null && !twilight.isNight() &&
+ mCurrentLux > mDefaultOutdoorLux));
+ }
+
+ if (enabled == mOutdoorMode) {
+ return;
+ }
+
+ mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, enabled);
+ mOutdoorMode = enabled;
+ }
+
+ /**
+ * Color enhancement is optional, but can look bad with night mode
+ */
+ private synchronized void updateColorEnhancement(TwilightState twilight) {
+ if (!mUseColorEnhancement) {
+ return;
+ }
+
+ boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_COLOR_ENHANCE,
+ 1,
+ UserHandle.USER_CURRENT) == 1;
+
+ boolean enabled = !mLowPerformance && value &&
+ !(mMode == MODE_NIGHT ||
+ (mMode == MODE_AUTO && twilight != null && twilight.isNight()));
+
+ if (enabled == mColorEnhancement) {
+ return;
+ }
+
+ mHardware.set(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT, enabled);
+ mColorEnhancement = enabled;
+ }
+
+ /**
+ * Adaptive backlight / low power mode. Turn it off when under very bright light.
+ */
+ private synchronized void updateLowPowerMode() {
+ if (!mUseLowPower) {
+ return;
+ }
+
+ boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.DISPLAY_LOW_POWER,
+ 1,
+ UserHandle.USER_CURRENT) == 1;
+
+ boolean enabled = value && (mCurrentLux < mDefaultOutdoorLux);
+
+ if (enabled == mLowPower) {
+ return;
+ }
+
+ mHardware.set(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT, enabled);
+ mLowPower = enabled;
+ }
+
+ /**
+ * Where is the sun anyway? This calculation determines day or night, and scales
+ * the value around sunset/sunrise for a smooth transition.
+ *
+ * @param now
+ * @param sunset
+ * @param sunrise
+ * @return float between 0 and 1
+ */
+ private static float adj(long now, long sunset, long sunrise) {
+ if (sunset < 0 || sunrise < 0
+ || now < sunset || now > sunrise) {
+ return 1.0f;
+ }
+
+ if (now < sunset + TWILIGHT_ADJUSTMENT_TIME) {
+ return MathUtils.lerp(1.0f, 0.0f,
+ (float)(now - sunset) / TWILIGHT_ADJUSTMENT_TIME);
+ }
+
+ if (now > sunrise - TWILIGHT_ADJUSTMENT_TIME) {
+ return MathUtils.lerp(1.0f, 0.0f,
+ (float)(sunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
+ }
+
+ return 0.0f;
+ }
+
+ /**
+ * Determine the color temperature we should use for the display based on
+ * the position of the sun.
+ *
+ * @param state
+ * @return color temperature in Kelvin
+ */
+ private int getTwilightK(TwilightState state) {
+ float adjustment = 1.0f;
+
+ if (state != null) {
+ final long now = System.currentTimeMillis();
+ adjustment = adj(now, state.getYesterdaySunset(), state.getTodaySunrise()) *
+ adj(now, state.getTodaySunset(), state.getTomorrowSunrise());
+ }
+
+ return (int)MathUtils.lerp(mNightTemperature, mDayTemperature, adjustment);
+ }
+
+ /**
+ * Tell SurfaceFlinger to repaint the screen. This is called after updating
+ * hardware registers for display calibration to have an immediate effect.
+ */
+ private static void screenRefresh() {
+ try {
+ final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+ if (flinger != null) {
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ flinger.transact(1004, data, null, 0);
+ data.recycle();
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to refresh screen", ex);
+ }
+ }
+
+ private void saveUserHint(int value) {
+ if (mHintCounter == value) {
+ return;
+ }
+ CMSettings.System.putIntForUser(mContext.getContentResolver(),
+ CMSettings.System.LIVE_DISPLAY_HINTED,
+ value,
+ UserHandle.USER_CURRENT);
+ mHintCounter = value;
+ }
+
+ /**
+ * Show a friendly notification to the user about the potential benefits of decreasing
+ * blue light at night. Do this only once if the feature has not been used after
+ * three sunsets. It would be great to enable this by default, but we don't want
+ * the change of screen color to be considered a "bug" by a user who doesn't
+ * understand what's happening.
+ *
+ * @param state
+ */
+ private void updateUserHint(TwilightState state) {
+ // check if we should send the hint only once after sunset
+ if (state == null || mHintCounter == 1) {
+ return;
+ }
+ boolean transition = state.isNight() && !mSunset;
+ mSunset = state.isNight();
+ if (!transition) {
+ return;
+ }
+
+ if (mHintCounter <= 0) {
+ mHintCounter++;
+ saveUserHint(mHintCounter);
+ }
+ if (mHintCounter == 0) {
+ //show the notification and don't come back here
+ final Intent intent = new Intent("android.settings.LIVEDISPLAY_SETTINGS");
+ PendingIntent result = PendingIntent.getActivity(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ Notification.Builder builder = new Notification.Builder(mContext)
+ .setContentTitle(mContext.getResources().getString(
+ org.cyanogenmod.platform.internal.R.string.live_display_title))
+ .setContentText(mContext.getResources().getString(
+ org.cyanogenmod.platform.internal.R.string.live_display_hint))
+ .setSmallIcon(org.cyanogenmod.platform.internal.R.drawable.ic_livedisplay_notif)
+ .setStyle(new Notification.BigTextStyle().bigText(mContext.getResources()
+ .getString(
+ org.cyanogenmod.platform.internal.R.string.live_display_hint)))
+ .setContentIntent(result)
+ .setAutoCancel(true);
+
+ NotificationManager nm =
+ (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notifyAsUser(null, 1, builder.build(), UserHandle.CURRENT);
+
+ saveUserHint(1);
+ }
+ }
+
+ private final TwilightListener mTwilightListener = new TwilightListener() {
+ @Override
+ public void onTwilightStateChanged() {
+ updateLiveDisplay(mCurrentLux);
+ }
+ };
+
+ private final class LiveDisplayHandler extends Handler {
+ public LiveDisplayHandler(Looper looper) {
+ super(looper, null, true /*async*/);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_LIVE_DISPLAY:
+ if (!mInitialized) {
+ break;
+ }
+ TwilightState twilight = mTwilightManager.getCurrentState();
+
+ updateColorTemperature(twilight);
+ updateOutdoorMode(twilight);
+ updateColorEnhancement(twilight);
+ updateLowPowerMode();
+ updateUserHint(twilight);
+
+ boolean transition = mMode == MODE_AUTO &&
+ mColorTemperature != mDayTemperature &&
+ mColorTemperature != mNightTemperature;
+ if (transition) {
+ // fire again in a minute
+ sendEmptyMessageDelayed(MSG_UPDATE_LIVE_DISPLAY,
+ DateUtils.MINUTE_IN_MILLIS);
+ }
+ break;
+ }
+ }
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println();
+ pw.println("LiveDisplay Controller Configuration:");
+ pw.println(" mDayTemperature=" + mDayTemperature);
+ pw.println(" mNightTemperature=" + mNightTemperature);
+ pw.println();
+ pw.println("LiveDisplay Controller State:");
+ pw.println(" mMode=" + (mLowPerformance ? "disabled in powersave mode" : mMode));
+ pw.println(" mSunset=" + mSunset);
+ pw.println(" mColorTemperature=" + mColorTemperature);
+ pw.println(" mColorAdjustment=[r: " + mColorAdjustment[0] + " g:" + mColorAdjustment[1] +
+ " b:" + mColorAdjustment[2] + "]");
+ pw.println(" mRGB=[r:" + mRGB[0] + " g:" + mRGB[1] + " b:" + mRGB[2] + "]");
+ pw.println(" mOutdoorMode=" + (mUseOutdoorMode ? mOutdoorMode : "N/A"));
+ pw.println(" mColorEnhancement=" + (mUseColorEnhancement ? mColorEnhancement : "N/A"));
+ pw.println(" mLowPower=" + (mUseLowPower ? mLowPower : "N/A"));
+ }
+}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 088d96e..7a28f48 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -58,6 +58,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
+ SurfaceControl.BUILT_IN_DISPLAY_ID_TERTIARY,
};
private final SparseArray<LocalDisplayDevice> mDevices =
@@ -191,6 +192,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
for (int j = 0; j < colorTransforms.size(); j++) {
if (colorTransforms.get(j).getColorTransform() == info.colorTransform) {
existingMode = true;
+ if (i == activeDisplayInfo) {
+ activeColorTransform = colorTransforms.get(j);
+ }
break;
}
}
diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java
index 8932ca0..239f8cd 100644
--- a/services/core/java/com/android/server/display/WifiDisplayController.java
+++ b/services/core/java/com/android/server/display/WifiDisplayController.java
@@ -137,6 +137,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
// Number of connection retries remaining.
private int mConnectionRetriesLeft;
+ // The Extended remote display that is listening on the connection.
+ // Created after the Wifi P2P network is connected.
+ private Object mExtRemoteDisplay;
+
// The remote display that is listening on the connection.
// Created after the Wifi P2P network is connected.
private RemoteDisplay mRemoteDisplay;
@@ -565,11 +569,19 @@ final class WifiDisplayController implements DumpUtils.Dump {
// Step 1. Before we try to connect to a new device, tell the system we
// have disconnected from the old one.
- if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) {
- Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface
+ if ((mRemoteDisplay != null || mExtRemoteDisplay != null) &&
+ mConnectedDevice != mDesiredDevice) {
+ Slog.i(TAG, "Stopped listening for RTSP connection on "
+ + mRemoteDisplayInterface
+ " from Wifi display: " + mConnectedDevice.deviceName);
- mRemoteDisplay.dispose();
+ if(mRemoteDisplay != null) {
+ mRemoteDisplay.dispose();
+ } else if(mExtRemoteDisplay != null) {
+ ExtendedRemoteDisplayHelper.dispose(mExtRemoteDisplay);
+ }
+
+ mExtRemoteDisplay = null;
mRemoteDisplay = null;
mRemoteDisplayInterface = null;
mRemoteDisplayConnected = false;
@@ -717,7 +729,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
}
// Step 6. Listen for incoming RTSP connection.
- if (mConnectedDevice != null && mRemoteDisplay == null) {
+ if (mConnectedDevice != null && mRemoteDisplay == null &&
+ mExtRemoteDisplay== null) {
Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo);
if (addr == null) {
Slog.i(TAG, "Failed to get local interface address for communicating "
@@ -736,7 +749,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
Slog.i(TAG, "Listening for RTSP connection on " + iface
+ " from Wifi display: " + mConnectedDevice.deviceName);
- mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() {
+ RemoteDisplay.Listener listener = new RemoteDisplay.Listener() {
@Override
public void onDisplayConnected(Surface surface,
int width, int height, int flags, int session) {
@@ -775,7 +788,14 @@ final class WifiDisplayController implements DumpUtils.Dump {
handleConnectionFailure(false);
}
}
- }, mHandler, mContext.getOpPackageName());
+ };
+ if(ExtendedRemoteDisplayHelper.isAvailable()){
+ mExtRemoteDisplay = ExtendedRemoteDisplayHelper.listen(iface,
+ listener, mHandler, mContext);
+ } else {
+ mRemoteDisplay = RemoteDisplay.listen(iface, listener,
+ mHandler, mContext.getOpPackageName());
+ }
// Use extended timeout value for certification, as some tests require user inputs
int rtspTimeout = mWifiDisplayCertMode ?
@@ -910,7 +930,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
@Override
public void run() {
if (mConnectedDevice != null
- && mRemoteDisplay != null && !mRemoteDisplayConnected) {
+ && (mRemoteDisplay != null || mExtRemoteDisplay != null)
+ && !mRemoteDisplayConnected) {
Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after "
+ RTSP_TIMEOUT_SECONDS + " seconds: "
+ mConnectedDevice.deviceName);
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 8813a61..c986e74 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -18,6 +18,7 @@ package com.android.server.dreams;
import static android.Manifest.permission.BIND_DREAM_SERVICE;
+import android.view.WindowManagerPolicy;
import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
import com.android.server.SystemService;
@@ -84,6 +85,7 @@ public final class DreamManagerService extends SystemService {
private boolean mCurrentDreamIsWaking;
private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ private int mLidState = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
public DreamManagerService(Context context) {
super(context);
@@ -150,6 +152,12 @@ public final class DreamManagerService extends SystemService {
}
}
+ private boolean isDozingInternal() {
+ synchronized (mLock) {
+ return mCurrentDreamIsDozing;
+ }
+ }
+
private void requestDreamInternal() {
// Ask the power manager to nap. It will eventually call back into
// startDream() if/when it is appropriate to start dreaming.
@@ -219,7 +227,8 @@ public final class DreamManagerService extends SystemService {
}
synchronized (mLock) {
- if (mCurrentDreamToken == token && mCurrentDreamCanDoze) {
+ if (mCurrentDreamToken == token && mCurrentDreamCanDoze
+ && mLidState != WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED) {
mCurrentDreamDozeScreenState = screenState;
mCurrentDreamDozeScreenBrightness = screenBrightness;
mPowerManagerInternal.setDozeOverrideFromDreamManager(
@@ -232,6 +241,43 @@ public final class DreamManagerService extends SystemService {
}
}
+ private int getLidStateInternal() {
+ return mLidState;
+ }
+
+ private void setLidStateInternal(int state) {
+ synchronized (mLock) {
+ if (mLidState == state) {
+ return;
+ }
+ mLidState = state;
+ }
+ switch (state) {
+ case WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT:
+ // do nothing
+ break;
+ case WindowManagerPolicy.WindowManagerFuncs.LID_OPEN:
+ synchronized (mLock) {
+ mPowerManagerInternal.setDozeOverrideFromDreamManager(
+ Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT);
+ }
+ break;
+ case WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED:
+ // mimicing logic from stopDozingInternal(), stop any thing when the lid is closed.
+ synchronized (mLock) {
+ if (mCurrentDreamIsDozing) {
+ mCurrentDreamIsDozing = false;
+ if (mDozeWakeLock.isHeld()) {
+ mDozeWakeLock.release();
+ }
+ mPowerManagerInternal.setDozeOverrideFromDreamManager(
+ Display.STATE_OFF, PowerManager.BRIGHTNESS_OFF);
+ }
+ }
+ break;
+ }
+ }
+
private void stopDozingInternal(IBinder token) {
if (DEBUG) {
Slog.d(TAG, "Dream requested to stop dozing: " + token);
@@ -530,6 +576,18 @@ public final class DreamManagerService extends SystemService {
}
@Override // Binder call
+ public boolean isDozing() {
+ checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isDozingInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public void dream() {
checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
@@ -621,6 +679,30 @@ public final class DreamManagerService extends SystemService {
Binder.restoreCallingIdentity(ident);
}
}
+
+ @Override
+ public void setLidState(int lidState) {
+ checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setLidStateInternal(lidState);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public int getLidState() {
+ checkPermission(Manifest.permission.READ_DREAM_STATE);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return getLidStateInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
}
private final class LocalService extends DreamManagerInternal {
@@ -638,6 +720,11 @@ public final class DreamManagerService extends SystemService {
public boolean isDreaming() {
return isDreamingInternal();
}
+
+ @Override
+ public boolean isDozing() {
+ return isDozingInternal();
+ }
}
private final Runnable mSystemPropertiesChanged = new Runnable() {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index ec7c1c4..6612218 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -19,7 +19,6 @@ package com.android.server.fingerprint;
import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.AppOpsManager;
@@ -30,6 +29,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
@@ -143,12 +143,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
resetFailedAttempts();
}
};
+ private boolean mFingerprintManagerRestrictedToSystemAndOwner;
public FingerprintService(Context context) {
super(context);
mContext = context;
mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
com.android.internal.R.string.config_keyguardComponent)).getPackageName();
+ mFingerprintManagerRestrictedToSystemAndOwner = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_fingerprintRestrictedToSystemAndOwner);
mAppOps = context.getSystemService(AppOpsManager.class);
mPowerManager = mContext.getSystemService(PowerManager.class);
mAlarmManager = mContext.getSystemService(AlarmManager.class);
@@ -582,6 +585,21 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground");
return false;
}
+ if (mFingerprintManagerRestrictedToSystemAndOwner) {
+ try {
+ ApplicationInfo ai = mContext.getPackageManager()
+ .getApplicationInfo(opPackageName, PackageManager.GET_META_DATA);
+ if (ai != null && ai.isSystemApp() && Binder.getCallingUserHandle().isOwner()) {
+ return true;
+ }
+ Slog.w(TAG, "Rejecting " + opPackageName
+ + "(uid: " + uid + ") ; fingerprint restricted to system apps.");
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, opPackageName + " package not found, not allowing fingerprint access.");
+ return false;
+ }
+ return false;
+ }
return true;
}
diff --git a/services/core/java/com/android/server/gesture/GestureInputFilter.java b/services/core/java/com/android/server/gesture/GestureInputFilter.java
new file mode 100644
index 0000000..e40761f
--- /dev/null
+++ b/services/core/java/com/android/server/gesture/GestureInputFilter.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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.gesture;
+
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.Display;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnDoubleTapListener;
+import android.view.IInputFilter;
+import android.view.IInputFilterHost;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+import android.view.OrientationEventListener;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+import java.io.PrintWriter;
+
+/**
+ * A simple input filter that listens for gesture sensor events and converts
+ * them to input events to be injected into the input stream.
+ */
+public class GestureInputFilter implements IInputFilter, GestureDetector.OnGestureListener, OnDoubleTapListener {
+
+ private static final String TAG = "GestureInputFilter";
+ private static final boolean DEBUG = false;
+
+ private IInputFilterHost mHost = null;
+
+ private GestureDetector mGestureDetector;
+ private InputManager mInputManager;
+ private OrientationEventListener mOrientationListener;
+ private final int mScreenWidth, mScreenHeight;
+ private float mGesturePadWidth, mGesturePadHeight;
+ private int mTouchSlop, mOrientation;
+ private Context mContext;
+ private PendingIntent mLongPressPendingIntent;
+ private PendingIntent mDoubleClickPendingIntent;
+
+ public GestureInputFilter(Context context) {
+ mInputManager = InputManager.getInstance();
+ mContext = context;
+ for (int id : mInputManager.getInputDeviceIds()) {
+ InputDevice inputDevice = mInputManager.getInputDevice(id);
+ if ((inputDevice.getSources() & InputDevice.SOURCE_GESTURE_SENSOR)
+ == mInputManager.getInputDevice(id).getSources()) {
+ mGesturePadWidth = inputDevice.getMotionRange(MotionEvent.AXIS_X).getMax();
+ mGesturePadHeight = inputDevice.getMotionRange(MotionEvent.AXIS_Y).getMax();
+ break;
+ }
+ }
+ ViewConfiguration vc = ViewConfiguration.get(context);
+ mTouchSlop = vc.getScaledTouchSlop();
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ mScreenWidth = display.getWidth();
+ mScreenHeight = display.getHeight();
+ mGestureDetector = new GestureDetector(context, this);
+ mGestureDetector.setOnDoubleTapListener(this);
+ mOrientationListener = new OrientationEventListener(context) {
+ @Override
+ public void onOrientationChanged(int orientation) {
+ if (orientation == -1) {
+ return;
+ }
+ mOrientation = (orientation + 45) / 90 * 90;
+ }
+ };
+ }
+
+ /**
+ * Called to enqueue the input event for filtering.
+ * The event must be recycled after the input filter processed it.
+ * This method is guaranteed to be non-reentrant.
+ *
+ * @see InputFilter#filterInputEvent(InputEvent, int)
+ * @param event The input event to enqueue.
+ */
+ // called by the input dispatcher thread
+ public void filterInputEvent(InputEvent event, int policyFlags)
+ throws RemoteException {
+ if (DEBUG) Slog.d(TAG, event.toString());
+
+ try {
+ if (event.getSource() != InputDevice.SOURCE_GESTURE_SENSOR
+ || !(event instanceof MotionEvent)) {
+ try {
+ mHost.sendInputEvent(event, policyFlags);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ return;
+ }
+
+ MotionEvent motionEvent = (MotionEvent) event;
+ mGestureDetector.onTouchEvent(motionEvent);
+ } finally {
+ event.recycle();
+ }
+ }
+
+ // called by the input dispatcher thread
+ public void install(IInputFilterHost host) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "Gesture input filter installed.");
+ }
+ mHost = host;
+ mOrientationListener.enable();
+ }
+
+ // called by the input dispatcher thread
+ public void uninstall() throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "Gesture input filter uninstalled.");
+ }
+ mHost = null;
+ mOrientationListener.disable();
+ mContext = null;
+ }
+
+ // should never be called
+ public IBinder asBinder() {
+ throw new UnsupportedOperationException();
+ }
+
+ // called by a Binder thread
+ public void dump(PrintWriter pw, String prefix) {
+
+ }
+
+ private boolean generateSwipe(MotionEvent e1, MotionEvent e2) {
+ switch (mOrientation) {
+ case 90:
+ Slog.d(TAG, "Adjusting motion for 90 degrees");
+ e1.setLocation(e1.getY(), e1.getX());
+ e2.setLocation(e2.getY(), e2.getX());
+ break;
+ case 180:
+ Slog.d(TAG, "Adjusting motion for 180 degrees");
+ e1.setLocation(mGesturePadWidth - e1.getX(),
+ mGesturePadHeight - e1.getY());
+ e2.setLocation(mGesturePadWidth - e2.getX(),
+ mGesturePadHeight - e2.getY());
+ break;
+ case 270:
+ Slog.d(TAG, "Adjusting motion for 270 degrees");
+ e1.setLocation(mGesturePadHeight - e1.getY(),
+ e1.getX());
+ e2.setLocation(mGesturePadHeight - e2.getY(),
+ e2.getX());
+ break;
+ }
+
+ float deltaX = Math.abs(e1.getX() - e2.getX());
+ float deltaY = Math.abs(e1.getY() - e2.getY());
+
+ if (deltaX < mTouchSlop && deltaY < mTouchSlop) {
+ return false;
+ }
+
+ if (deltaX > deltaY) {
+ e2.setLocation(e2.getX(), e1.getY());
+ } else if (deltaY > deltaX) {
+ e2.setLocation(e1.getX(), e2.getY());
+ }
+
+ float scaleX = mScreenWidth / mGesturePadWidth;
+ float scaleY = mScreenHeight / mGesturePadHeight;
+
+ float magnitudeX = deltaX * scaleX;
+ float magnitudeY = deltaY * scaleY;
+
+ float origX = mScreenWidth / 2;
+ float origY = mScreenHeight / 2;
+ float endX = 0.0f;
+ float endY = 0.0f;
+
+ if (e2.getY() > e1.getY()) {
+ if (DEBUG) Slog.d(TAG, "Detected down motion");
+ // Ensure selection does not occur
+ endX = origX + mTouchSlop + 5;
+ endY = origY + magnitudeY;
+ } else if (e2.getY() < e1.getY()) {
+ if (DEBUG) Slog.d(TAG, "Detected up motion");
+ endX = origX + mTouchSlop + 5;
+ endY = origY - magnitudeY;
+ } else if (e2.getX() > e1.getX()) {
+ if (DEBUG) Slog.d(TAG, "Detected left motion");
+ endX = origX + magnitudeX;
+ endY = origY + mTouchSlop + 5;
+ } else if (e2.getX() < e1.getX()) {
+ if (DEBUG) Slog.d(TAG, "Detected right motion");
+ endX = origX - magnitudeX;
+ endY = origY + mTouchSlop + 5;
+ } else {
+ return false;
+ }
+
+ sendSwipe(origX, origY, endX, endY);
+ return true;
+ }
+
+ private void sendSwipe(float x1, float y1, float x2, float y2) {
+ final long duration = 100;
+ long now = SystemClock.uptimeMillis();
+ final long startTime = now;
+ final long endTime = startTime + duration;
+ sendMotionEvent(MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
+
+ while (now < endTime) {
+ long elapsedTime = now - startTime;
+ float alpha = (float) elapsedTime / duration;
+ sendMotionEvent(MotionEvent.ACTION_MOVE, now,
+ lerp(x1, x2, alpha), lerp(y1, y2, alpha), 1.0f);
+ now = SystemClock.uptimeMillis();
+ }
+ sendMotionEvent(MotionEvent.ACTION_UP, now, x2, y2, 1.0f);
+ }
+
+ private void sendMotionEvent(int action, long when, float x, float y,
+ float pressure) {
+ final float DEFAULT_SIZE = 1.0f;
+ final int DEFAULT_META_STATE = 0;
+ final float DEFAULT_PRECISION_X = 1.0f;
+ final float DEFAULT_PRECISION_Y = 1.0f;
+ final int DEFAULT_DEVICE_ID = 0;
+ final int DEFAULT_EDGE_FLAGS = 0;
+
+ MotionEvent e = MotionEvent.obtain(when, when, action, x, y, pressure,
+ DEFAULT_SIZE, DEFAULT_META_STATE, DEFAULT_PRECISION_X,
+ DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID, DEFAULT_EDGE_FLAGS);
+ e.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ sendInputEvent(e);
+ }
+
+ private void sendInputEvent(InputEvent event) {
+ mInputManager.injectInputEvent(event,
+ InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
+ }
+
+ private static final float lerp(float a, float b, float alpha) {
+ return (b - a) * alpha + a;
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public void onShowPress(MotionEvent e) {
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+ float distanceY) {
+ return false;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ if (mLongPressPendingIntent != null) {
+ try {
+ mLongPressPendingIntent.send();
+ } catch (CanceledException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+ float velocityY) {
+ return generateSwipe(e1, e2);
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (mDoubleClickPendingIntent != null) {
+ try {
+ mDoubleClickPendingIntent.send();
+ return true;
+ } catch (CanceledException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ return false;
+ }
+
+ public void setOnLongPressPendingIntent(PendingIntent pendingIntent) {
+ mLongPressPendingIntent = pendingIntent;
+ }
+
+ public void setOnDoubleClickPendingIntent(PendingIntent pendingIntent) {
+ mDoubleClickPendingIntent = pendingIntent;
+ }
+}
diff --git a/services/core/java/com/android/server/gesture/GestureService.java b/services/core/java/com/android/server/gesture/GestureService.java
new file mode 100644
index 0000000..1a01e41
--- /dev/null
+++ b/services/core/java/com/android/server/gesture/GestureService.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project (Jens Doll)
+ *
+ * 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.gesture;
+
+import android.Manifest;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.gesture.IGestureService;
+import android.util.Slog;
+
+import com.android.server.input.InputManagerService;
+
+/**
+ * A system service to track gesture sensor gestures. This service is
+ * responsible for creating input events from motion events generated by
+ * gesture sensor input hardware:
+ * <li>Installing an input filter to listen for gesture sensor events</li>
+ * <li>Generating input events to be injected into the input stream</li>
+ */
+public class GestureService extends IGestureService.Stub {
+ public static final String TAG = "GestureService";
+ public static final boolean DEBUG = false;
+
+ private Context mContext;
+ private InputManagerService mInputManager;
+ private GestureInputFilter mInputFilter;
+
+ public GestureService(Context context, InputManagerService inputManager) {
+ mContext = context;
+ mInputManager = inputManager;
+ }
+
+ // called by system server
+ public void systemReady() {
+ if (DEBUG) Slog.d(TAG, "Starting Gesture Sensor service");
+ mInputFilter = new GestureInputFilter(mContext);
+ mInputManager.registerSecondaryInputFilter(mInputFilter);
+ }
+
+ public void setOnLongPressPendingIntent(PendingIntent pendingIntent) {
+ mInputFilter.setOnLongPressPendingIntent(pendingIntent);
+ }
+
+ public void setOnDoubleClickPendingIntent(PendingIntent pendingIntent) {
+ mInputFilter.setOnDoubleClickPendingIntent(pendingIntent);
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 0205a20..37326cc 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -97,6 +97,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import cyanogenmod.providers.CMSettings;
import libcore.io.Streams;
import libcore.util.Objects;
@@ -161,8 +162,9 @@ public class InputManagerService extends IInputManager.Stub
// State for the currently installed input filter.
final Object mInputFilterLock = new Object();
- IInputFilter mInputFilter; // guarded by mInputFilterLock
- InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
+ ChainedInputFilterHost mInputFilterHost; // guarded by mInputFilterLock
+ ArrayList<ChainedInputFilterHost> mInputFilterChain =
+ new ArrayList<ChainedInputFilterHost>(); // guarded by mInputFilterLock
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
@@ -197,6 +199,8 @@ public class InputManagerService extends IInputManager.Stub
InputChannel fromChannel, InputChannel toChannel);
private static native void nativeSetPointerSpeed(long ptr, int speed);
private static native void nativeSetShowTouches(long ptr, boolean enabled);
+ private static native void nativeSetStylusIconEnabled(long ptr, boolean enabled);
+ private static native void nativeSetVolumeKeysRotation(long ptr, int mode);
private static native void nativeSetInteractive(long ptr, boolean interactive);
private static native void nativeReloadCalibration(long ptr);
private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
@@ -305,17 +309,22 @@ public class InputManagerService extends IInputManager.Stub
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
+ registerStylusIconEnabledSettingObserver();
+ registerVolumeKeysRotationSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
+ updateVolumeKeysRotationFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
+ updateStylusIconEnabledFromSettings();
+ updateVolumeKeysRotationFromSettings();
}
// TODO(BT) Pass in paramter for bluetooth system
@@ -512,34 +521,71 @@ public class InputManagerService extends IInputManager.Stub
*/
public void setInputFilter(IInputFilter filter) {
synchronized (mInputFilterLock) {
- final IInputFilter oldFilter = mInputFilter;
- if (oldFilter == filter) {
- return; // nothing to do
- }
-
- if (oldFilter != null) {
- mInputFilter = null;
+ if (mInputFilterHost != null) {
mInputFilterHost.disconnectLocked();
+ mInputFilterChain.remove(mInputFilterHost);
mInputFilterHost = null;
- try {
- oldFilter.uninstall();
- } catch (RemoteException re) {
- /* ignore */
- }
}
if (filter != null) {
- mInputFilter = filter;
- mInputFilterHost = new InputFilterHost();
- try {
- filter.install(mInputFilterHost);
- } catch (RemoteException re) {
- /* ignore */
+ ChainedInputFilterHost head = mInputFilterChain.isEmpty() ? null :
+ mInputFilterChain.get(0);
+ mInputFilterHost = new ChainedInputFilterHost(filter, head);
+ mInputFilterHost.connectLocked();
+ mInputFilterChain.add(0, mInputFilterHost);
+ }
+
+ nativeSetInputFilterEnabled(mPtr, !mInputFilterChain.isEmpty());
+ }
+ }
+
+ /**
+ * Registers a secondary input filter. These filters are always behind the "original"
+ * input filter. This ensures that all input events will be filtered by the
+ * {@code AccessibilityManagerService} first.
+ * <p>
+ * <b>Note:</b> Even though this implementation using AIDL interfaces, it is designed to only
+ * provide direct access. Therefore, any filter registering should reside in the
+ * system server DVM only!
+ *
+ * @param filter The input filter to register.
+ */
+ public void registerSecondaryInputFilter(IInputFilter filter) {
+ synchronized (mInputFilterLock) {
+ ChainedInputFilterHost host = new ChainedInputFilterHost(filter, null);
+ if (!mInputFilterChain.isEmpty()) {
+ mInputFilterChain.get(mInputFilterChain.size() - 1).mNext = host;
+ }
+ host.connectLocked();
+ mInputFilterChain.add(host);
+
+ nativeSetInputFilterEnabled(mPtr, !mInputFilterChain.isEmpty());
+ }
+ }
+
+ public void unregisterSecondaryInputFilter(IInputFilter filter) {
+ synchronized (mInputFilterLock) {
+ int index = findInputFilterIndexLocked(filter);
+ if (index >= 0) {
+ ChainedInputFilterHost host = mInputFilterChain.get(index);
+ host.disconnectLocked();
+ if (index >= 1) {
+ mInputFilterChain.get(index - 1).mNext = host.mNext;
}
+ mInputFilterChain.remove(index);
}
- nativeSetInputFilterEnabled(mPtr, filter != null);
+ nativeSetInputFilterEnabled(mPtr, !mInputFilterChain.isEmpty());
+ }
+ }
+
+ private int findInputFilterIndexLocked(IInputFilter filter) {
+ for (int i = 0; i < mInputFilterChain.size(); i++) {
+ if (mInputFilterChain.get(i).mInputFilter == filter) {
+ return i;
+ }
}
+ return -1;
}
@Override // Binder call
@@ -1357,6 +1403,58 @@ public class InputManagerService extends IInputManager.Stub
return result;
}
+ public void updateStylusIconEnabledFromSettings() {
+ int enabled = getStylusIconEnabled(0);
+ nativeSetStylusIconEnabled(mPtr, enabled != 0);
+ }
+
+ public void registerStylusIconEnabledSettingObserver() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.STYLUS_ICON_ENABLED), false,
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateStylusIconEnabledFromSettings();
+ }
+ });
+ }
+
+ private int getStylusIconEnabled(int defaultValue) {
+ int result = defaultValue;
+ try {
+ result = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.STYLUS_ICON_ENABLED);
+ } catch (SettingNotFoundException snfe) {
+ }
+ return result;
+ }
+
+ public void updateVolumeKeysRotationFromSettings() {
+ int mode = getVolumeKeysRotationSetting(0);
+ nativeSetVolumeKeysRotation(mPtr, mode);
+ }
+
+ public void registerVolumeKeysRotationSettingObserver() {
+ mContext.getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.SWAP_VOLUME_KEYS_ON_ROTATION), false,
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateVolumeKeysRotationFromSettings();
+ }
+ });
+ }
+
+ private int getVolumeKeysRotationSetting(int defaultValue) {
+ int result = defaultValue;
+ try {
+ result = CMSettings.System.getIntForUser(mContext.getContentResolver(),
+ CMSettings.System.SWAP_VOLUME_KEYS_ON_ROTATION, UserHandle.USER_CURRENT);
+ } catch (CMSettings.CMSettingNotFoundException snfe) {
+ }
+ return result;
+ }
+
// Binder call
@Override
public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
@@ -1521,15 +1619,22 @@ public class InputManagerService extends IInputManager.Stub
// Native callback.
final boolean filterInputEvent(InputEvent event, int policyFlags) {
+ ChainedInputFilterHost head = null;
synchronized (mInputFilterLock) {
- if (mInputFilter != null) {
- try {
- mInputFilter.filterInputEvent(event, policyFlags);
- } catch (RemoteException e) {
- /* ignore */
- }
- return false;
+ if (!mInputFilterChain.isEmpty()) {
+ head = mInputFilterChain.get(0);
+ }
+ }
+ // call filter input event outside of the lock.
+ // this is safe, because we know that mInputFilter never changes.
+ // we may loose a event, but this does not differ from the original implementation.
+ if (head != null) {
+ try {
+ head.mInputFilter.filterInputEvent(event, policyFlags);
+ } catch (RemoteException e) {
+ /* ignore */
}
+ return false;
}
event.recycle();
return true;
@@ -1786,6 +1891,66 @@ public class InputManagerService extends IInputManager.Stub
}
}
+ /**
+ * Hosting interface for input filters to call back into the input manager.
+ */
+ private final class ChainedInputFilterHost extends IInputFilterHost.Stub {
+ private final IInputFilter mInputFilter;
+ private ChainedInputFilterHost mNext;
+ private boolean mDisconnected;
+
+ private ChainedInputFilterHost(IInputFilter filter, ChainedInputFilterHost next) {
+ mInputFilter = filter;
+ mNext = next;
+ mDisconnected = false;
+ }
+
+ public void connectLocked() {
+ try {
+ mInputFilter.install(this);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+
+ public void disconnectLocked() {
+ try {
+ mInputFilter.uninstall();
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ // DO NOT set mInputFilter to null here! mInputFilter is used outside of the lock!
+ mDisconnected = true;
+ }
+
+ @Override
+ public void sendInputEvent(InputEvent event, int policyFlags) {
+ if (event == null) {
+ throw new IllegalArgumentException("event must not be null");
+ }
+
+ synchronized (mInputFilterLock) {
+ if (!mDisconnected) {
+ if (mNext == null) {
+ nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
+ policyFlags | WindowManagerPolicy.FLAG_FILTERED);
+ } else {
+ try {
+ // We need to pass a copy into filterInputEvent as it assumes
+ // the callee takes responsibility and recycles it - in case
+ // multiple filters are chained, calling into the second filter
+ // will cause event to be recycled twice
+ mNext.mInputFilter.filterInputEvent(event.copy(), policyFlags);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ }
+ }
+ }
+ }
+ }
+
private static final class KeyboardLayoutDescriptor {
public String packageName;
public String receiverName;
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java
index b496b4c..3eb570c 100644
--- a/services/core/java/com/android/server/lights/Light.java
+++ b/services/core/java/com/android/server/lights/Light.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +36,7 @@ public abstract class Light {
public abstract void setBrightness(int brightness, int brightnessMode);
public abstract void setColor(int color);
public abstract void setFlashing(int color, int mode, int onMS, int offMS);
+ public abstract void setModes(int brightnessLevel, boolean multipleLeds);
public abstract void pulse();
public abstract void pulse(int color, int onMS);
public abstract void turnOff();
diff --git a/services/core/java/com/android/server/lights/LightsManager.java b/services/core/java/com/android/server/lights/LightsManager.java
index 2f20509..e1e5aa3 100644
--- a/services/core/java/com/android/server/lights/LightsManager.java
+++ b/services/core/java/com/android/server/lights/LightsManager.java
@@ -25,7 +25,9 @@ public abstract class LightsManager {
public static final int LIGHT_ID_ATTENTION = 5;
public static final int LIGHT_ID_BLUETOOTH = 6;
public static final int LIGHT_ID_WIFI = 7;
- public static final int LIGHT_ID_COUNT = 8;
+ public static final int LIGHT_ID_CAPS = 8;
+ public static final int LIGHT_ID_FUNC = 9;
+ public static final int LIGHT_ID_COUNT = 10;
public abstract Light getLight(int id);
}
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index ed884ef..16dde26 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +35,9 @@ public class LightsService extends SystemService {
private LightImpl(int id) {
mId = id;
+ mBrightnessLevel = 0xFF;
+ mModesUpdate = false;
+ mMultipleLeds = false;
}
@Override
@@ -65,6 +69,20 @@ public class LightsService extends SystemService {
}
@Override
+ public void setModes(int brightnessLevel, boolean multipleLeds) {
+ synchronized (this) {
+ if (mBrightnessLevel != brightnessLevel) {
+ mBrightnessLevel = brightnessLevel;
+ mModesUpdate = true;
+ }
+ if (mMultipleLeds != multipleLeds) {
+ mMultipleLeds = multipleLeds;
+ mModesUpdate = true;
+ }
+ }
+ }
+
+ @Override
public void pulse() {
pulse(0x00ffffff, 7);
}
@@ -94,17 +112,20 @@ public class LightsService extends SystemService {
}
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
- if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
+ if (mModesUpdate || color != mColor || mode != mMode || onMS != mOnMS ||
+ offMS != mOffMS) {
if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color));
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
+ mModesUpdate = false;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
+ Integer.toHexString(color) + ")");
try {
- setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
+ setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode,
+ mBrightnessLevel, mMultipleLeds ? 1 : 0);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
@@ -116,7 +137,10 @@ public class LightsService extends SystemService {
private int mMode;
private int mOnMS;
private int mOffMS;
+ private int mBrightnessLevel;
private boolean mFlashing;
+ private boolean mModesUpdate;
+ private boolean mMultipleLeds;
}
public LightsService(Context context) {
@@ -163,7 +187,8 @@ public class LightsService extends SystemService {
private static native void finalize_native(long ptr);
static native void setLight_native(long ptr, int light, int color, int mode,
- int onMS, int offMS, int brightnessMode);
+ int onMS, int offMS, int brightnessMode, int brightnessLevel,
+ int mMultipleLeds);
private long mNativePointer;
}
diff --git a/services/core/java/com/android/server/location/GeoFencerBase.java b/services/core/java/com/android/server/location/GeoFencerBase.java
new file mode 100644
index 0000000..eec07ab
--- /dev/null
+++ b/services/core/java/com/android/server/location/GeoFencerBase.java
@@ -0,0 +1,147 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 com.android.server.location;
+
+import android.os.Binder;
+import android.os.Parcelable;
+import android.util.Log;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.location.GeoFenceParams;
+import android.location.ILocationListener;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Collection;
+import java.util.ArrayList;
+
+/**
+ * This class defines a base class for GeoFencers
+ *
+ * @hide
+ */
+public abstract class GeoFencerBase {
+ private static final String TAG = "GeoFencerBase";
+ private HashMap<PendingIntent,GeoFenceParams> mGeoFences;
+
+ public GeoFencerBase() {
+ mGeoFences = new HashMap<PendingIntent,GeoFenceParams>();
+ }
+
+ public void add(double latitude, double longitude,
+ float radius, long expiration, PendingIntent intent,
+ String packageName) {
+ add(new GeoFenceParams(latitude, longitude, radius,
+ expiration, intent, packageName));
+ }
+
+ public void add(GeoFenceParams geoFence) {
+ synchronized(mGeoFences) {
+ mGeoFences.put(geoFence.mIntent, geoFence);
+ }
+ if (!start(geoFence)) {
+ synchronized(mGeoFences) {
+ mGeoFences.remove(geoFence.mIntent);
+ }
+ }
+ }
+
+ public void remove(PendingIntent intent) {
+ remove(intent, false);
+ }
+
+ public void remove(PendingIntent intent, boolean localOnly) {
+ GeoFenceParams geoFence = null;
+
+ synchronized(mGeoFences) {
+ geoFence = mGeoFences.remove(intent);
+ }
+
+ if (geoFence != null) {
+ if (!localOnly && !stop(intent)) {
+ synchronized(mGeoFences) {
+ mGeoFences.put(geoFence.mIntent, geoFence);
+ }
+ }
+ }
+ }
+
+ public int getNumbOfGeoFences() {
+ return mGeoFences.size();
+ }
+
+ public Collection<GeoFenceParams> getAllGeoFences() {
+ return mGeoFences.values();
+ }
+
+ public GeoFenceParams getGeoFence(PendingIntent intent) {
+ return mGeoFences.get(intent);
+ }
+
+ public boolean hasCaller(int uid) {
+ for (GeoFenceParams alert : mGeoFences.values()) {
+ if (alert.mUid == uid) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void removeCaller(int uid) {
+ ArrayList<PendingIntent> removedFences = null;
+ for (GeoFenceParams alert : mGeoFences.values()) {
+ if (alert.mUid == uid) {
+ if (removedFences == null) {
+ removedFences = new ArrayList<PendingIntent>();
+ }
+ removedFences.add(alert.mIntent);
+ }
+ }
+ if (removedFences != null) {
+ for (int i = removedFences.size()-1; i>=0; i--) {
+ mGeoFences.remove(removedFences.get(i));
+ }
+ }
+ }
+
+ public void transferService(GeoFencerBase geofencer) {
+ for (GeoFenceParams alert : geofencer.mGeoFences.values()) {
+ geofencer.stop(alert.mIntent);
+ add(alert);
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ if (mGeoFences.size() > 0) {
+ pw.println(prefix + " GeoFences:");
+ prefix += " ";
+ for (Map.Entry<PendingIntent, GeoFenceParams> i
+ : mGeoFences.entrySet()) {
+ pw.println(prefix + i.getKey() + ":");
+ i.getValue().dump(pw, prefix);
+ }
+ }
+ }
+
+ abstract protected boolean start(GeoFenceParams geoFence);
+ abstract protected boolean stop(PendingIntent intent);
+}
diff --git a/services/core/java/com/android/server/location/GeoFencerProxy.java b/services/core/java/com/android/server/location/GeoFencerProxy.java
new file mode 100644
index 0000000..8ffbe8c
--- /dev/null
+++ b/services/core/java/com/android/server/location/GeoFencerProxy.java
@@ -0,0 +1,149 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 com.android.server.location;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.app.PendingIntent;
+import android.location.IGeoFencer;
+import android.location.IGeoFenceListener;
+import android.location.GeoFenceParams;
+
+/**
+ * A class for proxying IGeoFenceProvider implementations.
+ *
+ * {@hide}
+ */
+public class GeoFencerProxy extends GeoFencerBase {
+
+ private static final String TAG = "GeoFencerProxy";
+ private static final boolean LOGV_ENABLED = true;
+
+ private final Context mContext;
+ private final Intent mIntent;
+ private IGeoFencer mGeoFencer;
+
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ synchronized (this) {
+ mGeoFencer = IGeoFencer.Stub.asInterface(service);
+ notifyAll();
+ }
+ Log.v(TAG, "onServiceConnected: mGeoFencer - "+mGeoFencer);
+ }
+ public void onServiceDisconnected(ComponentName className) {
+ synchronized (this) {
+ mGeoFencer = null;
+ }
+ Log.v(TAG, "onServiceDisconnected");
+ }
+ };
+
+ private final IGeoFenceListener.Stub mListener = new IGeoFenceListener.Stub() {
+ @Override
+ public void geoFenceExpired(PendingIntent intent) throws RemoteException {
+ logv("geoFenceExpired - "+intent);
+ remove(intent, true);
+ }
+ };
+
+ private static GeoFencerProxy mGeoFencerProxy;
+ public static GeoFencerProxy getGeoFencerProxy(Context context, String serviceName) {
+ if (mGeoFencerProxy == null) {
+ mGeoFencerProxy = new GeoFencerProxy(context, serviceName);
+ }
+ return mGeoFencerProxy;
+ }
+
+ private GeoFencerProxy(Context context, String serviceName) {
+ mContext = context;
+ mIntent = new Intent(IGeoFencer.class.getName());
+ mIntent.setPackage(serviceName);
+ mContext.bindService(mIntent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_ALLOW_OOM_MANAGEMENT);
+ }
+
+ public void removeCaller(int uid) {
+ super.removeCaller(uid);
+ if(mGeoFencer != null) {
+ try {
+ mGeoFencer.clearGeoFenceUser(uid);
+ } catch (RemoteException re) {
+ }
+ }
+ else
+ Log.e(TAG, "removeCaller - mGeoFencer is null");
+ }
+
+ private boolean ensureGeoFencer() {
+ if (mGeoFencer == null) {
+ try {
+ synchronized(mServiceConnection) {
+ logv("waiting...");
+ mServiceConnection.wait(60000);
+ logv("woke up!!!");
+ }
+ } catch (InterruptedException ie) {
+ Log.w(TAG, "Interrupted while waiting for GeoFencer");
+ return false;
+ }
+
+ if (mGeoFencer == null) {
+ Log.w(TAG, "Timed out. No GeoFencer connection");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected boolean start(GeoFenceParams geofence) {
+ if (ensureGeoFencer()) {
+ try {
+ return mGeoFencer.setGeoFence(mListener, geofence);
+ } catch (RemoteException re) {
+ }
+ }
+ return false;
+ }
+
+ protected boolean stop(PendingIntent intent) {
+ if (ensureGeoFencer()) {
+ try {
+ mGeoFencer.clearGeoFence(mListener, intent);
+ return true;
+ } catch (RemoteException re) {
+ }
+ }
+ return false;
+ }
+
+ private void logv(String s) {
+ if (LOGV_ENABLED) Log.v(TAG, s);
+ }
+}
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 4f42f83..bdb77db 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -88,6 +88,7 @@ import java.io.StringReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
+import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Properties;
@@ -359,6 +360,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
private String mC2KServerHost;
private int mC2KServerPort;
private boolean mSuplEsEnabled = false;
+ private HashSet<String> mLastKnownMccMnc;
private final Context mContext;
private final NtpTrustedTime mNtpTime;
@@ -482,18 +484,14 @@ public class GpsLocationProvider implements LocationProviderInterface {
};
private void subscriptionOrSimChanged(Context context) {
- Log.d(TAG, "received SIM related action: ");
- TelephonyManager phone = (TelephonyManager)
- mContext.getSystemService(Context.TELEPHONY_SERVICE);
- String mccMnc = phone.getSimOperator();
- if (!TextUtils.isEmpty(mccMnc)) {
- Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
- synchronized (mLock) {
+ HashSet<String> mccMnc = getKnownMccMnc(context);
+ Log.d(TAG, "received SIM change, new known MCC/MNC: " + mccMnc);
+ synchronized (mLock) {
+ if (!mccMnc.isEmpty() && !mccMnc.equals(mLastKnownMccMnc)) {
reloadGpsProperties(context, mProperties);
mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
}
- } else {
- Log.d(TAG, "SIM MCC/MNC is still not available");
+ mLastKnownMccMnc = mccMnc;
}
}
@@ -585,6 +583,20 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
+ private HashSet<String> getKnownMccMnc(Context context) {
+ final TelephonyManager phone = (TelephonyManager)
+ context.getSystemService(Context.TELEPHONY_SERVICE);
+ final HashSet<String> mccMnc = new HashSet<String>();
+ final int phoneCnt = phone.getPhoneCount();
+ for (int i = 0;i < phoneCnt; ++i) {
+ String operator = phone.getNetworkOperatorForPhone(i);
+ if (!TextUtils.isEmpty(operator)) {
+ mccMnc.add(operator);
+ }
+ }
+ return mccMnc;
+ }
+
private void loadPropertiesFromResource(Context context,
Properties properties) {
String[] configValues = context.getResources().getStringArray(
@@ -650,6 +662,8 @@ public class GpsLocationProvider implements LocationProviderInterface {
// Construct internal handler
mHandler = new ProviderHandler(looper);
+ mLastKnownMccMnc = getKnownMccMnc(mContext);
+
// Load GPS configuration and register listeners in the background:
// some operations, such as opening files and registering broadcast receivers, can take a
// relative long time, so the ctor() is kept to create objects needed by this instance,
@@ -1934,7 +1948,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
}
native_agps_set_ref_location_cellid(type, mcc, mnc,
- gsm_cell.getLac(), gsm_cell.getCid());
+ gsm_cell.getLac(), gsm_cell.getCid(), gsm_cell.getPsc());
} else {
Log.e(TAG,"Error getting cell location info.");
}
@@ -2293,7 +2307,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
// AGPS ril suport
private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
- int lac, int cid);
+ int lac, int cid, int psc);
private native void native_agps_set_id(int type, String setid);
private native void native_update_network_state(boolean connected, int type,
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index f92f631..bc830f0 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -106,6 +106,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private CharSequence mQueueTitle;
private int mRatingType;
private long mLastActiveTime;
+ private String mBrowsedPlayerURI;
+ private boolean mPlayItemStatus;
+ private long[] mNowPlayingList;
// End TransportPerformer fields
// Volume handling fields
@@ -518,6 +521,86 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
}
+ private void pushBrowsePlayerInfo() {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ return;
+ }
+ for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
+ ISessionControllerCallback cb = mControllerCallbacks.get(i);
+ try {
+ Log.d(TAG, "pushBrowsePlayerInfo");
+ cb.onUpdateFolderInfoBrowsedPlayer(mBrowsedPlayerURI);
+ } catch (DeadObjectException e) {
+ Log.w(TAG, "Removing dead callback in pushBrowsePlayerInfo. ", e);
+ mControllerCallbacks.remove(i);
+ } catch (RemoteException e) {
+ Log.w(TAG, "unexpected exception in pushBrowsePlayerInfo. ", e);
+ }
+ }
+ }
+ }
+
+ private void pushNowPlayingEntries() {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ return;
+ }
+ for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
+ ISessionControllerCallback cb = mControllerCallbacks.get(i);
+ try {
+ Log.d(TAG, "pushNowPlayingEntries");
+ cb.onUpdateNowPlayingEntries(mNowPlayingList);
+ } catch (DeadObjectException e) {
+ Log.w(TAG, "Removing dead callback in pushNowPlayingEntries. ", e);
+ mControllerCallbacks.remove(i);
+ } catch (RemoteException e) {
+ Log.w(TAG, "unexpected exception in pushNowPlayingEntries. ", e);
+ }
+ }
+ }
+ }
+
+ private void pushNowPlayingContentChange() {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ return;
+ }
+ for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
+ ISessionControllerCallback cb = mControllerCallbacks.get(i);
+ try {
+ Log.d(TAG, "pushNowPlayingContentChange");
+ cb.onUpdateNowPlayingContentChange();
+ } catch (DeadObjectException e) {
+ Log.w(TAG, "Removing dead callback in pushNowPlayingContentChange. ", e);
+ mControllerCallbacks.remove(i);
+ } catch (RemoteException e) {
+ Log.w(TAG, "unexpected exception in pushNowPlayingContentChange. ", e);
+ }
+ }
+ }
+ }
+
+ private void pushPlayItemResponse() {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ return;
+ }
+ for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
+ ISessionControllerCallback cb = mControllerCallbacks.get(i);
+ try {
+ Log.d(TAG, "pushPlayItemResponse");
+ cb.onPlayItemResponse(mPlayItemStatus);
+ } catch (DeadObjectException e) {
+ Log.w(TAG, "Removing dead callback in pushPlayItemResponse. ", e);
+ mControllerCallbacks.remove(i);
+ } catch (RemoteException e) {
+ Log.w(TAG, "unexpected exception in pushPlayItemResponse. ", e);
+ }
+ }
+ }
+ }
+
private void pushQueueUpdate() {
synchronized (mLock) {
if (mDestroyed) {
@@ -775,6 +858,33 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
+ public void updateFolderInfoBrowsedPlayer(String stringUri) {
+ Log.d(TAG, "SessionStub: updateFolderInfoBrowsedPlayer");
+ mBrowsedPlayerURI = stringUri;
+ mHandler.post(MessageHandler.MSG_FOLDER_INFO_BROWSED_PLAYER);
+ }
+
+ @Override
+ public void updateNowPlayingEntries(long[] playList) {
+ Log.d(TAG, "SessionStub: updateNowPlayingEntries");
+ mNowPlayingList = playList;
+ mHandler.post(MessageHandler.MSG_UPDATE_NOWPLAYING_ENTRIES);
+ }
+
+ @Override
+ public void updateNowPlayingContentChange() {
+ Log.d(TAG, "SessionStub: updateNowPlayingContentChange");
+ mHandler.post(MessageHandler.MSG_UPDATE_NOWPLAYING_CONTENT_CHANGE);
+ }
+
+ @Override
+ public void playItemResponse(boolean success) {
+ Log.d(TAG, "SessionStub: playItemResponse");
+ mPlayItemStatus = success;
+ mHandler.post(MessageHandler.MSG_PLAY_ITEM_RESPONSE);
+ }
+
+ @Override
public void setQueueTitle(CharSequence title) {
mQueueTitle = title;
mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE);
@@ -957,6 +1067,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
public void seekTo(long pos) {
+ Slog.d(TAG, "seekTo in SessionCb");
try {
mCb.onSeekTo(pos);
} catch (RemoteException e) {
@@ -964,6 +1075,42 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
}
+ /**
+ * @hide
+ */
+ public void setRemoteControlClientBrowsedPlayer() {
+ Slog.d(TAG, "setRemoteControlClientBrowsedPlayer in SessionCb");
+ try {
+ mCb.setRemoteControlClientBrowsedPlayer();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in setRemoteControlClientBrowsedPlayer.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setRemoteControlClientPlayItem(long uid, int scope) throws RemoteException {
+ Slog.d(TAG, "setRemoteControlClientPlayItem in SessionCb");
+ try {
+ mCb.setRemoteControlClientPlayItem(uid, scope);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in setRemoteControlClientPlayItem.", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void getRemoteControlClientNowPlayingEntries() throws RemoteException {
+ Slog.d(TAG, "getRemoteControlClientNowPlayingEntries in SessionCb");
+ try {
+ mCb.getRemoteControlClientNowPlayingEntries();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in getRemoteControlClientNowPlayingEntries.", e);
+ }
+ }
+
public void rate(Rating rating) {
try {
mCb.onRate(rating);
@@ -1157,10 +1304,29 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void seekTo(long pos) throws RemoteException {
+ Log.d(TAG, "seekTo in ControllerStub");
mSessionCb.seekTo(pos);
}
@Override
+ public void setRemoteControlClientBrowsedPlayer() throws RemoteException {
+ Log.d(TAG, "setRemoteControlClientBrowsedPlayer in ControllerStub");
+ mSessionCb.setRemoteControlClientBrowsedPlayer();
+ }
+
+ @Override
+ public void setRemoteControlClientPlayItem(long uid, int scope) throws RemoteException {
+ Log.d(TAG, "setRemoteControlClientPlayItem in ControllerStub");
+ mSessionCb.setRemoteControlClientPlayItem(uid, scope);
+ }
+
+ @Override
+ public void getRemoteControlClientNowPlayingEntries() throws RemoteException {
+ Log.d(TAG, "getRemoteControlClientNowPlayingEntries in ControllerStub");
+ mSessionCb.getRemoteControlClientNowPlayingEntries();
+ }
+
+ @Override
public void rate(Rating rating) throws RemoteException {
mSessionCb.rate(rating);
}
@@ -1224,6 +1390,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private static final int MSG_UPDATE_SESSION_STATE = 7;
private static final int MSG_UPDATE_VOLUME = 8;
private static final int MSG_DESTROYED = 9;
+ private static final int MSG_FOLDER_INFO_BROWSED_PLAYER = 10;
+ private static final int MSG_UPDATE_NOWPLAYING_ENTRIES = 11;
+ private static final int MSG_UPDATE_NOWPLAYING_CONTENT_CHANGE = 12;
+ private static final int MSG_PLAY_ITEM_RESPONSE = 13;
public MessageHandler(Looper looper) {
super(looper);
@@ -1257,6 +1427,18 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
break;
case MSG_DESTROYED:
pushSessionDestroyed();
+ case MSG_FOLDER_INFO_BROWSED_PLAYER:
+ pushBrowsePlayerInfo();
+ break;
+ case MSG_UPDATE_NOWPLAYING_ENTRIES:
+ pushNowPlayingEntries();
+ break;
+ case MSG_UPDATE_NOWPLAYING_CONTENT_CHANGE:
+ pushNowPlayingContentChange();
+ break;
+ case MSG_PLAY_ITEM_RESPONSE:
+ pushPlayItemResponse();
+ break;
}
}
diff --git a/services/core/java/com/android/server/net/NetPluginDelegate.java b/services/core/java/com/android/server/net/NetPluginDelegate.java
new file mode 100644
index 0000000..6716a6b
--- /dev/null
+++ b/services/core/java/com/android/server/net/NetPluginDelegate.java
@@ -0,0 +1,101 @@
+/*
+ *Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ *Redistribution and use in source and binary forms, with or without
+ *modification, are permitted provided that the following conditions are
+ *met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.server.net;
+
+import dalvik.system.PathClassLoader;
+
+import java.lang.reflect.Constructor;
+
+import android.util.Slog;
+import android.net.NetworkStats;
+import android.util.Log;
+
+class NetPluginDelegate {
+
+ private static final String TAG = "ConnectivityExtension";
+ private static final boolean LOGV = false;
+
+ private static Class tetherExtensionClass = null;
+ private static Object tetherExtensionObj = null;
+
+ private static boolean extensionFailed;
+
+ static void getTetherStats(NetworkStats uidStats, NetworkStats devStats,
+ NetworkStats xtStats) {
+ if (!loadTetherExtJar()) {
+ return;
+ }
+ try {
+ tetherExtensionClass.getMethod("getTetherStats", NetworkStats.class,
+ NetworkStats.class, NetworkStats.class).invoke(tetherExtensionObj, uidStats,
+ devStats, xtStats);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.w(TAG, "error in invoke method");
+ }
+ }
+
+ static void setQuota(String iface, long quota) {
+ if (!loadTetherExtJar()) {
+ return;
+ }
+ try {
+ tetherExtensionClass.getMethod("setQuota", String.class, long.class).invoke(
+ tetherExtensionObj, iface, quota);
+ } catch (Exception ex) {
+ Log.w(TAG, "Error calling setQuota Method on extension jar");
+ }
+ }
+
+
+
+ private static boolean loadTetherExtJar() {
+ final String realProvider = "com.qualcomm.qti.tetherstatsextension.TetherStatsReporting";
+ final String realProviderPath = "/system/framework/ConnectivityExt.jar";
+ if (!extensionFailed && tetherExtensionClass == null && tetherExtensionObj == null) {
+ if (LOGV) Slog.v(TAG, "loading ConnectivityExt jar");
+ try {
+
+ PathClassLoader classLoader = new PathClassLoader(realProviderPath,
+ ClassLoader.getSystemClassLoader());
+
+ tetherExtensionClass = classLoader.loadClass(realProvider);
+ tetherExtensionObj = tetherExtensionClass.newInstance();
+ if (LOGV)
+ Slog.v(TAG, "ConnectivityExt jar loaded");
+ extensionFailed = false;
+ } catch (Exception e) {
+ Log.w(TAG, "Connectivity extension is not available");
+ extensionFailed = true;
+ }
+ }
+ return !extensionFailed;
+ }
+}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 1b08c2f..da62313 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -249,6 +249,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
private static final int MSG_SCREEN_ON_CHANGED = 8;
+ private static final int MSG_PROCESS_LOW_POWER_CHANGED = 9;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -447,13 +448,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
- public void onLowPowerModeChanged(boolean enabled) {
- synchronized (mRulesLock) {
- if (mRestrictPower != enabled) {
- mRestrictPower = enabled;
- updateRulesForGlobalChangeLocked(true);
- }
- }
+ public void onLowPowerModeChanged(final boolean enabled) {
+ mHandler.removeMessages(MSG_PROCESS_LOW_POWER_CHANGED);
+ Message msg = Message.obtain(mHandler, MSG_PROCESS_LOW_POWER_CHANGED, enabled);
+ mHandler.sendMessage(msg);
}
});
mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
@@ -820,7 +818,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} else {
notifyUnderLimitLocked(policy.template);
- if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
+ if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start
+ && policy.limitBytes != LIMIT_DISABLED) {
enqueueNotification(policy, TYPE_WARNING, totalBytes);
hasNotifications = true;
}
@@ -2223,12 +2222,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
uidRules.clear();
// Fully update the app idle firewall chain.
+ final IPackageManager ipm = AppGlobals.getPackageManager();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
UserInfo user = users.get(ui);
int[] idleUids = mUsageStats.getIdleUidsForUser(user.id);
for (int uid : idleUids) {
if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) {
+ // quick check: if this uid doesn't have INTERNET permission, it
+ // doesn't have network access anyway, so it is a waste to mess
+ // with it here.
+ try {
+ if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ continue;
+ }
+ } catch (RemoteException e) {
+ }
uidRules.put(uid, FIREWALL_RULE_DENY);
}
}
@@ -2313,11 +2323,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private boolean isUidIdle(int uid) {
final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
- final int userId = UserHandle.getUserId(uid);
- for (String packageName : packages) {
- if (!mUsageStats.isAppIdle(packageName, uid, userId)) {
- return false;
+ if (packages != null) {
+ final int userId = UserHandle.getUserId(uid);
+ for (String packageName : packages) {
+ if (!mUsageStats.isAppIdle(packageName, uid, userId)) {
+ return false;
+ }
}
}
return true;
@@ -2516,6 +2528,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
updateScreenOn();
return true;
}
+ case MSG_PROCESS_LOW_POWER_CHANGED: {
+ boolean enabled = (Boolean) msg.obj;
+ synchronized (mRulesLock) {
+ if (mRestrictPower != enabled) {
+ mRestrictPower = enabled;
+ updateRulesForGlobalChangeLocked(true);
+ }
+ }
+ return true;
+ }
default: {
return false;
}
@@ -2526,6 +2548,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void setInterfaceQuota(String iface, long quotaBytes) {
try {
mNetworkManager.setInterfaceQuota(iface, quotaBytes);
+ NetPluginDelegate.setQuota(iface, quotaBytes);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting interface quota", e);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 8449348..acd05f7 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -971,7 +971,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
-
+ NetPluginDelegate.getTetherStats(uidSnapshot, xtSnapshot, devSnapshot);
VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, null, currentTime);
mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, null, currentTime);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 288810c..36818b5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +24,7 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
@@ -30,6 +32,7 @@ import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.ITransientNotification;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
@@ -41,7 +44,9 @@ import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
+import android.database.Cursor;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -53,11 +58,15 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.IRingtonePlayer;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -92,7 +101,9 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
+import android.util.LruCache;
import android.util.Slog;
+import android.util.SparseIntArray;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -101,6 +112,9 @@ import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.cm.SpamFilter;
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -110,6 +124,9 @@ import com.android.server.notification.ManagedServices.ManagedServiceInfo;
import com.android.server.notification.ManagedServices.UserProfiles;
import com.android.server.statusbar.StatusBarManagerInternal;
+import cyanogenmod.providers.CMSettings;
+import cyanogenmod.util.ColorUtils;
+
import libcore.io.IoUtils;
import org.json.JSONArray;
@@ -134,10 +151,15 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
/** {@hide} */
public class NotificationManagerService extends SystemService {
@@ -170,6 +192,8 @@ public class NotificationManagerService extends SystemService {
static final int JUNK_SCORE = -1000;
static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER;
+ private static final String IS_FILTERED_QUERY = NotificationTable.NORMALIZED_TEXT + "=? AND " +
+ PackageTable.PACKAGE_NAME + "=?";
// Notifications with scores below this will not interrupt the user, either via LED or
// sound or vibration
@@ -198,6 +222,9 @@ public class NotificationManagerService extends SystemService {
/** notification_enqueue status value for an ignored notification. */
private static final int EVENTLOG_ENQUEUE_STATUS_IGNORED = 2;
+ /** notification light maximum brightness value to use. */
+ private static final int LIGHT_BRIGHTNESS_MAXIMUM = 255;
+
private IActivityManager mAm;
AudioManager mAudioManager;
AudioManagerInternal mAudioManagerInternal;
@@ -217,10 +244,37 @@ public class NotificationManagerService extends SystemService {
private int mDefaultNotificationLedOff;
private long[] mDefaultVibrationPattern;
+ private boolean mAdjustableNotificationLedBrightness;
+ private int mNotificationLedBrightnessLevel = LIGHT_BRIGHTNESS_MAXIMUM;
+
+ private boolean mMultipleNotificationLeds;
+ private boolean mMultipleLedsEnabledSetting = false;
+
+ private boolean mAutoGenerateNotificationColor = true;
+
+ private boolean mScreenOnEnabled = false;
+ private boolean mScreenOnDefault = false;
+
private long[] mFallbackVibrationPattern;
private boolean mUseAttentionLight;
boolean mSystemReady;
+ private final SparseIntArray mSpamCache;
+ private ExecutorService mSpamExecutor = Executors.newSingleThreadExecutor();
+
+ private static final Uri FILTER_MSG_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SpamFilter.AUTHORITY)
+ .appendPath("messages")
+ .build();
+
+ private static final Uri UPDATE_MSG_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SpamFilter.AUTHORITY)
+ .appendPath(SpamFilter.MESSAGE_PATH)
+ .appendEncodedPath("inc_count")
+ .build();
+
private boolean mDisableNotificationEffects;
private int mCallState;
private String mSoundNotificationKey;
@@ -235,6 +289,13 @@ public class NotificationManagerService extends SystemService {
private boolean mScreenOn = true;
private boolean mInCall = false;
private boolean mNotificationPulseEnabled;
+ private HashMap<String, NotificationLedValues> mNotificationPulseCustomLedValues;
+ private Map<String, String> mPackageNameMappings;
+ private final Map<String, Integer> mGeneratedPackageLedColors =
+ new HashMap<String, Integer>();
+
+ // for checking lockscreen status
+ private KeyguardManager mKeyguardManager;
// used as a mutex for access to all active notifications & listeners
final ArrayList<NotificationRecord> mNotificationList =
@@ -275,6 +336,8 @@ public class NotificationManagerService extends SystemService {
private NotificationListeners mListeners;
private ConditionProviders mConditionProviders;
private NotificationUsageStats mUsageStats;
+ private boolean mDisableDuckingWhileMedia;
+ private boolean mActiveMedia;
private static final int MY_UID = Process.myUid();
private static final int MY_PID = Process.myPid();
@@ -487,6 +550,12 @@ public class NotificationManagerService extends SystemService {
}
}
+ class NotificationLedValues {
+ public int color;
+ public int onMS;
+ public int offMS;
+ }
+
private final NotificationDelegate mNotificationDelegate = new NotificationDelegate() {
@Override
@@ -610,9 +679,19 @@ public class NotificationManagerService extends SystemService {
Binder.restoreCallingIdentity(identity);
}
- // light
- mLights.clear();
- updateLightsLocked();
+ // lights
+ // clear only if lockscreen is not active
+ // and LED is not forced on by Settings app
+ if (mLights.size() > 0) {
+ final String owner = mLights.get(mLights.size() - 1);
+ NotificationRecord ledNotification = mNotificationsByKey.get(owner);
+ if (mKeyguardManager != null && !mKeyguardManager.isKeyguardLocked()) {
+ if (!isLedNotificationForcedOn(ledNotification)) {
+ mLights.clear();
+ }
+ updateLightsLocked();
+ }
+ }
}
}
@@ -629,8 +708,9 @@ public class NotificationManagerService extends SystemService {
"Bad notification posted from package " + pkg
+ ": " + message);
} catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- Binder.restoreCallingIdentity(ident);
}
@Override
@@ -774,12 +854,16 @@ public class NotificationManagerService extends SystemService {
}
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
// turn off LED when user passes through lock screen
- mNotificationLight.turnOff();
- mStatusBar.notificationLightOff();
+ // if lights with screen on is disabled.
+ if (!mScreenOnEnabled) {
+ mNotificationLight.turnOff();
+ mStatusBar.notificationLightOff();
+ }
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
// reload per-user settings
mSettingsObserver.update(null);
+ mSpamFilterObserver.update(null);
mUserProfiles.updateCache(context);
// Refresh managed services
mConditionProviders.onUserSwitched(user);
@@ -794,9 +878,103 @@ public class NotificationManagerService extends SystemService {
}
};
- private final class SettingsObserver extends ContentObserver {
+ class SpamFilterObserver extends ContentObserver {
+
+ private Future mTask;
+
+ public SpamFilterObserver(Handler handler) {
+ super(handler);
+ }
+
+ private void addToCache(Cursor c) {
+ int notifId = c.getInt(c.getColumnIndex(
+ NotificationTable.ID));
+ String pkgName = c.getString(c.getColumnIndex(
+ PackageTable.PACKAGE_NAME));
+ String normalizedText = c.getString(c.getColumnIndex(
+ NotificationTable.NORMALIZED_TEXT));
+ int hash = getSpamCacheHash(normalizedText, pkgName);
+ synchronized (mSpamCache) {
+ mSpamCache.put(hash, notifId);
+ }
+ }
+
+ private Runnable mFetchAllFilters = new Runnable() {
+ @Override
+ public void run() {
+ Cursor c = getContext().getContentResolver().query(FILTER_MSG_URI,
+ null, null, null, null);
+ if (c != null) {
+ synchronized (mSpamCache) {
+ mSpamCache.clear();
+ while (c.moveToNext()) {
+ addToCache(c);
+ if (Thread.interrupted()) {
+ break;
+ }
+ c.close();
+ }
+ }
+ }
+ }
+ };
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update(uri);
+ }
+
+ void update(final Uri uri) {
+ if (mTask != null && !mTask.isDone()) {
+ mTask.cancel(true);
+ }
+ if (uri == null) {
+ mTask = mSpamExecutor.submit(mFetchAllFilters);
+ } else {
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ String id = uri.getLastPathSegment();
+ Cursor c = getContext().getContentResolver().query(
+ uri, null, null, null, null);
+
+ if (c != null) {
+ int index;
+ synchronized (mSpamCache) {
+ index = mSpamCache.indexOfValue(Integer.parseInt(id));
+ }
+ if (!c.moveToFirst()) {
+ synchronized (mSpamCache) {
+ // Filter was deleted
+ if (index >= 0) {
+ mSpamCache.removeAt(index);
+ }
+ }
+ } else if (index < 0) {
+ // Filter was added/updated
+ addToCache(c);
+ }
+ c.close();
+ }
+ }
+ };
+ mTask = mSpamExecutor.submit(r);
+ }
+ }
+
+ public void observe() {
+ ContentResolver resolver = getContext().getContentResolver();
+ resolver.registerContentObserver(SpamFilter.NOTIFICATION_URI,
+ true, this, UserHandle.USER_ALL);
+ update(null);
+ }
+ }
+
+ class SettingsObserver extends ContentObserver {
private final Uri NOTIFICATION_LIGHT_PULSE_URI
= Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
+ private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
+ = Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
SettingsObserver(Handler handler) {
super(handler);
@@ -804,8 +982,44 @@ public class NotificationManagerService extends SystemService {
void observe() {
ContentResolver resolver = getContext().getContentResolver();
- resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
+ resolver.registerContentObserver(
+ NOTIFICATION_LIGHT_PULSE_URI, false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(
+ ENABLED_NOTIFICATION_LISTENERS_URI, false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON),
false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_SCREEN_ON),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Global.getUriFor(
+ CMSettings.Global.ZEN_DISABLE_DUCKING_DURING_MEDIA_PLAYBACK), false,
+ this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO), false,
+ this, UserHandle.USER_ALL);
+ if (mAdjustableNotificationLedBrightness) {
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL),
+ false, this, UserHandle.USER_ALL);
+ }
+ if (mMultipleNotificationLeds) {
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NOTIFICATION_LIGHT_MULTIPLE_LEDS_ENABLE),
+ false, this, UserHandle.USER_ALL);
+ }
update(null);
}
@@ -815,18 +1029,85 @@ public class NotificationManagerService extends SystemService {
public void update(Uri uri) {
ContentResolver resolver = getContext().getContentResolver();
- if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
- boolean pulseEnabled = Settings.System.getInt(resolver,
- Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0;
- if (mNotificationPulseEnabled != pulseEnabled) {
- mNotificationPulseEnabled = pulseEnabled;
- updateNotificationPulse();
- }
+
+ // LED enabled
+ mNotificationPulseEnabled = Settings.System.getIntForUser(resolver,
+ Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0;
+
+ // Automatically pick a color for LED if not set
+ mAutoGenerateNotificationColor = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO,
+ 1, UserHandle.USER_CURRENT) != 0;
+
+ // LED default color
+ mDefaultNotificationColor = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR,
+ mDefaultNotificationColor, UserHandle.USER_CURRENT);
+
+ // LED default on MS
+ mDefaultNotificationLedOn = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON,
+ mDefaultNotificationLedOn, UserHandle.USER_CURRENT);
+
+ // LED default off MS
+ mDefaultNotificationLedOff = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF,
+ mDefaultNotificationLedOff, UserHandle.USER_CURRENT);
+
+ // LED generated notification colors
+ mGeneratedPackageLedColors.clear();
+
+ // LED custom notification colors
+ mNotificationPulseCustomLedValues.clear();
+ if (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE, 0,
+ UserHandle.USER_CURRENT) != 0) {
+ parseNotificationPulseCustomValuesString(CMSettings.System.getStringForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES,
+ UserHandle.USER_CURRENT));
}
+
+ // Notification LED brightness
+ if (mAdjustableNotificationLedBrightness) {
+ mNotificationLedBrightnessLevel = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
+ LIGHT_BRIGHTNESS_MAXIMUM, UserHandle.USER_CURRENT);
+ }
+
+ // Multiple LEDs enabled
+ if (mMultipleNotificationLeds) {
+ mMultipleLedsEnabledSetting = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_MULTIPLE_LEDS_ENABLE,
+ mMultipleNotificationLeds ? 1 : 0, UserHandle.USER_CURRENT) != 0);
+ }
+
+ // Notification lights with screen on
+ mScreenOnEnabled = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NOTIFICATION_LIGHT_SCREEN_ON,
+ mScreenOnDefault ? 1 : 0, UserHandle.USER_CURRENT) != 0);
+
+ updateNotificationPulse();
+
+ mDisableDuckingWhileMedia = CMSettings.Global.getInt(resolver,
+ CMSettings.Global.ZEN_DISABLE_DUCKING_DURING_MEDIA_PLAYBACK, 0) == 1;
+ updateDisableDucking();
+ }
+ }
+
+ private void updateDisableDucking() {
+ if (!mSystemReady) {
+ return;
+ }
+ final MediaSessionManager mediaSessionManager = (MediaSessionManager) getContext()
+ .getSystemService(Context.MEDIA_SESSION_SERVICE);
+ mediaSessionManager.removeOnActiveSessionsChangedListener(mSessionListener);
+ if (mDisableDuckingWhileMedia) {
+ mediaSessionManager.addOnActiveSessionsChangedListener(mSessionListener, null);
}
}
private SettingsObserver mSettingsObserver;
+ private SpamFilterObserver mSpamFilterObserver;
private ZenModeHelper mZenModeHelper;
private final Runnable mBuzzBeepBlinked = new Runnable() {
@@ -851,6 +1132,7 @@ public class NotificationManagerService extends SystemService {
public NotificationManagerService(Context context) {
super(context);
+ mSpamCache = new SparseIntArray();
}
@Override
@@ -861,6 +1143,8 @@ public class NotificationManagerService extends SystemService {
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
+ mKeyguardManager =
+ (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mHandler = new WorkerHandler();
mRankingThread.start();
@@ -916,6 +1200,16 @@ public class NotificationManagerService extends SystemService {
mDefaultNotificationLedOff = resources.getInteger(
R.integer.config_defaultNotificationLedOff);
+ mNotificationPulseCustomLedValues = new HashMap<String, NotificationLedValues>();
+
+ mPackageNameMappings = new HashMap<String, String>();
+ final String[] defaultMapping = resources.getStringArray(
+ com.android.internal.R.array.notification_light_package_mapping);
+ for (String mapping : defaultMapping) {
+ String[] map = mapping.split("\\|");
+ mPackageNameMappings.put(map[0], map[1]);
+ }
+
mDefaultVibrationPattern = getLongArray(resources,
R.array.config_defaultNotificationVibePattern,
VIBRATE_PATTERN_MAXLEN,
@@ -926,6 +1220,11 @@ public class NotificationManagerService extends SystemService {
VIBRATE_PATTERN_MAXLEN,
DEFAULT_VIBRATE_PATTERN);
+ mAdjustableNotificationLedBrightness = resources.getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness);
+ mMultipleNotificationLeds = resources.getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds);
+
mUseAttentionLight = resources.getBoolean(R.bool.config_useAttentionLight);
// Don't start allowing notifications until the setup wizard has run once.
@@ -937,6 +1236,7 @@ public class NotificationManagerService extends SystemService {
mDisableNotificationEffects = true;
}
mZenModeHelper.initZenMode();
+ mZenModeHelper.readAllowLightsFromSettings();
mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
mUserProfiles.updateCache(getContext());
@@ -969,6 +1269,10 @@ public class NotificationManagerService extends SystemService {
null);
mSettingsObserver = new SettingsObserver(mHandler);
+ mSettingsObserver.observe();
+
+ mSpamFilterObserver = new SpamFilterObserver(mHandler);
+ mSpamFilterObserver.observe();
mArchive = new Archive(resources.getInteger(
R.integer.config_notificationServiceArchiveSize));
@@ -1011,10 +1315,13 @@ public class NotificationManagerService extends SystemService {
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
mZenModeHelper.onSystemReady();
+
+ updateDisableDucking();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
// This observer will force an update when observe is called, causing us to
// bind to listener services.
mSettingsObserver.observe();
+ mSpamFilterObserver.observe();
mListeners.onBootPhaseAppsCanStart();
mConditionProviders.onBootPhaseAppsCanStart();
}
@@ -1798,13 +2105,16 @@ public class NotificationManagerService extends SystemService {
};
private String disableNotificationEffects(NotificationRecord record) {
+ boolean smsRingtone = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_sms_ringtone_incall);
if (mDisableNotificationEffects) {
return "booleanState";
}
if ((mListenerHints & HINT_HOST_DISABLE_EFFECTS) != 0) {
return "listenerHints";
}
- if (mCallState != TelephonyManager.CALL_STATE_IDLE && !mZenModeHelper.isCall(record)) {
+ if (mCallState != TelephonyManager.CALL_STATE_IDLE && !mZenModeHelper.isCall(record)
+ && !smsRingtone) {
return "callState";
}
return null;
@@ -2168,6 +2478,11 @@ public class NotificationManagerService extends SystemService {
return;
}
+ if (isNotificationSpam(notification, pkg)) {
+ mArchive.record(r.sbn);
+ return;
+ }
+
int index = indexOfNotificationLocked(n.getKey());
if (index < 0) {
mNotificationList.add(r);
@@ -2311,6 +2626,21 @@ public class NotificationManagerService extends SystemService {
return false;
}
+ private MediaSessionManager.OnActiveSessionsChangedListener mSessionListener =
+ new MediaSessionManager.OnActiveSessionsChangedListener() {
+ @Override
+ public void onActiveSessionsChanged(@Nullable List<MediaController> controllers) {
+ for (MediaController activeSession : controllers) {
+ PlaybackState playbackState = activeSession.getPlaybackState();
+ if (playbackState != null && playbackState.getState() == PlaybackState.STATE_PLAYING) {
+ mActiveMedia = true;
+ return;
+ }
+ }
+ mActiveMedia = false;
+ }
+ };
+
private void buzzBeepBlinkLocked(NotificationRecord record) {
boolean buzz = false;
boolean beep = false;
@@ -2340,7 +2670,8 @@ public class NotificationManagerService extends SystemService {
if (disableEffects != null) {
ZenLog.traceDisableEffects(record, disableEffects);
}
- if (disableEffects == null
+
+ if ((disableEffects == null)
&& (!(record.isUpdate
&& (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
&& (record.getUserId() == UserHandle.USER_ALL ||
@@ -2378,7 +2709,7 @@ public class NotificationManagerService extends SystemService {
hasValidSound = (soundUri != null);
}
- if (hasValidSound) {
+ if (hasValidSound && (!mDisableDuckingWhileMedia || !mActiveMedia)) {
boolean looping =
(notification.flags & Notification.FLAG_INSISTENT) != 0;
AudioAttributes audioAttributes = audioAttributesForNotification(notification);
@@ -2456,7 +2787,9 @@ public class NotificationManagerService extends SystemService {
// light
// release the light
boolean wasShowLights = mLights.remove(record.getKey());
- if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold) {
+ final boolean canInterruptWithLight = canInterrupt || isLedNotificationForcedOn(record)
+ || (!canInterrupt && mZenModeHelper.getAllowLights());
+ if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && canInterruptWithLight) {
mLights.add(record.getKey());
updateLightsLocked();
if (mUseAttentionLight) {
@@ -2742,6 +3075,33 @@ public class NotificationManagerService extends SystemService {
return (x < low) ? low : ((x > high) ? high : x);
}
+ private int getSpamCacheHash(CharSequence message, String packageName) {
+ return (message + packageName).hashCode();
+ }
+
+ private boolean isNotificationSpam(Notification notification, String basePkg) {
+ CharSequence normalizedContent = SpamFilter
+ .getNormalizedNotificationContent(notification);
+ int notificationHash = getSpamCacheHash(normalizedContent, basePkg);
+ int notificationId;
+ synchronized (mSpamCache) {
+ notificationId = mSpamCache.get(notificationHash, -1);
+ }
+ if (notificationId != -1) {
+ final String notifIdString = String.valueOf(notificationId);
+ mSpamExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ Uri updateUri = Uri.withAppendedPath(UPDATE_MSG_URI,
+ notifIdString);
+ getContext().getContentResolver().update(updateUri,
+ new ContentValues(), null, null);
+ }
+ });
+ }
+ return notificationId != -1;
+ }
+
void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
AccessibilityManager manager = AccessibilityManager.getInstance(getContext());
if (!manager.isEnabled()) {
@@ -3041,6 +3401,16 @@ public class NotificationManagerService extends SystemService {
}
}
+ private boolean isLedNotificationForcedOn(NotificationRecord r) {
+ if (r != null) {
+ final Notification n = r.sbn.getNotification();
+ if (n.extras != null) {
+ return n.extras.getBoolean(Notification.EXTRA_FORCE_SHOW_LIGHTS, false);
+ }
+ }
+ return false;
+ }
+
// lock on mNotificationList
void updateLightsLocked()
{
@@ -3056,29 +3426,128 @@ public class NotificationManagerService extends SystemService {
}
// Don't flash while we are in a call or screen is on
- if (ledNotification == null || mInCall || mScreenOn) {
+ // (unless Notification has EXTRA_FORCE_SHOW_LGHTS)
+ final boolean enableLed;
+ if (ledNotification == null) {
+ enableLed = false;
+ } else if (isLedNotificationForcedOn(ledNotification)) {
+ enableLed = true;
+ } else if (!mScreenOnEnabled && (mInCall || mScreenOn)) {
+ enableLed = false;
+ } else {
+ enableLed = true;
+ }
+
+ if (!enableLed) {
mNotificationLight.turnOff();
mStatusBar.notificationLightOff();
} else {
final Notification ledno = ledNotification.sbn.getNotification();
- int ledARGB = ledno.ledARGB;
- int ledOnMS = ledno.ledOnMS;
- int ledOffMS = ledno.ledOffMS;
- if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) {
- ledARGB = mDefaultNotificationColor;
+ final NotificationLedValues ledValues = getLedValuesForNotification(ledNotification);
+ int ledARGB;
+ int ledOnMS;
+ int ledOffMS;
+
+ if (ledValues != null) {
+ ledARGB = ledValues.color != 0 ? ledValues.color : mDefaultNotificationColor;
+ ledOnMS = ledValues.onMS >= 0 ? ledValues.onMS : mDefaultNotificationLedOn;
+ ledOffMS = ledValues.offMS >= 0 ? ledValues.offMS : mDefaultNotificationLedOff;
+ } else if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) {
+ ledARGB = generateLedColorForNotification(ledNotification);
ledOnMS = mDefaultNotificationLedOn;
ledOffMS = mDefaultNotificationLedOff;
+ } else {
+ ledARGB = ledno.ledARGB;
+ ledOnMS = ledno.ledOnMS;
+ ledOffMS = ledno.ledOffMS;
}
+
+ // update the LEDs modes variables
+ mNotificationLight.setModes(mNotificationLedBrightnessLevel,
+ mMultipleLedsEnabledSetting);
+
if (mNotificationPulseEnabled) {
// pulse repeatedly
mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,
ledOnMS, ledOffMS);
}
+
// let SystemUI make an independent decision
mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);
}
}
+ private void parseNotificationPulseCustomValuesString(String customLedValuesString) {
+ if (TextUtils.isEmpty(customLedValuesString)) {
+ return;
+ }
+
+ for (String packageValuesString : customLedValuesString.split("\\|")) {
+ String[] packageValues = packageValuesString.split("=");
+ if (packageValues.length != 2) {
+ Log.e(TAG, "Error parsing custom led values for unknown package");
+ continue;
+ }
+ String packageName = packageValues[0];
+ String[] values = packageValues[1].split(";");
+ if (values.length != 3) {
+ Log.e(TAG, "Error parsing custom led values '"
+ + packageValues[1] + "' for " + packageName);
+ continue;
+ }
+ NotificationLedValues ledValues = new NotificationLedValues();
+ try {
+ ledValues.color = Integer.parseInt(values[0]);
+ ledValues.onMS = Integer.parseInt(values[1]);
+ ledValues.offMS = Integer.parseInt(values[2]);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Error parsing custom led values '"
+ + packageValues[1] + "' for " + packageName);
+ continue;
+ }
+ mNotificationPulseCustomLedValues.put(packageName, ledValues);
+ }
+ }
+
+ private NotificationLedValues getLedValuesForNotification(NotificationRecord ledNotification) {
+ final String packageName = ledNotification.sbn.getPackageName();
+ return mNotificationPulseCustomLedValues.get(mapPackage(packageName));
+ }
+
+ private int generateLedColorForNotification(NotificationRecord ledNotification) {
+ if (!mAutoGenerateNotificationColor) {
+ return mDefaultNotificationColor;
+ }
+ final String packageName = ledNotification.sbn.getPackageName();
+ final String mapping = mapPackage(packageName);
+ int color = mDefaultNotificationColor;
+
+ if (mGeneratedPackageLedColors.containsKey(mapping)) {
+ return mGeneratedPackageLedColors.get(mapping);
+ }
+
+ PackageManager pm = getContext().getPackageManager();
+ Drawable icon;
+ try {
+ icon = pm.getApplicationIcon(mapping);
+ } catch (NameNotFoundException e) {
+ Slog.e(TAG, e.getMessage(), e);
+ return color;
+ }
+
+ color = ColorUtils.generateAlertColorFromDrawable(icon);
+ mGeneratedPackageLedColors.put(mapping, color);
+
+ return color;
+ }
+
+ private String mapPackage(String pkg) {
+ if (!mPackageNameMappings.containsKey(pkg)) {
+ return pkg;
+ }
+ return mPackageNameMappings.get(pkg);
+ }
+
// lock on mNotificationList
int indexOfNotificationLocked(String pkg, String tag, int id, int userId)
{
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index cd043cc..468ef8d 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -53,6 +53,7 @@ import android.util.SparseArray;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.server.LocalServices;
+import cyanogenmod.providers.CMSettings;
import libcore.io.IoUtils;
@@ -89,6 +90,7 @@ public class ZenModeHelper {
private ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
private boolean mEffectsSuppressed;
+ private boolean mAllowLights;
public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
mContext = context;
@@ -378,6 +380,7 @@ public class ZenModeHelper {
ZenLog.traceSetZenMode(zen, reason);
mZenMode = zen;
updateRingerModeAffectedStreams();
+ readAllowLightsFromSettings();
setZenModeSetting(mZenMode);
if (setRingerMode) {
applyZenToRingerMode();
@@ -407,6 +410,24 @@ public class ZenModeHelper {
return zen;
}
+ public boolean getAllowLights() {
+ return mAllowLights;
+ }
+
+ public void readAllowLightsFromSettings() {
+ switch (mZenMode) {
+ case Global.ZEN_MODE_NO_INTERRUPTIONS:
+ case Global.ZEN_MODE_ALARMS:
+ mAllowLights = CMSettings.System.getInt(mContext.getContentResolver(),
+ CMSettings.System.ZEN_ALLOW_LIGHTS, 1) == 1;
+ break;
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ mAllowLights = CMSettings.System.getInt(mContext.getContentResolver(),
+ CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS, 1) == 1;
+ break;
+ }
+ }
+
private void applyRestrictions() {
final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
@@ -421,6 +442,8 @@ public class ZenModeHelper {
// alarm restrictions
final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
applyRestrictions(muteAlarms, USAGE_ALARM);
+
+ readAllowLightsFromSettings();
}
private void applyRestrictions(boolean mute, int usage) {
@@ -691,6 +714,10 @@ public class ZenModeHelper {
private final class SettingsObserver extends ContentObserver {
private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
+ private final Uri ZEN_ALLOW_LIGHTS = CMSettings.System.getUriFor(
+ CMSettings.System.ZEN_ALLOW_LIGHTS);
+ private final Uri ZEN_PRIORITY_ALLOW_LIGHTS = CMSettings.System.getUriFor(
+ CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS);
public SettingsObserver(Handler handler) {
super(handler);
@@ -699,6 +726,10 @@ public class ZenModeHelper {
public void observe() {
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
+ resolver.registerContentObserver(
+ ZEN_ALLOW_LIGHTS, false /*notifyForDescendents*/, this);
+ resolver.registerContentObserver(
+ ZEN_PRIORITY_ALLOW_LIGHTS, false /*notifyForDescendents*/, this);
update(null);
}
@@ -713,6 +744,8 @@ public class ZenModeHelper {
if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
setZenModeSetting(mZenMode);
}
+ } else if (ZEN_ALLOW_LIGHTS.equals(uri) || ZEN_PRIORITY_ALLOW_LIGHTS.equals(uri)) {
+ readAllowLightsFromSettings();
}
}
}
diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java
index 52d0928..cab4691 100644
--- a/services/core/java/com/android/server/pm/BasePermission.java
+++ b/services/core/java/com/android/server/pm/BasePermission.java
@@ -53,6 +53,8 @@ final class BasePermission {
*/
private boolean perUser;
+ boolean allowViaWhitelist;
+
BasePermission(String _name, String _sourcePackage, int _type) {
name = _name;
sourcePackage = _sourcePackage;
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 8abc8fc..29e9fa6 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -20,6 +20,7 @@ import android.Manifest;
import android.app.DownloadManager;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal.PackagesProvider;
@@ -608,7 +609,6 @@ final class DefaultPermissionGrantPolicy {
}
}
-
private void grantDefaultPermissionsToDefaultSystemSmsAppLPr(
PackageParser.Package smsPackage, int userId) {
if (doesPackageSupportRuntimePermissions(smsPackage)) {
@@ -618,7 +618,6 @@ final class DefaultPermissionGrantPolicy {
}
}
-
public void grantDefaultPermissionsToDefaultSmsAppLPr(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default sms app for user:" + userId);
if (packageName == null) {
@@ -696,29 +695,23 @@ final class DefaultPermissionGrantPolicy {
private PackageParser.Package getDefaultSystemHandlerActivityPackageLPr(
Intent intent, int userId) {
- List<ResolveInfo> handlers = mService.mActivities.queryIntent(intent,
- intent.resolveType(mService.mContext.getContentResolver()),
- PackageManager.GET_DISABLED_COMPONENTS, userId);
- if (handlers == null) {
+ ResolveInfo handler = mService.resolveIntent(intent,
+ intent.resolveType(mService.mContext.getContentResolver()), 0, userId);
+ if (handler == null || handler.activityInfo == null) {
return null;
}
- final int handlerCount = handlers.size();
- for (int i = 0; i < handlerCount; i++) {
- ResolveInfo handler = handlers.get(i);
- PackageParser.Package handlerPackage = getSystemPackageLPr(
- handler.activityInfo.packageName);
- if (handlerPackage != null) {
- return handlerPackage;
- }
+ ActivityInfo activityInfo = handler.activityInfo;
+ if (activityInfo.packageName.equals(mService.mResolveActivity.packageName)
+ && activityInfo.name.equals(mService.mResolveActivity.name)) {
+ return null;
}
- return null;
+ return getSystemPackageLPr(handler.activityInfo.packageName);
}
private PackageParser.Package getDefaultSystemHandlerServicePackageLPr(
Intent intent, int userId) {
List<ResolveInfo> handlers = mService.queryIntentServices(intent,
- intent.resolveType(mService.mContext.getContentResolver()),
- PackageManager.GET_DISABLED_COMPONENTS, userId);
+ intent.resolveType(mService.mContext.getContentResolver()), 0, userId);
if (handlers == null) {
return null;
}
@@ -744,10 +737,9 @@ final class DefaultPermissionGrantPolicy {
for (String syncAdapterPackageName : syncAdapterPackageNames) {
homeIntent.setPackage(syncAdapterPackageName);
- List<ResolveInfo> homeActivities = mService.mActivities.queryIntent(homeIntent,
- homeIntent.resolveType(mService.mContext.getContentResolver()),
- PackageManager.GET_DISABLED_COMPONENTS, userId);
- if (!homeActivities.isEmpty()) {
+ ResolveInfo homeActivity = mService.resolveIntent(homeIntent,
+ homeIntent.resolveType(mService.mContext.getContentResolver()), 0, userId);
+ if (homeActivity != null) {
continue;
}
@@ -866,7 +858,7 @@ final class DefaultPermissionGrantPolicy {
return false;
}
PackageSetting sysPkg = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
- if (sysPkg != null) {
+ if (sysPkg != null && sysPkg.pkg != null) {
if ((sysPkg.pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
return false;
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index f292c9c..4be7e25 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -110,14 +110,53 @@ public final class Installer extends SystemService {
debuggable, outputPath, bootComplete);
}
- public int idmap(String targetApkPath, String overlayApkPath, int uid) {
+ public int idmap(String targetApkPath, String overlayApkPath, String cachePath,
+ int uid, int targetHash, int overlayHash) {
StringBuilder builder = new StringBuilder("idmap");
builder.append(' ');
builder.append(targetApkPath);
builder.append(' ');
builder.append(overlayApkPath);
builder.append(' ');
+ builder.append(cachePath);
+ builder.append(' ');
+ builder.append(uid);
+ builder.append(' ');
+ builder.append(targetHash);
+ builder.append(' ');
+ builder.append(overlayHash);
+ return mInstaller.execute(builder.toString());
+ }
+
+ public int aapt(String themeApkPath, String internalPath, String resTablePath, int uid,
+ int pkgId, int minSdkVersion, String appResourcesPath, String commonResourcesPath) {
+
+ StringBuilder builder = new StringBuilder();
+ if (TextUtils.isEmpty(commonResourcesPath)) {
+ builder.append("aapt");
+ } else {
+ builder.append("aapt_with_common");
+ }
+ builder.append(' ');
+ builder.append(themeApkPath);
+ builder.append(' ');
+ builder.append(internalPath);
+ builder.append(' ');
+ builder.append(resTablePath);
+ builder.append(' ');
builder.append(uid);
+ builder.append(' ');
+ builder.append(pkgId);
+ builder.append(' ');
+ builder.append(minSdkVersion);
+ builder.append(' ');
+ builder.append(appResourcesPath);
+
+ if (!TextUtils.isEmpty(commonResourcesPath)) {
+ builder.append(' ');
+ builder.append(commonResourcesPath);
+ }
+
return mInstaller.execute(builder.toString());
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b692def..f73cb0a 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
+import android.os.Environment;
import android.os.PowerManager;
import android.os.UserHandle;
import android.os.WorkSource;
@@ -224,6 +225,11 @@ final class PackageDexOptimizer {
File codePath = new File(pkg.codePath);
if (codePath.isDirectory()) {
File oatDir = getOatDir(codePath);
+ // skip the prebundled apps dir since it's actually read-only
+ if (oatDir.getAbsolutePath().startsWith(
+ Environment.getPrebundledDirectory().getAbsolutePath())) {
+ return null;
+ }
mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
dexInstructionSet);
return oatDir.getAbsolutePath();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 4a473fd..65f5bce 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -381,7 +381,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (stageDir != null && deltaBytes > 0) {
mPm.freeStorage(params.volumeUuid, deltaBytes);
}
- Libcore.os.posix_fallocate(targetFd, 0, lengthBytes);
+ try {
+ Libcore.os.posix_fallocate(targetFd, 0, lengthBytes);
+ } catch (ErrnoException e) {
+ if (e.errno == OsConstants.ENOTSUP) {
+ Libcore.os.ftruncate(targetFd, lengthBytes);
+ } else {
+ throw e.rethrowAsIOException();
+ }
+ }
}
if (offsetBytes > 0) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c1d091b..d5c58df 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +43,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
+import static android.content.pm.PackageManager.INSTALL_FAILED_REGION_LOCKED_PREBUNDLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY;
@@ -64,6 +66,7 @@ import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.INSTALL_FAILED_UNINSTALLED_PREBUNDLE;
import static android.content.pm.PackageParser.isApkFile;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
@@ -82,12 +85,23 @@ import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
+import static com.android.internal.util.ArrayUtils.removeInt;
+
+import android.content.res.Configuration;
import android.Manifest;
+
+import cyanogenmod.app.CMContextConstants;
+import cyanogenmod.app.suggest.AppSuggestManager;
+
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
+import android.app.ComposedIconInfo;
+import android.app.AppOpsManager;
import android.app.IActivityManager;
+import android.app.IconPackHelper;
+import android.app.PackageInstallObserver;
import android.app.admin.IDevicePolicyManager;
import android.app.backup.IBackupManager;
import android.app.usage.UsageStats;
@@ -129,6 +143,9 @@ import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageStats;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageParser.Activity;
+import android.content.pm.PackageParser.Package;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
@@ -138,10 +155,13 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
+import android.content.pm.ManifestDigest;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.content.res.Resources;
+import android.content.res.AssetManager;
+import android.content.res.ThemeConfig;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Debug;
@@ -172,6 +192,8 @@ import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.provider.Settings.Global;
+import android.provider.Settings.Secure;
import android.security.KeyStore;
import android.security.SystemKeyStore;
import android.system.ErrnoException;
@@ -188,6 +210,7 @@ import android.util.ExceptionUtils;
import android.util.Log;
import android.util.LogPrinter;
import android.util.MathUtils;
+import android.util.Pair;
import android.util.PrintStreamPrinter;
import android.util.Slog;
import android.util.SparseArray;
@@ -196,6 +219,9 @@ import android.util.SparseIntArray;
import android.util.Xml;
import android.view.Display;
+import cyanogenmod.providers.CMSettings;
+import cyanogenmod.themes.IThemeService;
+
import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
@@ -228,6 +254,7 @@ import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.pm.Settings.VersionInfo;
import com.android.server.storage.DeviceStorageMonitorInternal;
+import org.cyanogenmod.internal.util.ThemeUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -237,16 +264,25 @@ import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.BufferedWriter;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
+import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateEncodingException;
@@ -298,6 +334,8 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_VERIFY = false;
private static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
+ private static final boolean DEBUG_PREBUNDLED_SCAN = false;
+ private static final boolean DEBUG_PROTECTED = false;
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
@@ -339,7 +377,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* minute but we sometimes do very lengthy I/O operations on this thread,
* such as installing multi-gigabyte applications, so ours needs to be longer.
*/
- private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
+ private static final long WATCHDOG_TIMEOUT = 1000*60*60; // sixty minutes
/**
* Wall-clock timeout (in milliseconds) after which we *require* that an fstrim
@@ -414,6 +452,24 @@ public class PackageManagerService extends IPackageManager.Stub {
final ServiceThread mHandlerThread;
+ //Where overlays are be found in a theme APK
+ private static final String APK_PATH_TO_OVERLAY = "assets/overlays/";
+
+ //Where the icon pack can be found in a themed apk
+ private static final String APK_PATH_TO_ICONS = "assets/icons/";
+
+ private static final String COMMON_OVERLAY = ThemeUtils.COMMON_RES_TARGET;
+
+ private static final long COMMON_RESOURCE_EXPIRATION = 3*60*1000; // 3 minutes
+
+ private static final String PROTECTED_APPS_TARGET_VALIDATION_COMPONENT =
+ "com.android.settings/com.android.settings.applications.ProtectedAppsActivity";
+
+ /**
+ * The offset in bytes to the beginning of the hashes in an idmap
+ */
+ private static final int IDMAP_HASH_START_OFFSET = 16;
+
final PackageHandler mHandler;
/**
@@ -500,10 +556,13 @@ public class PackageManagerService extends IPackageManager.Stub {
final Settings mSettings;
boolean mRestoredSettings;
+ private Resources mCustomResources;
+
// System configuration read by SystemConfig.
final int[] mGlobalGids;
final SparseArray<ArraySet<String>> mSystemPermissions;
final ArrayMap<String, FeatureInfo> mAvailableFeatures;
+ final ArrayMap<Signature, ArraySet<String>> mSignatureAllowances;
// If mac_permissions.xml was found for seinfo labeling.
boolean mFoundPolicyFile;
@@ -819,6 +878,16 @@ public class PackageManagerService extends IPackageManager.Stub {
private IntentFilterVerifier mIntentFilterVerifier;
+ private IconPackHelper mIconPackHelper;
+
+ private Map<String, Long> mAvailableCommonResources = new ArrayMap<String, Long>();
+
+ private ThemeConfig mBootThemeConfig;
+
+ ArrayList<ComponentName> mDisabledComponentsList;
+
+ private AppOpsManager mAppOps;
+
// Set of pending broadcasts for aggregating enable/disable of components.
static class PendingPackageBroadcasts {
// for each user id, a map of <package name -> components within that package>
@@ -1388,18 +1457,23 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, null, null, firstUsers);
+ packageName, null, extras, null, null, firstUsers);
final boolean update = res.removedInfo.removedPackage != null;
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
+ String category = null;
+ if(res.pkg.mIsThemeApk) {
+ category = cyanogenmod.content.Intent
+ .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, null, null, updateUsers);
+ packageName, null, extras, null, null, updateUsers);
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- packageName, extras, null, null, updateUsers);
+ packageName, null, extras, null, null, updateUsers);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
- null, null, packageName, null, updateUsers);
+ null, null, null, packageName, null, updateUsers);
// treat asec-hosted packages like removable media on upgrade
if (res.pkg.isForwardLocked() || isExternal(res.pkg)) {
@@ -1414,6 +1488,10 @@ public class PackageManagerService extends IPackageManager.Stub {
pkgList,uidArray, null);
}
}
+ // if this was a theme, send it off to the theme service for processing
+ if(res.pkg.mIsThemeApk || res.pkg.mIsLegacyIconPackApk) {
+ processThemeResourcesInThemeService(res.pkg.packageName);
+ }
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
deleteOld = true;
@@ -1432,6 +1510,17 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
+ if (!update && !isSystemApp(res.pkg)) {
+ boolean privacyGuard = CMSettings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ CMSettings.Secure.PRIVACY_GUARD_DEFAULT,
+ 0, UserHandle.USER_CURRENT) == 1;
+ if (privacyGuard) {
+ mAppOps.setPrivacyGuardSettingForPackage(
+ res.pkg.applicationInfo.uid,
+ res.pkg.applicationInfo.packageName, true);
+ }
+ }
// Log current value of "unknown sources" setting
EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
getUnknownSourcesSettings());
@@ -1810,7 +1899,9 @@ public class PackageManagerService extends IPackageManager.Stub {
mContext = context;
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
- mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
+ mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type")) ||
+ ("userdebug".equals(SystemProperties.get("ro.build.type")) &&
+ SystemProperties.getBoolean("persist.sys.lazy.dexopt", false));
mMetrics = new DisplayMetrics();
mSettings = new Settings(mPackages);
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
@@ -1835,6 +1926,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
+ mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
@@ -1861,10 +1954,13 @@ public class PackageManagerService extends IPackageManager.Stub {
getDefaultDisplayMetrics(context, mMetrics);
+ removeLegacyResourceCache();
+
SystemConfig systemConfig = SystemConfig.getInstance();
mGlobalGids = systemConfig.getGlobalGids();
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
+ mSignatureAllowances = systemConfig.getSignatureAllowances();
synchronized (mInstallLock) {
// writer
@@ -1910,10 +2006,13 @@ public class PackageManagerService extends IPackageManager.Stub {
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false),
- mSdkVersion, mOnlyCore);
+ mSdkVersion, mOnlyCore, mInstaller);
- String customResolverActivity = Resources.getSystem().getString(
- R.string.config_customResolverActivity);
+ String customResolverActivity = SystemProperties.get("ro.custom.resolver.activity");
+ if (TextUtils.isEmpty(customResolverActivity)) {
+ customResolverActivity = Resources.getSystem().getString(
+ R.string.config_customResolverActivity);
+ }
if (TextUtils.isEmpty(customResolverActivity)) {
customResolverActivity = null;
} else {
@@ -2005,6 +2104,10 @@ public class PackageManagerService extends IPackageManager.Stub {
// avoid the resulting log spew.
alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
+ // Gross hack for now: we know this file doesn't contain any
+ // code, so don't dexopt it to avoid the resulting log spew
+ alreadyDexOpted.add(frameworkDir.getPath() + "/org.cyanogenmod.platform-res.apk");
+
/**
* There are a number of commands implemented in Java, which
* we currently need to do the dexopt on so that they can be
@@ -2042,7 +2145,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final VersionInfo ver = mSettings.getInternalVersion();
- mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
+ mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint) ||
+ !Build.DISPLAY.equals(ver.displayversion);
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
@@ -2059,30 +2163,32 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ mBootThemeConfig = ThemeConfig.getSystemTheme();
+
// Collect vendor overlay packages.
// (Do this before scanning any apps.)
// For security and version matching reason, only consider
// overlay packages if they reside in VENDOR_OVERLAY_DIR.
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0, null);
// Find base frameworks (resource packages without code).
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
- scanFlags | SCAN_NO_DEX, 0);
+ scanFlags | SCAN_NO_DEX, 0, null);
// Collected privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
- | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
+ | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0, null);
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0, null);
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
@@ -2092,12 +2198,19 @@ public class PackageManagerService extends IPackageManager.Stub {
// failed to look up canonical path, continue with original one
}
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0, null);
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0, null);
+
+ // Collect all prebundled packages.
+ createAndSetCustomResources();
+ scanDirLI(Environment.getPrebundledDirectory(),
+ PackageParser.PARSE_IS_PREBUNDLED_DIR, scanFlags, 0, UserHandle.OWNER);
+ // Clean up
+ mCustomResources = null;
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles();
@@ -2172,10 +2285,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
- scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
+ scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0, null);
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
- scanFlags | SCAN_REQUIRE_KNOWN, 0);
+ scanFlags | SCAN_REQUIRE_KNOWN, 0, null);
/**
* Remove disable package settings for any updated system
@@ -2288,6 +2401,12 @@ public class PackageManagerService extends IPackageManager.Stub {
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
+ // Remove any stale app permissions (declared permission that now are undeclared
+ // by the same app, removed from its Manifest in newer versions)
+ if (!onlyCore) {
+ mSettings.removeStalePermissions();
+ }
+
// If this is the first boot or an update from pre-M, and it is a normal
// boot, then we need to initialize the default preferred apps across
// all defined users.
@@ -2299,10 +2418,42 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ // Disable components marked for disabling at build-time
+ mDisabledComponentsList = new ArrayList<ComponentName>();
+ for (String name : mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_disabledComponents)) {
+ ComponentName cn = ComponentName.unflattenFromString(name);
+ mDisabledComponentsList.add(cn);
+ Slog.v(TAG, "Disabling " + name);
+ String className = cn.getClassName();
+ PackageSetting pkgSetting = mSettings.mPackages.get(cn.getPackageName());
+ if (pkgSetting == null || pkgSetting.pkg == null
+ || !pkgSetting.pkg.hasComponentClassName(className)) {
+ Slog.w(TAG, "Unable to disable " + name);
+ continue;
+ }
+ pkgSetting.disableComponentLPw(className, UserHandle.USER_OWNER);
+ }
+
+ // Enable components marked for forced-enable at build-time
+ for (String name : mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_forceEnabledComponents)) {
+ ComponentName cn = ComponentName.unflattenFromString(name);
+ Slog.v(TAG, "Enabling " + name);
+ String className = cn.getClassName();
+ PackageSetting pkgSetting = mSettings.mPackages.get(cn.getPackageName());
+ if (pkgSetting == null || pkgSetting.pkg == null
+ || !pkgSetting.pkg.hasComponentClassName(className)) {
+ Slog.w(TAG, "Unable to enable " + name);
+ continue;
+ }
+ pkgSetting.enableComponentLPw(className, UserHandle.USER_OWNER);
+ }
+
// If this is first boot after an OTA, and a normal boot, then
// we need to clear code cache directories.
if (mIsUpgrade && !onlyCore) {
- Slog.i(TAG, "Build fingerprint changed; clearing code caches");
+ Slog.i(TAG, "Build fingerprint or displayversion changed; clearing code caches");
for (int i = 0; i < mSettings.mPackages.size(); i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
@@ -2310,6 +2461,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
ver.fingerprint = Build.FINGERPRINT;
+ ver.displayversion = Build.DISPLAY;
}
checkDefaultBrowser();
@@ -3345,6 +3497,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
// We'll take care of setting this one.
if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
+ if (pi1.allowViaWhitelist != pi2.allowViaWhitelist) return false;
// These are not currently stored in settings.
//if (!compareStrings(pi1.group, pi2.group)) return false;
//if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
@@ -3469,6 +3622,16 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ private boolean isAllowedSignature(PackageParser.Package pkg, String permissionName) {
+ for (Signature pkgSig : pkg.mSignatures) {
+ ArraySet<String> perms = mSignatureAllowances.get(pkgSig);
+ if (perms != null && perms.contains(permissionName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void grantRuntimePermission(String packageName, String name, final int userId) {
if (!sUserManager.exists(userId)) {
@@ -3963,7 +4126,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.SIGNATURE_NO_MATCH;
}
- // Since both signature sets are of size 1, we can compare without HashSets.
+ // Since both signature sets are of size 1, we can compare without ArraySets.
if (s1.length == 1) {
return s1[0].equals(s2[0]) ?
PackageManager.SIGNATURE_MATCH :
@@ -4266,6 +4429,17 @@ public class PackageManagerService extends IPackageManager.Stub {
if (ri.activityInfo.metaData == null) ri.activityInfo.metaData = new Bundle();
ri.activityInfo.metaData.putBoolean(Intent.METADATA_DOCK_HOME, true);
return ri;
+ } else if (shouldIncludeResolveActivity(intent)) {
+ if (userId != 0) {
+ ResolveInfo ri = new ResolveInfo(mResolveInfo);
+ ri.activityInfo = new ActivityInfo(ri.activityInfo);
+ ri.activityInfo.applicationInfo = new ApplicationInfo(
+ ri.activityInfo.applicationInfo);
+ ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
+ UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
+ return ri;
+ }
+ return mResolveInfo;
}
}
return null;
@@ -4526,6 +4700,13 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
+ private boolean shouldIncludeResolveActivity(Intent intent) {
+ synchronized(mPackages) {
+ AppSuggestManager suggest = AppSuggestManager.getInstance(mContext);
+ return mResolverReplaced && (suggest != null) ? suggest.handles(intent) : false;
+ }
+ }
+
@Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
String resolvedType, int flags, int userId) {
@@ -5586,11 +5767,17 @@ public class PackageManagerService extends IPackageManager.Stub {
private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
PackageParser.Package opkg) {
+ if (DEBUG_PACKAGE_SCANNING) Log.d(TAG,
+ "Generating idmaps between " + pkg.packageName + ":" + opkg.packageName);
if (!opkg.mTrustedOverlay) {
Slog.w(TAG, "Skipping target and overlay pair " + pkg.baseCodePath + " and " +
opkg.baseCodePath + ": overlay not trusted");
return false;
}
+
+ // Some apps like to take on the package name of an existing app so we'll use the
+ // "real" package name, if it is non-null, when performing the idmap
+ final String pkgName = pkg.mRealPackage != null ? pkg.mRealPackage : pkg.packageName;
ArrayMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
if (overlaySet == null) {
Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " +
@@ -5598,30 +5785,19 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
- // TODO: generate idmap for split APKs
- if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid) != 0) {
- Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
- + opkg.baseCodePath);
+ final String cachePath =
+ ThemeUtils.getTargetCacheDir(pkgName, opkg.packageName);
+ if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, cachePath, sharedGid,
+ pkg.manifestHashCode, opkg.manifestHashCode) != 0) {
+ Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath +
+ " and " + opkg.baseCodePath);
return false;
}
- PackageParser.Package[] overlayArray =
- overlaySet.values().toArray(new PackageParser.Package[0]);
- Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
- public int compare(PackageParser.Package p1, PackageParser.Package p2) {
- return p1.mOverlayPriority - p2.mOverlayPriority;
- }
- };
- Arrays.sort(overlayArray, cmp);
-
- pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
- int i = 0;
- for (PackageParser.Package p : overlayArray) {
- pkg.applicationInfo.resourceDirs[i++] = p.baseCodePath;
- }
return true;
}
- private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
+ private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime,
+ UserHandle user) {
final File[] files = dir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + dir);
@@ -5633,6 +5809,16 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " flags=0x" + Integer.toHexString(parseFlags));
}
+ int prebundledUserId = user == null ? UserHandle.USER_OWNER : user.getIdentifier();
+ boolean isPrebundled = (parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0;
+ if (isPrebundled) {
+ synchronized (mPackages) {
+ if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, "Reading prebundled packages for user "
+ + prebundledUserId);
+ mSettings.readPrebundledPackagesLPr(prebundledUserId);
+ }
+ }
+
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
@@ -5642,7 +5828,27 @@ public class PackageManagerService extends IPackageManager.Stub {
}
try {
scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
- scanFlags, currentTime, null);
+ scanFlags, currentTime, user);
+ if (isPrebundled) {
+ final PackageParser.Package pkg;
+ try {
+ pkg = new PackageParser().parsePackage(file, parseFlags);
+ } catch (PackageParserException e) {
+ throw PackageManagerException.from(e);
+ }
+ synchronized (mPackages) {
+ if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG,
+ "Marking prebundled packages for user " + prebundledUserId);
+ mSettings.markPrebundledPackageInstalledLPr(prebundledUserId,
+ pkg.packageName);
+ // do this for every other user
+ for (UserInfo userInfo : sUserManager.getUsers(true)) {
+ if (userInfo.id == prebundledUserId) continue;
+ mSettings.markPrebundledPackageInstalledLPr(userInfo.id,
+ pkg.packageName);
+ }
+ }
+ }
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
@@ -5658,6 +5864,14 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
+
+ if (isPrebundled) {
+ synchronized (mPackages) {
+ if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, "Writing prebundled packages for user "
+ + prebundledUserId);
+ mSettings.writePrebundledPackagesLPr(prebundledUserId);
+ }
+ }
}
private static File getSettingsProblemFile() {
@@ -5711,6 +5925,12 @@ public class PackageManagerService extends IPackageManager.Stub {
// if the package appears to be unchanged.
pkg.mSignatures = ps.signatures.mSignatures;
pkg.mSigningKeys = signingKs;
+ // Collect manifest digest
+ try{
+ pp.collectManifestDigest(pkg);
+ } catch (PackageParserException e) {
+ throw PackageManagerException.from(e);
+ }
return;
}
@@ -5730,7 +5950,7 @@ public class PackageManagerService extends IPackageManager.Stub {
/*
* Scan a package and return the newly parsed package.
- * Returns null in case of errors and the error code is stored in mLastScanError
+ * Returns null in case of errors and the error code is stored in
*/
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
@@ -5752,6 +5972,36 @@ public class PackageManagerService extends IPackageManager.Stub {
throw PackageManagerException.from(e);
}
+ if ((parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0) {
+ synchronized (mPackages) {
+ PackageSetting existingSettings = mSettings.peekPackageLPr(pkg.packageName);
+ if (mSettings.wasPrebundledPackageInstalledLPr(user.getIdentifier()
+ , pkg.packageName) && existingSettings == null) {
+ // The prebundled app was installed at some point in time, but now it is
+ // gone. Assume that the user uninstalled it intentionally: do not reinstall.
+ throw new PackageManagerException(INSTALL_FAILED_UNINSTALLED_PREBUNDLE,
+ "skip reinstall for " + pkg.packageName);
+ } else if (existingSettings == null &&
+ !mSettings.shouldPrebundledPackageBeInstalled(mContext.getResources(),
+ pkg.packageName, mCustomResources)) {
+ // The prebundled app is not needed for the default mobile country code,
+ // skip installing it
+ throw new PackageManagerException(INSTALL_FAILED_REGION_LOCKED_PREBUNDLE,
+ "skip install for " + pkg.packageName);
+ } else if (existingSettings != null
+ && existingSettings.versionCode >= pkg.mVersionCode
+ && !existingSettings.codePathString.contains(
+ Environment.getPrebundledDirectory().getPath())) {
+ // This app is installed in a location that is not the prebundled location
+ // and has a higher (or same) version as the prebundled one. Skip
+ // installing the prebundled version.
+ Slog.d(TAG, pkg.packageName + " already installed at " +
+ existingSettings.codePathString);
+ return null; // return null so we still mark package as installed
+ }
+ }
+ }
+
PackageSetting ps = null;
PackageSetting updatedPkg;
// reader
@@ -6177,13 +6427,11 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_DEXOPT) {
Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName);
}
- if (!isFirstBoot()) {
- try {
- ActivityManagerNative.getDefault().showBootMessage(
- mContext.getResources().getString(R.string.android_upgrading_apk,
- curr, total), true);
- } catch (RemoteException e) {
- }
+ try {
+ ActivityManagerNative.getDefault().showBootMessage(
+ mContext.getResources().getString(R.string.android_upgrading_apk,
+ curr, total), true);
+ } catch (RemoteException e) {
}
PackageParser.Package p = pkg;
synchronized (mInstallLock) {
@@ -6584,6 +6832,20 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ if (Build.TAGS.equals("test-keys") &&
+ !pkg.applicationInfo.sourceDir.startsWith(Environment.getRootDirectory().getPath()) &&
+ !pkg.applicationInfo.sourceDir.startsWith("/vendor")) {
+ Object obj = mSettings.getUserIdLPr(1000);
+ Signature[] s1 = null;
+ if (obj instanceof SharedUserSetting) {
+ s1 = ((SharedUserSetting)obj).signatures.mSignatures;
+ }
+ if ((compareSignatures(pkg.mSignatures, s1) == PackageManager.SIGNATURE_MATCH)) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+ "Cannot install platform packages to user storage!");
+ }
+ }
+
// Initialize package source and resource directories
File destCodeFile = new File(pkg.applicationInfo.getCodePath());
File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
@@ -6598,6 +6860,16 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.mAdoptPermissions = null;
}
+ // collect manifest digest which includes getting manifest hash code for themes
+ if (pkg.manifestDigest == null || pkg.manifestHashCode == 0) {
+ PackageParser pp = new PackageParser();
+ try {
+ pp.collectManifestDigest(pkg);
+ } catch (PackageParserException e) {
+ Slog.w(TAG, "Unable to collect manifest digest", e);
+ }
+ }
+
// writer
synchronized (mPackages) {
if (pkg.mSharedUserId != null) {
@@ -6963,7 +7235,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
- derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);
+ derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */, parseFlags);
// Some system apps still use directory structure for native libraries
// in which case we might end up not detecting abi solely based on apk
@@ -6971,7 +7243,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
pkg.applicationInfo.primaryCpuAbi == null) {
setBundledAppAbisAndRoots(pkg, pkgSetting);
- setNativeLibraryPaths(pkg);
+ setNativeLibraryPaths(pkg, parseFlags);
}
} else {
@@ -6987,7 +7259,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// ABIs we've determined above. For non-moves, the path will be updated based on the
// ABIs we determined during compilation, but the path will depend on the final
// package path (after the rename away from the stage path).
- setNativeLibraryPaths(pkg);
+ setNativeLibraryPaths(pkg, parseFlags);
}
if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
@@ -7192,6 +7464,13 @@ public class PackageManagerService extends IPackageManager.Stub {
// Add the new setting to mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
+
+ // Themes: handle case where app was installed after icon mapping applied
+ if (mIconPackHelper != null) {
+ int id = mIconPackHelper.getResourceIdForApp(pkg.packageName);
+ pkg.applicationInfo.themedIcon = id;
+ }
+
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// Make sure we don't accidentally delete its data.
@@ -7330,6 +7609,13 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
+
+ // Themes: handle case where app was installed after icon mapping applied
+ if (mIconPackHelper != null) {
+ a.info.themedIcon = mIconPackHelper
+ .getResourceIdForActivityIcon(a.info);
+ }
+
mActivities.addActivity(a, "activity");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
@@ -7415,6 +7701,7 @@ public class PackageManagerService extends IPackageManager.Stub {
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
bp.sourcePackage = p.info.packageName;
+ bp.allowViaWhitelist = p.info.allowViaWhitelist;
p.info.flags |= PermissionInfo.FLAG_INSTALLED;
} else if (!currentOwnerIsSystem) {
String msg = "New decl " + p.owner + " of permission "
@@ -7428,6 +7715,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (bp == null) {
bp = new BasePermission(p.info.name, p.info.packageName,
BasePermission.TYPE_NORMAL);
+ bp.allowViaWhitelist = p.info.allowViaWhitelist;
permissionMap.put(p.info.name, bp);
}
@@ -7441,6 +7729,7 @@ public class PackageManagerService extends IPackageManager.Stub {
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
bp.sourcePackage = p.info.packageName;
+ bp.allowViaWhitelist = p.info.allowViaWhitelist;
p.info.flags |= PermissionInfo.FLAG_INSTALLED;
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
@@ -7516,27 +7805,83 @@ public class PackageManagerService extends IPackageManager.Stub {
pkgSetting.setTimeStamp(scanFileTime);
- // Create idmap files for pairs of (packages, overlay packages).
- // Note: "android", ie framework-res.apk, is handled by native layers.
- if (pkg.mOverlayTarget != null) {
- // This is an overlay package.
- if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
- if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
- mOverlays.put(pkg.mOverlayTarget,
- new ArrayMap<String, PackageParser.Package>());
+ final boolean isBootScan = (scanFlags & SCAN_BOOTING) != 0;
+ // Generate resources & idmaps if pkg is NOT a theme
+ // We must compile resources here because during the initial boot process we may get
+ // here before a default theme has had a chance to compile its resources
+ if (pkg.mOverlayTargets.isEmpty() && mOverlays.containsKey(pkg.packageName)) {
+ ArrayMap<String, PackageParser.Package> themes = mOverlays.get(pkg.packageName);
+ for(PackageParser.Package themePkg : themes.values()) {
+ if (!isBootScan || (mBootThemeConfig != null &&
+ (themePkg.packageName.equals(mBootThemeConfig.getOverlayPkgName()) ||
+ themePkg.packageName.equals(
+ mBootThemeConfig.getOverlayPkgNameForApp(pkg.packageName))))) {
+ try {
+ compileResourcesAndIdmapIfNeeded(pkg, themePkg);
+ } catch (Exception e) {
+ // Do not stop a pkg installation just because of one bad theme
+ // Also we don't break here because we should try to compile other
+ // themes
+ Slog.w(TAG, "Unable to compile " + themePkg.packageName
+ + " for target " + pkg.packageName, e);
+ themePkg.mOverlayTargets.remove(pkg.packageName);
+ }
}
- ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
- map.put(pkg.packageName, pkg);
- PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
- if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
- throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
- "scanPackageLI failed to createIdmap");
+ }
+ }
+
+ // If this is a theme we should re-compile common resources if they exist so
+ // remove this package from mAvailableCommonResources.
+ if (!isBootScan && pkg.mOverlayTargets.size() > 0) {
+ mAvailableCommonResources.remove(pkg.packageName);
+ }
+
+ // Generate Idmaps and res tables if pkg is a theme
+ Iterator<String> iterator = pkg.mOverlayTargets.iterator();
+ while(iterator.hasNext()) {
+ String target = iterator.next();
+ Exception failedException = null;
+
+ insertIntoOverlayMap(target, pkg);
+ if (isBootScan && mBootThemeConfig != null &&
+ (pkg.packageName.equals(mBootThemeConfig.getOverlayPkgName()) ||
+ pkg.packageName.equals(
+ mBootThemeConfig.getOverlayPkgNameForApp(target)))) {
+ try {
+ compileResourcesAndIdmapIfNeeded(mPackages.get(target), pkg);
+ } catch (IdmapException e) {
+ failedException = e;
+ } catch (AaptException e) {
+ failedException = e;
+ } catch (Exception e) {
+ failedException = e;
+ }
+
+ if (failedException != null) {
+ Slog.w(TAG, "Unable to process theme " + pkgName + " for " + target,
+ failedException);
+ // remove target from mOverlayTargets
+ iterator.remove();
+ }
+ }
+ }
+
+ //Icon Packs need aapt too
+ if (isBootScan && (mBootThemeConfig != null &&
+ pkg.packageName.equals(mBootThemeConfig.getIconPackPkgName()))) {
+ if (isIconCompileNeeded(pkg)) {
+ try {
+ ThemeUtils.createCacheDirIfNotExists();
+ ThemeUtils.createIconDirIfNotExists(pkg.packageName);
+ compileIconPack(pkg);
+ } catch (Exception e) {
+ uninstallThemeForAllApps(pkg);
+ deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_THEME_AAPT_ERROR,
+ "Unable to process theme " + pkgName);
}
}
- } else if (mOverlays.containsKey(pkg.packageName) &&
- !pkg.packageName.equals("android")) {
- // This is a regular package, with one or more known overlay packages.
- createIdmapsForPackageLI(pkg);
}
}
@@ -7551,7 +7896,8 @@ public class PackageManagerService extends IPackageManager.Stub {
* If {@code extractLibs} is true, native libraries are extracted from the app if required.
*/
public void derivePackageAbi(PackageParser.Package pkg, File scanFile,
- String cpuAbiOverride, boolean extractLibs)
+ String cpuAbiOverride, boolean extractLibs,
+ int parseFlags)
throws PackageManagerException {
// TODO: We can probably be smarter about this stuff. For installed apps,
// we can calculate this information at install time once and for all. For
@@ -7560,7 +7906,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Give ourselves some initial paths; we'll come back for another
// pass once we've determined ABI below.
- setNativeLibraryPaths(pkg);
+ setNativeLibraryPaths(pkg, parseFlags);
// We would never need to extract libs for forward-locked and external packages,
// since the container service will do it for us. We shouldn't attempt to
@@ -7680,7 +8026,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Now that we've calculated the ABIs and determined if it's an internal app,
// we will go ahead and populate the nativeLibraryPath.
- setNativeLibraryPaths(pkg);
+ setNativeLibraryPaths(pkg, parseFlags);
}
/**
@@ -7778,27 +8124,339 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+
+ private boolean isIconCompileNeeded(Package pkg) {
+ if (!pkg.hasIconPack) return false;
+ // Read in the stored hash value and compare to the pkgs computed hash value
+ FileInputStream in = null;
+ DataInputStream dataInput = null;
+ try {
+ String hashFile = ThemeUtils.getIconHashFile(pkg.packageName);
+ in = new FileInputStream(hashFile);
+ dataInput = new DataInputStream(in);
+ int storedHashCode = dataInput.readInt();
+ int actualHashCode = pkg.manifestHashCode;
+ return storedHashCode != actualHashCode;
+ } catch(IOException e) {
+ // all is good enough for government work here,
+ // we'll just return true and the icons will be processed
+ } finally {
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(dataInput);
+ }
+
+ return true;
+ }
+
+ private void compileResourcesAndIdmapIfNeeded(PackageParser.Package targetPkg,
+ PackageParser.Package themePkg) throws IdmapException, AaptException, IOException {
+ if (!shouldCreateIdmap(targetPkg, themePkg)) {
+ return;
+ }
+
+ // Always use the manifest's pkgName when compiling resources
+ // the member value of "packageName" is dependent on whether this was a clean install
+ // or an upgrade w/ If the app is an upgrade then the original package name is used.
+ // because libandroidfw uses the manifests's pkgName during idmap creation we must
+ // be consistent here and use the same name, otherwise idmap will look in the wrong place
+ // for the resource table.
+ String pkgName = targetPkg.mRealPackage != null ?
+ targetPkg.mRealPackage : targetPkg.packageName;
+ compileResourcesIfNeeded(pkgName, themePkg);
+ generateIdmap(targetPkg.packageName, themePkg);
+ }
+
+ private void compileResourcesIfNeeded(String target, PackageParser.Package pkg)
+ throws AaptException, IOException
+ {
+ ThemeUtils.createCacheDirIfNotExists();
+
+ if (hasCommonResources(pkg)
+ && shouldCompileCommonResources(pkg)) {
+ ThemeUtils.createResourcesDirIfNotExists(COMMON_OVERLAY, pkg.packageName);
+ compileResources(COMMON_OVERLAY, pkg);
+ mAvailableCommonResources.put(pkg.packageName, System.currentTimeMillis());
+ }
+
+ ThemeUtils.createResourcesDirIfNotExists(target, pkg.packageName);
+ compileResources(target, pkg);
+ }
+
+ private void compileResources(String target, PackageParser.Package pkg)
+ throws IOException, AaptException {
+ if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Compile resource table for " + pkg.packageName);
+ //TODO: cleanup this hack. Modify aapt? Aapt uses the manifests package name
+ //when creating the resource table. We care about the resource table's name because
+ //it is used when removing the table by cookie.
+ try {
+ createTempManifest(COMMON_OVERLAY.equals(target)
+ ? ThemeUtils.getCommonPackageName(pkg.packageName) : pkg.packageName);
+ compileResourcesWithAapt(target, pkg);
+ } finally {
+ cleanupTempManifest();
+ }
+ }
+
+ private void compileIconPack(Package pkg) throws Exception {
+ if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Compile resource table for " + pkg.packageName);
+ OutputStream out = null;
+ DataOutputStream dataOut = null;
+ try {
+ createTempManifest(pkg.packageName);
+ int code = pkg.manifestHashCode;
+ String hashFile = ThemeUtils.getIconHashFile(pkg.packageName);
+ out = new FileOutputStream(hashFile);
+ dataOut = new DataOutputStream(out);
+ dataOut.writeInt(code);
+ compileIconsWithAapt(pkg);
+ } finally {
+ IoUtils.closeQuietly(out);
+ IoUtils.closeQuietly(dataOut);
+ cleanupTempManifest();
+ }
+ }
+
+ private void insertIntoOverlayMap(String target, PackageParser.Package opkg) {
+ if (!mOverlays.containsKey(target)) {
+ mOverlays.put(target,
+ new ArrayMap<String, PackageParser.Package>());
+ }
+ ArrayMap<String, PackageParser.Package> map = mOverlays.get(target);
+ map.put(opkg.packageName, opkg);
+ }
+
+ private void generateIdmap(String target, PackageParser.Package opkg) throws IdmapException {
+ PackageParser.Package targetPkg = mPackages.get(target);
+ if (targetPkg != null && !createIdmapForPackagePairLI(targetPkg, opkg)) {
+ throw new IdmapException("idmap failed for targetPkg: " + targetPkg
+ + " and opkg: " + opkg);
+ }
+ }
+
+ public class AaptException extends Exception {
+ public AaptException(String message) {
+ super(message);
+ }
+ }
+
+ public class IdmapException extends Exception {
+ public IdmapException(String message) {
+ super(message);
+ }
+ }
+
+ private boolean hasCommonResources(PackageParser.Package pkg) throws IOException {
+ boolean ret = false;
+ // check if assets/overlays/common exists in this theme
+ AssetManager assets = new AssetManager();
+ assets.addAssetPath(pkg.baseCodePath);
+ String[] common = assets.list("overlays/common");
+ if (common != null && common.length > 0) ret = true;
+
+ return ret;
+ }
+
+ private void compileResourcesWithAapt(String target, PackageParser.Package pkg)
+ throws IOException, AaptException {
+ String internalPath = APK_PATH_TO_OVERLAY + target + File.separator;
+ String resPath = ThemeUtils.getTargetCacheDir(target, pkg);
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ int pkgId;
+ if ("android".equals(target)) {
+ pkgId = Resources.THEME_FRAMEWORK_PKG_ID;
+ } else if (COMMON_OVERLAY.equals(target)) {
+ pkgId = Resources.THEME_COMMON_PKG_ID;
+ } else {
+ pkgId = Resources.THEME_APP_PKG_ID;
+ }
+
+ boolean hasCommonResources = (hasCommonResources(pkg) && !COMMON_OVERLAY.equals(target));
+ PackageParser.Package targetPkg = mPackages.get(target);
+ String appPath = targetPkg != null ? targetPkg.baseCodePath :
+ Environment.getRootDirectory() + "/framework/framework-res.apk";
+
+ if (mInstaller.aapt(pkg.baseCodePath, internalPath, resPath, sharedGid, pkgId,
+ pkg.applicationInfo.targetSdkVersion,
+ appPath,
+ hasCommonResources ? ThemeUtils.getTargetCacheDir(COMMON_OVERLAY, pkg)
+ + File.separator + "resources.apk" : "") != 0) {
+ throw new AaptException("Failed to run aapt");
+ }
+ }
+
+ private void compileIconsWithAapt(Package pkg) throws Exception {
+ String resPath = ThemeUtils.getIconPackDir(pkg.packageName);
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+
+ if (mInstaller.aapt(pkg.baseCodePath, APK_PATH_TO_ICONS, resPath, sharedGid,
+ Resources.THEME_ICON_PKG_ID,
+ pkg.applicationInfo.targetSdkVersion,
+ "", "") != 0) {
+ throw new AaptException("Failed to run aapt");
+ }
+ }
+
+ private void uninstallThemeForAllApps(PackageParser.Package opkg) {
+ for(String target : opkg.mOverlayTargets) {
+ ArrayMap<String, PackageParser.Package> map = mOverlays.get(target);
+ if (map != null) {
+ map.remove(opkg.packageName);
+
+ if (map.isEmpty()) {
+ mOverlays.remove(target);
+ }
+ }
+ }
+
+ // Now simply delete the root overlay cache directory and all its contents
+ recursiveDelete(new File(ThemeUtils.getOverlayResourceCacheDir(opkg.packageName)));
+ }
+
+ private void uninstallThemeForApp(PackageParser.Package appPkg) {
+ ArrayMap<String, PackageParser.Package> map = mOverlays.get(appPkg.packageName);
+ if (map == null) return;
+
+ for(PackageParser.Package opkg : map.values()) {
+ String cachePath = ThemeUtils.getTargetCacheDir(appPkg.packageName, opkg.packageName);
+ recursiveDelete(new File(cachePath));
+ }
+ }
+
+ private void recursiveDelete(File f) {
+ if (f.isDirectory()) {
+ for (File c : f.listFiles())
+ recursiveDelete(c);
+ }
+ f.delete();
+ }
+
+ private void createTempManifest(String pkgName) throws IOException {
+ StringBuilder manifest = new StringBuilder();
+ manifest.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+ manifest.append("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"");
+ manifest.append(" package=\"" + pkgName+ "\">");
+ manifest.append(" </manifest>");
+
+ BufferedWriter bw = null;
+ try {
+ bw = new BufferedWriter(new FileWriter("/data/app/AndroidManifest.xml"));
+ bw.write(manifest.toString());
+ bw.flush();
+ bw.close();
+ File resFile = new File("/data/app/AndroidManifest.xml");
+ FileUtils.setPermissions(resFile,
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH, -1, -1);
+ } finally {
+ IoUtils.closeQuietly(bw);
+ }
+ }
+
+ private void cleanupTempManifest() {
+ File resFile = new File("/data/app/AndroidManifest.xml");
+ resFile.delete();
+ }
+
+ /**
+ * Compares the 32 bit hash of the target and overlay to those stored
+ * in the idmap and returns true if either hash differs
+ * @param targetPkg
+ * @param overlayPkg
+ * @return
+ */
+ private boolean shouldCreateIdmap(PackageParser.Package targetPkg,
+ PackageParser.Package overlayPkg) {
+ if (targetPkg == null || targetPkg.baseCodePath == null || overlayPkg == null) return false;
+
+ int targetHash = targetPkg.manifestHashCode;
+ int overlayHash = overlayPkg.manifestHashCode;
+
+ File idmap =
+ new File(ThemeUtils.getIdmapPath(targetPkg.packageName, overlayPkg.packageName));
+ if (!idmap.exists()) {
+ return true;
+ }
+
+ int[] hashes;
+ try {
+ hashes = getIdmapHashes(idmap);
+ } catch (IOException e) {
+ return true;
+ }
+
+ if (targetHash == 0 || overlayHash == 0 ||
+ targetHash != hashes[0] || overlayHash != hashes[1]) {
+ // if the overlay changed we'll want to recreate the common resources if it has any
+ if (overlayHash != hashes[1]
+ && mAvailableCommonResources.containsKey(overlayPkg.packageName)) {
+ mAvailableCommonResources.remove(overlayPkg.packageName);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private boolean shouldCompileCommonResources(PackageParser.Package pkg) {
+ if (!mAvailableCommonResources.containsKey(pkg.packageName)) return true;
+
+ long lastUpdated = mAvailableCommonResources.get(pkg.packageName);
+ long currentTime = System.currentTimeMillis();
+ if (currentTime - lastUpdated > COMMON_RESOURCE_EXPIRATION) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the file modified times for the overlay and target from the idmap
+ * @param idmap
+ * @return
+ * @throws IOException
+ */
+ private int[] getIdmapHashes(File idmap) throws IOException {
+ int[] times = new int[2];
+ ByteBuffer bb = ByteBuffer.allocate(8);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ FileInputStream fis = new FileInputStream(idmap);
+ fis.skip(IDMAP_HASH_START_OFFSET);
+ fis.read(bb.array());
+ fis.close();
+ final IntBuffer ib = bb.asIntBuffer();
+ times[0] = ib.get(0);
+ times[1] = ib.get(1);
+
+ return times;
+ }
+
private void setUpCustomResolverActivity(PackageParser.Package pkg) {
synchronized (mPackages) {
- mResolverReplaced = true;
- // Set up information for custom user intent resolution activity.
- mResolveActivity.applicationInfo = pkg.applicationInfo;
- mResolveActivity.name = mCustomResolverComponentName.getClassName();
- mResolveActivity.packageName = pkg.applicationInfo.packageName;
- mResolveActivity.processName = pkg.applicationInfo.packageName;
- mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
- mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
- ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
- mResolveActivity.theme = 0;
- mResolveActivity.exported = true;
- mResolveActivity.enabled = true;
- mResolveInfo.activityInfo = mResolveActivity;
- mResolveInfo.priority = 0;
- mResolveInfo.preferredOrder = 0;
- mResolveInfo.match = 0;
- mResolveComponentName = mCustomResolverComponentName;
- Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " +
- mResolveComponentName);
+ for (Activity a : pkg.activities) {
+ if (a.getComponentName().getClassName()
+ .equals(mCustomResolverComponentName.getClassName())) {
+ mResolverReplaced = true;
+ // Set up information for custom user intent resolution activity.
+ mResolveActivity.applicationInfo = pkg.applicationInfo;
+ mResolveActivity.name = mCustomResolverComponentName.getClassName();
+ mResolveActivity.packageName = pkg.applicationInfo.packageName;
+ mResolveActivity.processName = pkg.applicationInfo.packageName;
+ mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+ mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
+ ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
+ mResolveActivity.theme = a.info.theme;
+ mResolveActivity.exported = true;
+ mResolveActivity.enabled = true;
+ mResolveInfo.activityInfo = mResolveActivity;
+ mResolveInfo.priority = 0;
+ mResolveInfo.preferredOrder = 0;
+ mResolveInfo.match = 0;
+ mResolveComponentName = mCustomResolverComponentName;
+ Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " +
+ mResolveComponentName);
+ break;
+ }
+ }
+ if (mResolveActivity.theme == 0) {
+ mResolveActivity.theme = R.style.Theme_DeviceDefault_Resolver;
+ }
}
}
@@ -7838,7 +8496,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* Derive and set the location of native libraries for the given package,
* which varies depending on where and how the package was installed.
*/
- private void setNativeLibraryPaths(PackageParser.Package pkg) {
+ private void setNativeLibraryPaths(PackageParser.Package pkg, int parseFlags) {
final ApplicationInfo info = pkg.applicationInfo;
final String codePath = pkg.codePath;
final File codeFile = new File(codePath);
@@ -7884,10 +8542,17 @@ public class PackageManagerService extends IPackageManager.Stub {
info.nativeLibraryRootRequiresIsa = false;
info.nativeLibraryDir = info.nativeLibraryRootDir;
} else {
- // Cluster install
- info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
+ if ((parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0) {
+ // mAppLib32InstallDir is the directory /data/app-lib which is used to store native
+ // libs for apps from the system paritition. It isn't really specific to 32bit in
+ // any way except for the variable name, the system will use the primary/secondary
+ // ABI computed below.
+ info.nativeLibraryRootDir =
+ new File(mAppLib32InstallDir, pkg.packageName).getAbsolutePath();
+ } else {
+ info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
+ }
info.nativeLibraryRootRequiresIsa = true;
-
info.nativeLibraryDir = new File(info.nativeLibraryRootDir,
getPrimaryInstructionSet(info)).getAbsolutePath();
@@ -8631,7 +9296,6 @@ public class PackageManagerService extends IPackageManager.Stub {
& PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
if (isSystemApp(pkg)) {
// For updated system applications, a system permission
- // is granted only if it had been defined by the original application.
if (pkg.isUpdatedSystemApp()) {
final PackageSetting sysPs = mSettings
.getDisabledSystemPkgLPr(pkg.packageName);
@@ -8699,6 +9363,9 @@ public class PackageManagerService extends IPackageManager.Stub {
allowed = origPermissions.hasInstallPermission(perm);
}
}
+ if (!allowed && bp.allowViaWhitelist) {
+ allowed = isAllowedSignature(pkg, perm);
+ }
return allowed;
}
@@ -8715,8 +9382,24 @@ public class PackageManagerService extends IPackageManager.Stub {
int userId) {
if (!sUserManager.exists(userId)) return null;
mFlags = flags;
- return super.queryIntent(intent, resolvedType,
+ List<ResolveInfo> list = super.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
+ // Remove protected Application components
+ int callingUid = Binder.getCallingUid();
+ String[] pkgs = getPackagesForUid(callingUid);
+ List<String> packages = (pkgs != null) ? Arrays.asList(pkgs) : Collections.EMPTY_LIST;
+ if (callingUid != Process.SYSTEM_UID &&
+ (getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ Iterator<ResolveInfo> itr = list.iterator();
+ while (itr.hasNext()) {
+ ActivityInfo activityInfo = itr.next().activityInfo;
+ if (activityInfo.applicationInfo.protect && (packages == null
+ || !packages.contains(activityInfo.packageName))) {
+ itr.remove();
+ }
+ }
+ }
+ return list;
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -9396,8 +10079,8 @@ public class PackageManagerService extends IPackageManager.Stub {
};
final void sendPackageBroadcast(final String action, final String pkg,
- final Bundle extras, final String targetPkg, final IIntentReceiver finishedReceiver,
- final int[] userIds) {
+ final String intentCategory, final Bundle extras, final String targetPkg,
+ final IIntentReceiver finishedReceiver, final int[] userIds) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -9434,6 +10117,9 @@ public class PackageManagerService extends IPackageManager.Stub {
+ intent.toShortString(false, true, false, false)
+ " " + intent.getExtras(), here);
}
+ if (intentCategory != null) {
+ intent.addCategory(intentCategory);
+ }
am.broadcastIntent(null, intent, null, finishedReceiver,
0, null, null, null, android.app.AppOpsManager.OP_NONE,
null, finishedReceiver != null, false, id);
@@ -9513,6 +10199,7 @@ public class PackageManagerService extends IPackageManager.Stub {
public void installPackage(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, VerificationParams verificationParams,
String packageAbiOverride) {
+ android.util.SeempLog.record(90);
installPackageAsUser(originPath, observer, installFlags, installerPackageName,
verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
}
@@ -9599,8 +10286,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, null, null, new int[] {userId});
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+ null, extras, null, null, new int[] {userId});
try {
IActivityManager am = ActivityManagerNative.getDefault();
final boolean isSystem =
@@ -10511,6 +11198,9 @@ public class PackageManagerService extends IPackageManager.Stub {
// reader
synchronized (mPackages) {
PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkgLite.isTheme) {
+ return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+ }
if (pkg != null) {
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
// Check for downgrading.
@@ -10650,7 +11340,7 @@ public class PackageManagerService extends IPackageManager.Stub {
loc = installLocationPolicy(pkgLite);
if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
- } else if (!onSd && !onInt) {
+ } else if ((!onSd && !onInt) || pkgLite.isTheme) {
// Override install location with flags
if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
// Set the flag to install on external media.
@@ -10662,6 +11352,9 @@ public class PackageManagerService extends IPackageManager.Stub {
installFlags |= PackageManager.INSTALL_INTERNAL;
installFlags &= ~PackageManager.INSTALL_EXTERNAL;
}
+ if (pkgLite.isTheme) {
+ installFlags &= ~PackageManager.INSTALL_FORWARD_LOCK;
+ }
}
}
}
@@ -12440,7 +13133,7 @@ public class PackageManagerService extends IPackageManager.Stub {
try {
derivePackageAbi(pkg, new File(pkg.codePath), args.abiOverride,
- true /* extract libs */);
+ true /* extract libs */, parseFlags);
} catch (PackageManagerException pme) {
Slog.e(TAG, "Error deriving application ABI", pme);
res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
@@ -12847,11 +13540,17 @@ public class PackageManagerService extends IPackageManager.Stub {
? info.removedAppId : info.uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+ String category = null;
+ if (info.isThemeApk) {
+ category = cyanogenmod.content.Intent
+ .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
+
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, category,
extras, null, null, null);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, category,
extras, null, null, null);
- sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
+ sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null,
null, packageName, null, null);
}
}
@@ -12876,6 +13575,7 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean isRemovedPackageSystemUpdate = false;
// Clean up resources deleted packages.
InstallArgs args = null;
+ boolean isThemeApk = false;
void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
Bundle extras = new Bundle(1);
@@ -12886,15 +13586,20 @@ public class PackageManagerService extends IPackageManager.Stub {
}
extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
if (removedPackage != null) {
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
+ String category = null;
+ if (isThemeApk) {
+ category = cyanogenmod.content.Intent
+ .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, category,
extras, null, null, removedUsers);
if (fullRemove && !replacing) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
- extras, null, null, removedUsers);
+ category, extras, null, null, removedUsers);
}
}
if (removedAppId >= 0) {
- sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
+ sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, null, extras, null, null,
removedUsers);
}
}
@@ -13201,7 +13906,8 @@ public class PackageManagerService extends IPackageManager.Stub {
false, //hidden
null, null, null,
false, // blockUninstall
- ps.readUserState(userId).domainVerificationStatus, 0);
+ ps.readUserState(userId).domainVerificationStatus, 0,
+ null, null);
if (!isSystemApp(ps)) {
if (ps.isAnyInstalled(sUserManager.getUserIds())) {
// Other user still have this package installed, so all
@@ -13274,6 +13980,15 @@ public class PackageManagerService extends IPackageManager.Stub {
outInfo, writeSettings);
}
+ //Cleanup theme related data
+ if (ps.pkg != null) {
+ if (ps.pkg.mOverlayTargets.size() > 0) {
+ uninstallThemeForAllApps(ps.pkg);
+ } else if (mOverlays.containsKey(ps.pkg.packageName)) {
+ uninstallThemeForApp(ps.pkg);
+ }
+ }
+
return ret;
}
@@ -14453,6 +15168,12 @@ public class PackageManagerService extends IPackageManager.Stub {
public void setComponentEnabledSetting(ComponentName componentName,
int newState, int flags, int userId) {
if (!sUserManager.exists(userId)) return;
+ // Don't allow to enable components marked for disabling at build-time
+ if (mDisabledComponentsList.contains(componentName)) {
+ Slog.d(TAG, "Ignoring attempt to set enabled state of disabled component "
+ + componentName.flattenToString());
+ return;
+ }
setEnabledSetting(componentName.getPackageName(),
componentName.getClassName(), newState, flags, userId, null);
}
@@ -14467,6 +15188,7 @@ public class PackageManagerService extends IPackageManager.Stub {
throw new IllegalArgumentException("Invalid new component state: "
+ newState);
}
+
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingOrSelfPermission(
@@ -14594,7 +15316,7 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
extras.putInt(Intent.EXTRA_UID, packageUid);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, null, extras, null, null,
new int[] {UserHandle.getUserId(packageUid)});
}
@@ -14670,6 +15392,9 @@ public class PackageManagerService extends IPackageManager.Stub {
int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
synchronized (mPackages) {
+ // process applied themes so their resources are up to date and ready use
+ processAppliedThemes();
+
// Verify that all of the preferred activity components actually
// exist. It is possible for applications to be updated and at
// that point remove a previously declared activity component that
@@ -15585,7 +16310,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
+ sendPackageBroadcast(action, null, null, extras, null, finishedReceiver, null);
}
}
@@ -15799,7 +16524,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
}
- if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
+ if ((!Build.FINGERPRINT.equals(ver.fingerprint)) ||
+ (!Build.DISPLAY.equals(ver.displayversion))) {
deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
}
}
@@ -16353,6 +17079,14 @@ public class PackageManagerService extends IPackageManager.Stub {
mSettings.createNewUserLILPw(this, mInstaller, userHandle);
applyFactoryDefaultBrowserLPw(userHandle);
primeDomainVerificationsLPw(userHandle);
+ // Set flag to monitor and not change apk file paths when
+ // scanning install directories.
+ final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
+ createAndSetCustomResources();
+ scanDirLI(Environment.getPrebundledDirectory(),
+ PackageParser.PARSE_IS_PREBUNDLED_DIR, scanFlags, 0,
+ new UserHandle(userHandle));
+ mCustomResources = null;
}
}
@@ -16408,6 +17142,121 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public void setComponentProtectedSetting(ComponentName componentName, boolean newState,
+ int userId) {
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "set protected");
+
+ String packageName = componentName.getPackageName();
+ String className = componentName.getClassName();
+
+ PackageSetting pkgSetting;
+ ArrayList<String> components;
+
+ synchronized (mPackages) {
+ pkgSetting = mSettings.mPackages.get(packageName);
+
+ if (pkgSetting == null) {
+ if (className == null) {
+ throw new IllegalArgumentException(
+ "Unknown package: " + packageName);
+ }
+ throw new IllegalArgumentException(
+ "Unknown component: " + packageName
+ + "/" + className);
+ }
+
+ //Protection levels must be applied at the Component Level!
+ if (className == null) {
+ throw new IllegalArgumentException(
+ "Must specify Component Class name."
+ );
+ } else {
+ PackageParser.Package pkg = pkgSetting.pkg;
+ if (pkg == null || !pkg.hasComponentClassName(className)) {
+ if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
+ throw new IllegalArgumentException("Component class " + className
+ + " does not exist in " + packageName);
+ } else {
+ Slog.w(TAG, "Failed setComponentProtectedSetting: component class "
+ + className + " does not exist in " + packageName);
+ }
+ }
+
+ pkgSetting.protectComponentLPw(className, newState, userId);
+ mSettings.writePackageRestrictionsLPr(userId);
+
+ components = mPendingBroadcasts.get(userId, packageName);
+ final boolean newPackage = components == null;
+ if (newPackage) {
+ components = new ArrayList<String>();
+ }
+ if (!components.contains(className)) {
+ components.add(className);
+ }
+ }
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ int packageUid = UserHandle.getUid(userId, pkgSetting.appId);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
+ @Override
+ public boolean isComponentProtected(String callingPackage,
+ ComponentName componentName, int userId) {
+ if (DEBUG_PROTECTED) Log.d(TAG, "Checking if component is protected "
+ + componentName.flattenToShortString() + " from calling package " + callingPackage);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "set protected");
+
+ //Allow managers full access
+ List<String> protectedComponentManagers =
+ CMSettings.Secure.getDelimitedStringAsList(mContext.getContentResolver(),
+ CMSettings.Secure.PROTECTED_COMPONENT_MANAGERS, "|");
+ if (protectedComponentManagers.contains(callingPackage)) {
+ if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is a protected manager, allow");
+ return false;
+ }
+
+ String packageName = componentName.getPackageName();
+ String className = componentName.getClassName();
+
+ //If this component is launched from the same package, allow it.
+ if (TextUtils.equals(packageName, callingPackage)) {
+ if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is same as target, allow");
+ return false;
+ }
+
+ if (TextUtils.equals(PROTECTED_APPS_TARGET_VALIDATION_COMPONENT,
+ componentName.flattenToString())) {
+ return false;
+ }
+
+ PackageSetting pkgSetting;
+ ArraySet<String> components;
+
+ synchronized (mPackages) {
+ pkgSetting = mSettings.mPackages.get(packageName);
+
+ if (pkgSetting == null) {
+ if (className == null) {
+ throw new IllegalArgumentException(
+ "Unknown package: " + packageName);
+ }
+ throw new IllegalArgumentException(
+ "Unknown component: " + packageName
+ + "/" + className);
+ }
+ // Get all the protected components
+ components = pkgSetting.getProtectedComponents(userId);
+ if (DEBUG_PROTECTED) Log.d(TAG, "Got " + components.size() + " protected components");
+ return components.size() > 0;
+ }
+ }
+
+ @Override
public boolean isStorageLow() {
final long token = Binder.clearCallingIdentity();
try {
@@ -16581,6 +17430,39 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ @Override
+ public void updateIconMapping(String pkgName) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_CONFIGURATION,
+ "could not update icon mapping because caller "
+ + "does not have change config permission");
+
+ if (pkgName == null) {
+ clearIconMapping();
+ return;
+ }
+ mIconPackHelper = new IconPackHelper(mContext);
+ try {
+ mIconPackHelper.loadIconPack(pkgName);
+ } catch(NameNotFoundException e) {
+ Log.e(TAG, "Unable to find icon pack: " + pkgName);
+ clearIconMapping();
+ return;
+ }
+
+ for (Activity activity : mActivities.mActivities.values()) {
+ activity.info.themedIcon =
+ mIconPackHelper.getResourceIdForActivityIcon(activity.info);
+ }
+
+ synchronized (mPackages) {
+ for (Package pkg : mPackages.values()) {
+ pkg.applicationInfo.themedIcon =
+ mIconPackHelper.getResourceIdForApp(pkg.packageName);
+ }
+ }
+ }
+
private static class MoveCallbacks extends Handler {
private static final int MSG_CREATED = 1;
private static final int MSG_STATUS_CHANGED = 2;
@@ -16807,4 +17689,157 @@ public class PackageManagerService extends IPackageManager.Stub {
"Cannot call " + tag + " from UID " + callingUid);
}
}
+
+ private void clearIconMapping() {
+ mIconPackHelper = null;
+ for (Activity activity : mActivities.mActivities.values()) {
+ activity.info.themedIcon = 0;
+ }
+
+ for (Package pkg : mPackages.values()) {
+ pkg.applicationInfo.themedIcon = 0;
+ }
+ }
+
+ @Override
+ public ComposedIconInfo getComposedIconInfo() {
+ return mIconPackHelper != null ? mIconPackHelper.getComposedIconInfo() : null;
+ }
+
+ @Override
+ public int processThemeResources(String themePkgName) {
+ mContext.enforceCallingOrSelfPermission(
+ cyanogenmod.platform.Manifest.permission.ACCESS_THEME_MANAGER, null);
+ PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(themePkgName);
+ }
+ if (pkg == null) {
+ Log.w(TAG, "Unable to get pkg for processing " + themePkgName);
+ return 0;
+ }
+
+ // Process icons
+ if (isIconCompileNeeded(pkg)) {
+ try {
+ ThemeUtils.createCacheDirIfNotExists();
+ ThemeUtils.createIconDirIfNotExists(pkg.packageName);
+ compileIconPack(pkg);
+ } catch (Exception e) {
+ uninstallThemeForAllApps(pkg);
+ deletePackageX(themePkgName, getCallingUid(), PackageManager.DELETE_ALL_USERS);
+ return PackageManager.INSTALL_FAILED_THEME_AAPT_ERROR;
+ }
+ }
+
+ // Generate Idmaps and res tables if pkg is a theme
+ Iterator<String> iterator = pkg.mOverlayTargets.iterator();
+ while (iterator.hasNext()) {
+ String target = iterator.next();
+ Exception failedException = null;
+ PackageParser.Package targetPkg;
+ synchronized (mPackages) {
+ targetPkg = mPackages.get(target);
+ }
+ try {
+ compileResourcesAndIdmapIfNeeded(targetPkg, pkg);
+ } catch (IdmapException e) {
+ failedException = e;
+ } catch (AaptException e) {
+ failedException = e;
+ } catch (Exception e) {
+ failedException = e;
+ }
+
+ if (failedException != null) {
+ Slog.w(TAG, "Unable to process theme " + pkg.packageName + " for " + target,
+ failedException);
+ // remove target from mOverlayTargets
+ iterator.remove();
+ }
+ }
+
+ return 0;
+ }
+
+ private void processThemeResourcesInThemeService(String pkgName) {
+ IThemeService ts = IThemeService.Stub.asInterface(ServiceManager.getService(
+ CMContextConstants.CM_THEME_SERVICE));
+ if (ts == null) {
+ Slog.e(TAG, "Theme service not available");
+ return;
+ }
+ try {
+ ts.processThemeResources(pkgName);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ }
+
+ /**
+ * Makes sure resources and idmaps for themes that are applied are up to date. This should only
+ * impact boots when something on /system has changed.
+ */
+ private void processAppliedThemes() {
+ ThemeConfig themeConfig = ThemeConfig.getBootTheme(mContext.getContentResolver());
+ if (themeConfig == null) return;
+
+ // gather up all the themes applied and then process them
+ Set<String> themesToProcess = new ArraySet<String>();
+ // process theme set for icons
+ if (themeConfig.getIconPackPkgName() != null) {
+ themesToProcess.add(themeConfig.getIconPackPkgName());
+ }
+ // process theme set for non-app specific overlays
+ if (themeConfig.getOverlayPkgName() != null) {
+ themesToProcess.add(themeConfig.getOverlayPkgName());
+ }
+ // process theme set for status bar
+ if (themeConfig.getOverlayForStatusBar() != null) {
+ themesToProcess.add(themeConfig.getOverlayForStatusBar());
+ }
+ // process theme set for navigation bar
+ if (themeConfig.getOverlayForNavBar() != null) {
+ themesToProcess.add(themeConfig.getOverlayForNavBar());
+ }
+ // process themes set for specific apps
+ Map<String, ThemeConfig.AppTheme> appThemesMap = themeConfig.getAppThemes();
+ for (String themePkgName : appThemesMap.keySet()) {
+ themesToProcess.add(themePkgName);
+ }
+
+ // now start the processing
+ for (String themePkgName : themesToProcess) {
+ processThemeResources(themePkgName);
+ }
+ }
+
+ private void createAndSetCustomResources() {
+ Configuration tempConfiguration = new Configuration();
+ String mcc = SystemProperties.get("ro.prebundled.mcc");
+ if (!TextUtils.isEmpty(mcc)) {
+ tempConfiguration.mcc = Integer.parseInt(mcc);
+ mCustomResources = new Resources(new AssetManager(), new DisplayMetrics(),
+ tempConfiguration);
+ }
+ }
+
+ /**
+ * The new resource cache structure does not flatten the paths for idmaps, so this method
+ * checks for files that end with @idmap and assumes this indicates the older format and
+ * removes all files and directories from the resource cache so that it can be rebuilt
+ * using the new format.
+ */
+ private static void removeLegacyResourceCache() {
+ File cacheDir = new File(ThemeUtils.RESOURCE_CACHE_DIR);
+ if (cacheDir.exists()) {
+ for (File f : cacheDir.listFiles()) {
+ if (f.getName().endsWith(ThemeUtils.IDMAP_SUFFIX)) {
+ Log.i(TAG, "Removing old resource cache");
+ FileUtils.deleteContents(new File(ThemeUtils.RESOURCE_CACHE_DIR));
+ return;
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 78328f5..635f46e 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.COMPONENT_VISIBLE_STATUS;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
@@ -344,7 +345,8 @@ abstract class PackageSettingBase extends SettingBase {
boolean notLaunched, boolean hidden,
String lastDisableAppCaller, ArraySet<String> enabledComponents,
ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState,
- int linkGeneration) {
+ int linkGeneration,
+ ArraySet<String> protectedComponents, ArraySet<String> visibleComponents) {
PackageUserState state = modifyUserState(userId);
state.enabled = enabled;
state.installed = installed;
@@ -357,6 +359,8 @@ abstract class PackageSettingBase extends SettingBase {
state.blockUninstall = blockUninstall;
state.domainVerificationStatus = domainVerifState;
state.appLinkGeneration = linkGeneration;
+ state.protectedComponents = protectedComponents;
+ state.visibleComponents = visibleComponents;
}
ArraySet<String> getEnabledComponents(int userId) {
@@ -396,6 +400,17 @@ abstract class PackageSettingBase extends SettingBase {
return state;
}
+ PackageUserState modifyUserStateComponents(int userId) {
+ PackageUserState state = modifyUserState(userId);
+ if (state.protectedComponents == null) {
+ state.protectedComponents = new ArraySet<String>(1);
+ }
+ if (state.visibleComponents == null) {
+ state.visibleComponents = new ArraySet<String>(1);
+ }
+ return state;
+ }
+
void addDisabledComponent(String componentClassName, int userId) {
modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
}
@@ -441,6 +456,27 @@ abstract class PackageSettingBase extends SettingBase {
}
}
+ boolean protectComponentLPw(String componentClassName, boolean protect, int userId) {
+ PackageUserState state = modifyUserStateComponents(userId);
+ boolean changed = false;
+ if (protect == COMPONENT_VISIBLE_STATUS) {
+ changed = state.protectedComponents != null
+ ? state.protectedComponents.remove(componentClassName) : false;
+ changed |= state.visibleComponents.add(componentClassName);
+ } else {
+ changed = state.visibleComponents != null
+ ? state.visibleComponents.remove(componentClassName) : false;
+ changed |= state.protectedComponents.add(componentClassName);
+ }
+
+ return changed;
+ }
+
+ ArraySet<String> getProtectedComponents(int userId) {
+ PackageUserState state = modifyUserStateComponents(userId);
+ return state.protectedComponents;
+ }
+
void removeUser(int userId) {
userState.delete(userId);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 647c17b..7b95106 100644..100755
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.INSTALL_FAILED_UNINSTALLED_PREBUNDLE;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
@@ -33,6 +34,8 @@ import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -59,6 +62,8 @@ import android.util.SparseLongArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
@@ -70,6 +75,7 @@ import com.android.server.pm.PermissionsState.PermissionState;
import java.io.FileNotFoundException;
import java.util.Collection;
+import java.util.HashSet;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -87,6 +93,7 @@ import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.pm.PackageUserState;
import android.content.pm.VerifierDeviceIdentity;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -96,9 +103,13 @@ import android.util.SparseIntArray;
import android.util.Xml;
import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
@@ -185,6 +196,9 @@ final class Settings {
private static final String TAG_DEFAULT_BROWSER = "default-browser";
private static final String TAG_VERSION = "version";
+ private static final String TAG_PROTECTED_COMPONENTS = "protected-components";
+ private static final String TAG_VISIBLE_COMPONENTS = "visible-components";
+
private static final String ATTR_NAME = "name";
private static final String ATTR_USER = "user";
private static final String ATTR_CODE = "code";
@@ -203,6 +217,7 @@ final class Settings {
private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
private static final String ATTR_PACKAGE_NAME = "packageName";
private static final String ATTR_FINGERPRINT = "fingerprint";
+ private static final String ATTR_DISPLAYVERSION = "displayversion";
private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
private static final String ATTR_VOLUME_UUID = "volumeUuid";
private static final String ATTR_SDK_VERSION = "sdkVersion";
@@ -217,6 +232,7 @@ final class Settings {
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
+ private final File mPrebundledPackagesFilename;
final ArrayMap<String, PackageSetting> mPackages =
new ArrayMap<String, PackageSetting>();
@@ -259,6 +275,12 @@ final class Settings {
String fingerprint;
/**
+ * Last known value of {@link Build#DISPLAY}. Used to determine when
+ * an system update has occurred, meaning we need to clear code caches.
+ */
+ String displayversion;
+
+ /**
* Force all version information to match current system values,
* typically after resolving any required upgrade steps.
*/
@@ -266,6 +288,7 @@ final class Settings {
sdkVersion = Build.VERSION.SDK_INT;
databaseVersion = CURRENT_DATABASE_VERSION;
fingerprint = Build.FINGERPRINT;
+ displayversion = Build.DISPLAY;
}
}
@@ -284,6 +307,10 @@ final class Settings {
final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
new SparseArray<PersistentPreferredIntentResolver>();
+ // The persistent prebundled packages for a user
+ final SparseArray<HashSet<String>> mPrebundledPackages =
+ new SparseArray<HashSet<String>>();
+
// For every user, it is used to find to which other users the intent can be forwarded.
final SparseArray<CrossProfileIntentResolver> mCrossProfileIntentResolvers =
new SparseArray<CrossProfileIntentResolver>();
@@ -362,6 +389,7 @@ final class Settings {
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
+ mPrebundledPackagesFilename = new File(mSystemDir, "prebundled-packages.list");
}
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
@@ -666,7 +694,10 @@ final class Settings {
false, // hidden
null, null, null,
false, // blockUninstall
- INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
+ INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
+ null,
+ null
+ );
writePackageRestrictionsLPr(user.id);
}
}
@@ -1035,6 +1066,15 @@ final class Settings {
return pir;
}
+ HashSet<String> editPrebundledPackagesLPw(int userId) {
+ HashSet<String> hashSet = mPrebundledPackages.get(userId);
+ if (hashSet == null) {
+ hashSet = new HashSet<String>();
+ mPrebundledPackages.put(userId, hashSet);
+ }
+ return hashSet;
+ }
+
PersistentPreferredIntentResolver editPersistentPreferredActivitiesLPw(int userId) {
PersistentPreferredIntentResolver ppir = mPersistentPreferredActivities.get(userId);
if (ppir == null) {
@@ -1204,6 +1244,10 @@ final class Settings {
"package-restrictions-backup.xml");
}
+ private File getUserPrebundledStateFile(int userId) {
+ return new File(Environment.getUserSystemDirectory(userId), "prebundled-packages.list");
+ }
+
void writeAllUsersPackageRestrictionsLPr() {
List<UserInfo> users = getAllUsers();
if (users == null) return;
@@ -1428,7 +1472,10 @@ final class Settings {
false, // hidden
null, null, null,
false, // blockUninstall
- INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
+ INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
+ null,
+ null
+ );
}
return;
}
@@ -1513,6 +1560,8 @@ final class Settings {
ArraySet<String> enabledComponents = null;
ArraySet<String> disabledComponents = null;
+ ArraySet<String> protectedComponents = null;
+ ArraySet<String> visibleComponents = null;
int packageDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1527,12 +1576,17 @@ final class Settings {
enabledComponents = readComponentsLPr(parser);
} else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
disabledComponents = readComponentsLPr(parser);
+ } else if (tagName.equals(TAG_PROTECTED_COMPONENTS)) {
+ protectedComponents = readComponentsLPr(parser);
+ } else if (tagName.equals(TAG_VISIBLE_COMPONENTS)) {
+ visibleComponents = readComponentsLPr(parser);
}
}
ps.setUserState(userId, enabled, installed, stopped, notLaunched, hidden,
enabledCaller, enabledComponents, disabledComponents, blockUninstall,
- verifState, linkGeneration);
+ verifState, linkGeneration,
+ protectedComponents, visibleComponents);
} else if (tagName.equals("preferred-activities")) {
readPreferredActivitiesLPw(parser, userId);
} else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
@@ -1772,7 +1826,11 @@ final class Settings {
&& ustate.disabledComponents.size() > 0)
|| ustate.blockUninstall
|| (ustate.domainVerificationStatus !=
- PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)) {
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)
+ || (ustate.protectedComponents != null
+ && ustate.protectedComponents.size() > 0)
+ || (ustate.visibleComponents != null
+ && ustate.visibleComponents.size() > 0)) {
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, pkg.name);
if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + ustate.enabled);
@@ -1829,7 +1887,26 @@ final class Settings {
}
serializer.endTag(null, TAG_DISABLED_COMPONENTS);
}
-
+ if (ustate.protectedComponents != null
+ && ustate.protectedComponents.size() > 0) {
+ serializer.startTag(null, TAG_PROTECTED_COMPONENTS);
+ for (final String name : ustate.protectedComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_PROTECTED_COMPONENTS);
+ }
+ if (ustate.visibleComponents != null
+ && ustate.visibleComponents.size() > 0) {
+ serializer.startTag(null, TAG_VISIBLE_COMPONENTS);
+ for (final String name : ustate.visibleComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_VISIBLE_COMPONENTS);
+ }
serializer.endTag(null, TAG_PACKAGE);
}
}
@@ -2098,6 +2175,7 @@ final class Settings {
XmlUtils.writeIntAttribute(serializer, ATTR_SDK_VERSION, ver.sdkVersion);
XmlUtils.writeIntAttribute(serializer, ATTR_DATABASE_VERSION, ver.databaseVersion);
XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
+ XmlUtils.writeStringAttribute(serializer, ATTR_DISPLAYVERSION, ver.displayversion);
serializer.endTag(null, TAG_VERSION);
}
@@ -2315,6 +2393,165 @@ final class Settings {
}
}
+ // Migrate from previous prebundled packages file to new one
+ void migratePrebundedPackagesIfNeededLPr(List<UserInfo> users, Installer installer) {
+ if (mPrebundledPackagesFilename.exists()) {
+ // Read old file
+ editPrebundledPackagesLPw(UserHandle.USER_OWNER);
+ readPrebundledPackagesOldLPw();
+ mPrebundledPackagesFilename.delete();
+ // Migrate to new file based on user
+ writePrebundledPackagesLPr(UserHandle.USER_OWNER);
+ } else {
+ if (users == null) {
+ readPrebundledPackagesLPr(UserHandle.USER_OWNER);
+ } else {
+ for (UserInfo user : users) {
+ editPrebundledPackagesLPw(user.id);
+ readPrebundledPackagesLPr(user.id);
+ // mark all existing users as having packages installed from OWNER
+ try {
+ markAllAsInstalledForUser(user.id, installer);
+ } catch (PackageManagerException e) {
+ Log.d(TAG, e.toString());
+ }
+ }
+ }
+ }
+ }
+
+ void writePrebundledPackagesLPr(int userId) {
+ editPrebundledPackagesLPw(userId);
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(
+ new BufferedWriter(new FileWriter(getUserPrebundledStateFile(userId), false)));
+
+ for (String packageName : mPrebundledPackages.get(userId)) {
+ writer.println(packageName);
+ }
+ } catch (IOException e) {
+ Slog.e(PackageManagerService.TAG, "Unable to write prebundled package list", e);
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ // This is done for an intermediate migration step on upgrade
+ void readPrebundledPackagesOldLPw() {
+ if (!mPrebundledPackagesFilename.exists()) {
+ return;
+ }
+
+ readPrebundledPackagesForUserFromFileLPr(UserHandle.USER_OWNER,
+ mPrebundledPackagesFilename);
+ }
+
+ void readPrebundledPackagesLPr(int userId) {
+ if (!getUserPrebundledStateFile(userId).exists()) {
+ return;
+ }
+ readPrebundledPackagesForUserFromFileLPr(userId, getUserPrebundledStateFile(userId));
+ }
+
+ private void readPrebundledPackagesForUserFromFileLPr(int userId, File file) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(file));
+ String packageName = reader.readLine();
+ while (packageName != null) {
+ if (!TextUtils.isEmpty(packageName)) {
+ mPrebundledPackages.get(userId).add(packageName);
+ }
+ packageName = reader.readLine();
+ }
+ } catch (IOException e) {
+ Slog.e(PackageManagerService.TAG, "Unable to read prebundled package list", e);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {}
+ }
+ }
+ }
+
+ private void markAllAsInstalledForUser(int userHandle, Installer installer)
+ throws PackageManagerException {
+ if (mPrebundledPackages.get(userHandle) == null) {
+ throw new PackageManagerException(INSTALL_FAILED_UNINSTALLED_PREBUNDLE,
+ "Failure migrating prebundled packages to existing user " + userHandle);
+ }
+
+ // grab all the packages from the user account, move them over
+ for (String s : mPrebundledPackages.get(UserHandle.USER_OWNER)) {
+ mPrebundledPackages.get(userHandle).add(s);
+ }
+
+ for (PackageSetting ps : mPackages.values()) {
+ if (ps.pkg == null || ps.pkg.applicationInfo == null) {
+ continue;
+ }
+ // Mark the app as installed
+ boolean setInstalled =
+ wasPrebundledPackageInstalledLPr(UserHandle.USER_OWNER, ps.name);
+ ps.setInstalled(setInstalled, userHandle);
+ // Tell the installer to create the user data for the application
+ installer.createUserData(ps.name,
+ UserHandle.getUid(userHandle, ps.appId), userHandle,
+ ps.pkg.applicationInfo.seinfo);
+ }
+ // Write the package restrications
+ writePackageRestrictionsLPr(userHandle);
+ }
+
+ void markPrebundledPackageInstalledLPr(int userId, String packageName) {
+ editPrebundledPackagesLPw(userId);
+ mPrebundledPackages.get(userId).add(packageName);
+ }
+
+ boolean wasPrebundledPackageInstalledLPr(int userId, String packageName) {
+ if (mPrebundledPackages.get(userId) == null) {
+ return false;
+ }
+ return mPrebundledPackages.get(userId).contains(packageName);
+ }
+
+ boolean shouldPrebundledPackageBeInstalled(Resources res, String packageName,
+ Resources configuredResources) {
+ // Default fallback on lack of bad package
+ if (TextUtils.isEmpty(packageName)) {
+ return false;
+ }
+
+ // Configured resources can be null if the device
+ // is not region locked. In such cases, fall back to
+ // the default resources object
+ Resources resources = configuredResources;
+ if (configuredResources == null) {
+ resources = res;
+ }
+
+ // If the package is compatible with the current region, install it
+ // Note : If a package needs to be installed only if the device is
+ // not provisioned, overlay values/config_region_locked_packages
+ // TODO change config_region_locked_packages to something that is
+ // not confusing inside a non region resource bucket
+ String[] prebundledArray
+ = resources.getStringArray(R.array.config_region_locked_packages);
+ if (ArrayUtils.contains(prebundledArray, packageName)) {
+ return true;
+ }
+
+ // If the package is not compatible with the current region, check if its locked
+ // to any other region before installing it.
+ prebundledArray = resources
+ .getStringArray(R.array.config_restrict_to_region_locked_devices);
+ return !ArrayUtils.contains(prebundledArray, packageName);
+ }
+
void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
throws java.io.IOException {
serializer.startTag(null, "updated-package");
@@ -2473,6 +2710,9 @@ final class Settings {
}
}
}
+ if (bp.allowViaWhitelist) {
+ serializer.attribute(null, "allowViaWhitelist", Integer.toString(1));
+ }
serializer.endTag(null, TAG_ITEM);
}
}
@@ -2498,7 +2738,7 @@ final class Settings {
}
boolean readLPw(PackageManagerService service, List<UserInfo> users, int sdkVersion,
- boolean onlyCore) {
+ boolean onlyCore, Installer installer) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
try {
@@ -2626,6 +2866,8 @@ final class Settings {
external.sdkVersion = XmlUtils.readIntAttribute(parser, "external", 0);
internal.fingerprint = external.fingerprint =
XmlUtils.readStringAttribute(parser, "fingerprint");
+ internal.displayversion = external.displayversion =
+ XmlUtils.readStringAttribute(parser, "displayversion");
} else if (tagName.equals("database-version")) {
// Upgrade from older XML schema
@@ -2657,6 +2899,7 @@ final class Settings {
ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
ver.databaseVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
+ ver.displayversion = XmlUtils.readStringAttribute(parser, ATTR_DISPLAYVERSION);
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
@@ -2682,7 +2925,8 @@ final class Settings {
// on update drop the files before loading them.
if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) {
final VersionInfo internal = getInternalVersion();
- if (!Build.FINGERPRINT.equals(internal.fingerprint)) {
+ if ((!Build.FINGERPRINT.equals(internal.fingerprint)) ||
+ (!Build.DISPLAY.equals(internal.displayversion))) {
if (users == null) {
mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
UserHandle.USER_OWNER);
@@ -2752,6 +2996,8 @@ final class Settings {
}
}
+ migratePrebundedPackagesIfNeededLPr(users, installer);
+
/*
* Make sure all the updated system packages have their shared users
* associated with them.
@@ -2973,6 +3219,11 @@ final class Settings {
for (int i=0; i<ri.size(); i++) {
ActivityInfo ai = ri.get(i).activityInfo;
set[i] = new ComponentName(ai.packageName, ai.name);
+ // We have already discovered the best third party match,
+ // so we only need to finish filling set with all results.
+ if (haveNonSys != null) {
+ continue;
+ }
if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
if (ri.get(i).match >= thirdPartyMatch) {
// Keep track of the best match we find of all third
@@ -2981,7 +3232,6 @@ final class Settings {
if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
+ ai.packageName + "/" + ai.name + ": non-system!");
haveNonSys = set[i];
- break;
}
} else if (cn.getPackageName().equals(ai.packageName)
&& cn.getClassName().equals(ai.name)) {
@@ -3126,6 +3376,8 @@ final class Settings {
bp.protectionLevel = readInt(parser, null, "protection",
PermissionInfo.PROTECTION_NORMAL);
bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
+ bp.allowViaWhitelist = readInt(parser, null,
+ "allowViaWhitelist", 0) == 1;
if (dynamic) {
PermissionInfo pi = new PermissionInfo();
pi.packageName = sourcePackage.intern();
@@ -3133,6 +3385,7 @@ final class Settings {
pi.icon = readInt(parser, null, "icon", 0);
pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
pi.protectionLevel = bp.protectionLevel;
+ pi.allowViaWhitelist = bp.allowViaWhitelist;
bp.pendingInfo = pi;
}
out.put(bp.name, bp);
@@ -3669,7 +3922,9 @@ final class Settings {
continue;
}
// Only system apps are initially installed.
- ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
+ boolean setInstalled = ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) ||
+ wasPrebundledPackageInstalledLPr(UserHandle.USER_OWNER, ps.name);
+ ps.setInstalled(setInstalled, userHandle);
// Need to create a data directory for all apps under this user.
installer.createUserData(ps.volumeUuid, ps.name,
UserHandle.getUid(userHandle, ps.appId), userHandle,
@@ -3678,6 +3933,7 @@ final class Settings {
applyDefaultPreferredAppsLPw(service, userHandle);
writePackageRestrictionsLPr(userHandle);
writePackageListLPr(userHandle);
+ writePrebundledPackagesLPr(userHandle);
}
void removeUserLPw(int userId) {
@@ -3686,10 +3942,13 @@ final class Settings {
entry.getValue().removeUser(userId);
}
mPreferredActivities.remove(userId);
+ mPrebundledPackages.remove(userId);
File file = getUserPackagesStateFile(userId);
file.delete();
file = getUserPackagesStateBackupFile(userId);
file.delete();
+ file = getUserPrebundledStateFile(userId);
+ file.delete();
removeCrossProfileIntentFiltersLPw(userId);
mRuntimePermissionsPersistence.onUserRemoved(userId);
@@ -3864,7 +4123,7 @@ final class Settings {
if (pkgSetting.getNotLaunched(userId)) {
if (pkgSetting.installerPackageName != null) {
yucky.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
- pkgSetting.name, null,
+ pkgSetting.name, null, null,
pkgSetting.installerPackageName, null, new int[] {userId});
}
pkgSetting.setNotLaunched(false, userId);
@@ -3874,6 +4133,57 @@ final class Settings {
return false;
}
+ void removeStalePermissions() {
+ /*
+ * Remove any permission that is not currently declared by any package
+ */
+ List<BasePermission> permissionsToRemove = new ArrayList<>();
+ for (BasePermission basePerm : mPermissions.values()) {
+ // Ignore permissions declared by the system
+ if (basePerm.sourcePackage.equals("android") ||
+ basePerm.sourcePackage.equals("cyanogenmod.platform")) {
+ continue;
+ }
+ // Ignore permissions other than NORMAL (ignore DYNAMIC and BUILTIN), like the
+ // ones based on permission-trees
+ if (basePerm.type != BasePermission.TYPE_NORMAL) {
+ continue;
+ }
+
+ if (!mPackages.containsKey(basePerm.sourcePackage)) {
+ // Package doesn't exist
+ permissionsToRemove.add(basePerm);
+ continue;
+ }
+ PackageSetting pkgSettings = mPackages.get(basePerm.sourcePackage);
+ if (pkgSettings.pkg == null || pkgSettings.pkg.permissions == null) {
+ // Package doesn't declare permissions
+ permissionsToRemove.add(basePerm);
+ continue;
+ }
+ boolean found = false;
+ for (PackageParser.Permission perm : pkgSettings.pkg.permissions) {
+ if (perm.info.name != null && basePerm.name.equals(perm.info.name)) {
+ // The original package still declares the permission
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // The original package doesn't currently declare the permission
+ permissionsToRemove.add(basePerm);
+ }
+ }
+ // And now remove all stale permissions
+ for (BasePermission basePerm : permissionsToRemove) {
+ String msg = "Removed stale permission: " + basePerm.name + " originally " +
+ "assigned to " + basePerm.sourcePackage + "\n";
+ mReadMessages.append(msg);
+ PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+ mPermissions.remove(basePerm.name);
+ }
+ }
+
List<UserInfo> getAllUsers() {
long id = Binder.clearCallingIdentity();
try {
@@ -3955,6 +4265,7 @@ final class Settings {
pw.printPair("databaseVersion", ver.databaseVersion);
pw.println();
pw.printPair("fingerprint", ver.fingerprint);
+ pw.printPair("displayversion", ver.displayversion);
pw.println();
pw.decreaseIndent();
}
@@ -4522,6 +4833,10 @@ final class Settings {
@GuardedBy("mLock")
// The mapping keys are user ids.
+ private final SparseArray<String> mDisplayversion = new SparseArray<>();
+
+ @GuardedBy("mLock")
+ // The mapping keys are user ids.
private final SparseBooleanArray mDefaultPermissionsGranted = new SparseBooleanArray();
public RuntimePermissionPersistence(Object lock) {
@@ -4534,6 +4849,7 @@ final class Settings {
public void onDefaultRuntimePermissionsGrantedLPr(int userId) {
mFingerprints.put(userId, Build.FINGERPRINT);
+ mDisplayversion.put(userId, Build.DISPLAY);
writePermissionsForUserAsyncLPr(userId);
}
@@ -4626,6 +4942,11 @@ final class Settings {
serializer.attribute(null, ATTR_FINGERPRINT, fingerprint);
}
+ String displayversion = mDisplayversion.get(userId);
+ if (displayversion != null) {
+ serializer.attribute(null, ATTR_DISPLAYVERSION, displayversion);
+ }
+
final int packageCount = permissionsForPackage.size();
for (int i = 0; i < packageCount; i++) {
String packageName = permissionsForPackage.keyAt(i);
@@ -4650,7 +4971,8 @@ final class Settings {
serializer.endDocument();
destination.finishWrite(out);
- if (Build.FINGERPRINT.equals(fingerprint)) {
+ if ((Build.FINGERPRINT.equals(fingerprint)) ||
+ (Build.DISPLAY.equals(displayversion))) {
mDefaultPermissionsGranted.put(userId, true);
}
// Any error while writing is fatal.
@@ -4733,8 +5055,11 @@ final class Settings {
switch (parser.getName()) {
case TAG_RUNTIME_PERMISSIONS: {
String fingerprint = parser.getAttributeValue(null, ATTR_FINGERPRINT);
+ String displayversion = parser.getAttributeValue(null, ATTR_DISPLAYVERSION);
mFingerprints.put(userId, fingerprint);
- final boolean defaultsGranted = Build.FINGERPRINT.equals(fingerprint);
+ mDisplayversion.put(userId, displayversion);
+ final boolean defaultsGranted = Build.FINGERPRINT.equals(fingerprint) ||
+ Build.DISPLAY.equals(displayversion);
mDefaultPermissionsGranted.put(userId, defaultsGranted);
} break;
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 9095f57..7a20e40 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -26,6 +26,7 @@ import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerPolicy.WindowState;
+import android.view.WindowManagerPolicyControl;
import com.android.internal.statusbar.IStatusBarService;
import java.io.PrintWriter;
@@ -119,7 +120,7 @@ public class BarController {
if (mWin != null) {
if (win != null && (win.getAttrs().privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) == 0) {
- int fl = PolicyControl.getWindowFlags(win, null);
+ int fl = WindowManagerPolicyControl.getWindowFlags(win, null);
if ((fl & mTranslucentWmFlag) != 0) {
vis |= mTranslucentFlag;
} else {
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 3cee927..c7cf7d3 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2010-2015 CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,26 +22,43 @@ import com.android.internal.app.AlertController.AlertParams;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.R;
+import com.android.internal.util.UserIcons;
import com.android.internal.widget.LockPatternUtils;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.INotificationManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
+import android.content.ServiceConnection;
import android.database.ContentObserver;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.Manifest;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
+import android.os.IPowerManager;
import android.os.Message;
+import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -49,6 +67,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
+import android.provider.Settings.Global;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.telephony.PhoneStateListener;
@@ -76,8 +95,15 @@ import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import android.widget.TextView;
+import cyanogenmod.providers.CMSettings;
+
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
+
+import org.cyanogenmod.internal.util.ThemeUtils;
+
+import static com.android.internal.util.cm.PowerMenuConstants.*;
/**
* Helper to show the global actions dialog. Each item is an {@link Action} that
@@ -90,20 +116,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private static final boolean SHOW_SILENT_TOGGLE = true;
- /* Valid settings for global actions keys.
- * see config.xml config_globalActionList */
- private static final String GLOBAL_ACTION_KEY_POWER = "power";
- private static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane";
- private static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport";
- private static final String GLOBAL_ACTION_KEY_SILENT = "silent";
- private static final String GLOBAL_ACTION_KEY_USERS = "users";
- private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
- private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
- private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
- private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
-
private final Context mContext;
private final WindowManagerFuncs mWindowManagerFuncs;
+ private Context mUiContext;
private final AudioManager mAudioManager;
private final IDreamManager mDreamManager;
@@ -123,6 +138,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private boolean mHasVibrator;
private final boolean mShowSilentToggle;
+ // Power menu customizations
+ String mActions;
+
/**
* @param context everything needs a context :(
*/
@@ -137,6 +155,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.UPDATE_POWER_MENU);
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mBroadcastReceiver, filter);
@@ -156,6 +175,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
+
+ updatePowerMenuActions();
}
/**
@@ -165,12 +186,14 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = isDeviceProvisioned;
- if (mDialog != null) {
+ if (mDialog != null && mUiContext == null) {
mDialog.dismiss();
mDialog = null;
+ mDialog = createDialog();
// Show delayed, so that the dismiss of the previous dialog completes
mHandler.sendEmptyMessage(MESSAGE_SHOW);
} else {
+ mDialog = createDialog();
handleShow();
}
}
@@ -189,7 +212,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private void handleShow() {
awakenIfNecessary();
- mDialog = createDialog();
prepareDialog();
// If we only have 1 item and it's a simple press action, just do this action.
@@ -206,6 +228,14 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ mUiContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+
/**
* Create the global actions dialog.
* @return A new dialog.
@@ -261,18 +291,31 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
onAirplaneModeChanged();
mItems = new ArrayList<Action>();
- String[] defaultActions = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_globalActionsList);
+
+ String[] actionsArray;
+ if (mActions == null) {
+ actionsArray = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_globalActionsList);
+ } else {
+ actionsArray = mActions.split("\\|");
+ }
+
+ // Always add the power off option
+ mItems.add(new PowerAction());
ArraySet<String> addedKeys = new ArraySet<String>();
- for (int i = 0; i < defaultActions.length; i++) {
- String actionKey = defaultActions[i];
+ for (int i = 0; i < actionsArray.length; i++) {
+ String actionKey = actionsArray[i];
if (addedKeys.contains(actionKey)) {
// If we already have added this, don't add it again.
continue;
}
if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
- mItems.add(new PowerAction());
+ continue;
+ } else if (GLOBAL_ACTION_KEY_REBOOT.equals(actionKey)) {
+ mItems.add(new RebootAction());
+ } else if (GLOBAL_ACTION_KEY_SCREENSHOT.equals(actionKey)) {
+ mItems.add(getScreenshotAction());
} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
mItems.add(mAirplaneModeOn);
} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
@@ -285,7 +328,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mItems.add(mSilentModeAction);
}
} else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
- if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
+ List<UserInfo> users = ((UserManager) mContext.getSystemService(
+ Context.USER_SERVICE)).getUsers();
+ if (users.size() > 1) {
addUsersToMenu(mItems);
}
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
@@ -305,12 +350,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mAdapter = new MyAdapter();
- AlertParams params = new AlertParams(mContext);
+ AlertParams params = new AlertParams(getUiContext());
params.mAdapter = mAdapter;
params.mOnClickListener = this;
params.mForceInverseBackground = true;
- GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
+ GlobalActionsDialog dialog = new GlobalActionsDialog(getUiContext(), params);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.getListView().setItemsCanFocus(true);
@@ -367,6 +412,53 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
}
+ private final class RebootAction extends SinglePressAction {
+ private RebootAction() {
+ super(com.android.internal.R.drawable.ic_lock_power_reboot,
+ R.string.global_action_reboot);
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ try {
+ IPowerManager pm = IPowerManager.Stub.asInterface(ServiceManager
+ .getService(Context.POWER_SERVICE));
+ pm.reboot(true, null, false);
+ } catch (RemoteException e) {
+ Log.e(TAG, "PowerManager service died!", e);
+ return;
+ }
+ }
+ }
+
+ private Action getScreenshotAction() {
+ return new SinglePressAction(com.android.internal.R.drawable.ic_lock_screenshot,
+ R.string.global_action_screenshot) {
+
+ public void onPress() {
+ takeScreenshot();
+ }
+
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+ };
+ }
+
private Action getBugReportAction() {
return new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
R.string.bugreport_title) {
@@ -423,7 +515,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
private Action getSettingsAction() {
- return new SinglePressAction(com.android.internal.R.drawable.ic_settings,
+ return new SinglePressAction(com.android.internal.R.drawable.ic_lock_settings,
R.string.global_action_settings) {
@Override
@@ -533,16 +625,24 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
if (um.isUserSwitcherEnabled()) {
List<UserInfo> users = um.getUsers();
UserInfo currentUser = getCurrentUser();
+ final int avatarSize = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.global_actions_avatar_size);
for (final UserInfo user : users) {
if (user.supportsSwitchTo()) {
boolean isCurrentUser = currentUser == null
? user.id == 0 : (currentUser.id == user.id);
- Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath)
- : null;
+ Drawable avatar = null;
+ Bitmap rawAvatar = um.getUserIcon(user.id);
+ if (rawAvatar == null) {
+ rawAvatar = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
+ user.isGuest() ? UserHandle.USER_NULL : user.id, /*light=*/ false));
+ }
+ avatar = new BitmapDrawable(mContext.getResources(),
+ createCircularClip(rawAvatar, avatarSize, avatarSize));
+
SinglePressAction switchToUser = new SinglePressAction(
- com.android.internal.R.drawable.ic_menu_cc, icon,
- (user.name != null ? user.name : "Primary")
- + (isCurrentUser ? " \u2714" : "")) {
+ com.android.internal.R.drawable.ic_lock_user, avatar,
+ (user.name != null ? user.name : "Primary")) {
public void onPress() {
try {
ActivityManagerNative.getDefault().switchUser(user.id);
@@ -559,12 +659,101 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
return false;
}
};
+ if (isCurrentUser) {
+ switchToUser.setStatus(mContext.getString(
+ R.string.global_action_current_user));
+ }
items.add(switchToUser);
}
}
}
}
+ /**
+ * functions needed for taking screenhots.
+ * This leverages the built in ICS screenshot functionality
+ */
+ final Object mScreenshotLock = new Object();
+ ServiceConnection mScreenshotConnection = null;
+
+ final Runnable mScreenshotTimeout = new Runnable() {
+ @Override public void run() {
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != null) {
+ mContext.unbindService(mScreenshotConnection);
+ mScreenshotConnection = null;
+ }
+ }
+ }
+ };
+
+ private void takeScreenshot() {
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != null) {
+ return;
+ }
+ ComponentName cn = new ComponentName("com.android.systemui",
+ "com.android.systemui.screenshot.TakeScreenshotService");
+ Intent intent = new Intent();
+ intent.setComponent(cn);
+ ServiceConnection conn = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != this) {
+ return;
+ }
+ Messenger messenger = new Messenger(service);
+ Message msg = Message.obtain(null, 1);
+ final ServiceConnection myConn = this;
+ Handler h = new Handler(mHandler.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection == myConn) {
+ mContext.unbindService(mScreenshotConnection);
+ mScreenshotConnection = null;
+ mHandler.removeCallbacks(mScreenshotTimeout);
+ }
+ }
+ }
+ };
+ msg.replyTo = new Messenger(h);
+ msg.arg1 = msg.arg2 = 0;
+
+ /* remove for the time being
+ if (mStatusBar != null && mStatusBar.isVisibleLw())
+ msg.arg1 = 1;
+ if (mNavigationBar != null && mNavigationBar.isVisibleLw())
+ msg.arg2 = 1;
+ */
+
+ /* wait for the dialog box to close */
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ // Do nothing
+ }
+
+ /* take the screenshot */
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ // Do nothing
+ }
+ }
+ }
+ @Override
+ public void onServiceDisconnected(ComponentName name) {}
+ };
+ if (mContext.bindServiceAsUser(
+ intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
+ mScreenshotConnection = conn;
+ mHandler.postDelayed(mScreenshotTimeout, 10000);
+ }
+ }
+ }
+
private void prepareDialog() {
refreshSilentMode();
mAirplaneModeOn.updateState(mAirplaneState);
@@ -671,7 +860,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position);
- return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
+ final Context context = getUiContext();
+ return action.create(context, convertView, parent, LayoutInflater.from(context));
}
}
@@ -726,6 +916,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private final Drawable mIcon;
private final int mMessageResId;
private final CharSequence mMessage;
+ private CharSequence mStatusMessage;
protected SinglePressAction(int iconResId, int messageResId) {
mIconResId = iconResId;
@@ -752,8 +943,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
return true;
}
- public String getStatus() {
- return null;
+ public CharSequence getStatus() {
+ return mStatusMessage;
+ }
+
+ public void setStatus(CharSequence status) {
+ mStatusMessage = status;
}
abstract public void onPress();
@@ -774,7 +969,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
TextView messageView = (TextView) v.findViewById(R.id.message);
TextView statusView = (TextView) v.findViewById(R.id.status);
- final String status = getStatus();
+ final CharSequence status = getStatus();
if (!TextUtils.isEmpty(status)) {
statusView.setText(status);
} else {
@@ -782,7 +977,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
if (mIcon != null) {
icon.setImageDrawable(mIcon);
- icon.setScaleType(ScaleType.CENTER_CROP);
+ icon.setScaleType(ScaleType.CENTER);
} else if (mIconResId != 0) {
icon.setImageDrawable(context.getDrawable(mIconResId));
}
@@ -952,9 +1147,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
}
- private static class SilentModeTriStateAction implements Action, View.OnClickListener {
+ private final class SilentModeTriStateAction implements Action, View.OnClickListener {
- private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 };
+ private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3, R.id.option4 };
private final AudioManager mAudioManager;
private final Handler mHandler;
@@ -966,14 +1161,15 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mContext = context;
}
- private int ringerModeToIndex(int ringerMode) {
- // They just happen to coincide
- return ringerMode;
- }
-
private int indexToRingerMode(int index) {
- // They just happen to coincide
- return index;
+ if (index == 2) {
+ if (mHasVibrator) {
+ return AudioManager.RINGER_MODE_VIBRATE;
+ } else {
+ return AudioManager.RINGER_MODE_NORMAL;
+ }
+ }
+ return AudioManager.RINGER_MODE_NORMAL;
}
@Override
@@ -985,9 +1181,28 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
LayoutInflater inflater) {
View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false);
- int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode());
- for (int i = 0; i < 3; i++) {
+ int ringerMode = mAudioManager.getRingerModeInternal();
+ int zenMode = Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE,
+ Global.ZEN_MODE_OFF);
+ int selectedIndex = 0;
+ if (zenMode != Global.ZEN_MODE_OFF) {
+ if (zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ selectedIndex = 0;
+ } else if (zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
+ selectedIndex = 1;
+ }
+ } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ selectedIndex = 2;
+ } else if (ringerMode == AudioManager.RINGER_MODE_NORMAL) {
+ selectedIndex = 3;
+ }
+
+ for (int i = 0; i < ITEM_IDS.length; i++) {
View itemView = v.findViewById(ITEM_IDS[i]);
+ if (!mHasVibrator && i == 2) {
+ itemView.setVisibility(View.GONE);
+ continue;
+ }
itemView.setSelected(selectedIndex == i);
// Set up click handler
itemView.setTag(i);
@@ -1018,7 +1233,28 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
if (!(v.getTag() instanceof Integer)) return;
int index = (Integer) v.getTag();
- mAudioManager.setRingerMode(indexToRingerMode(index));
+ if (index == 0 || index == 1) {
+ int zenMode = index == 0
+ ? Global.ZEN_MODE_NO_INTERRUPTIONS
+ : Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ // ZenModeHelper will revert zen mode back to the previous value if we just
+ // put the value into the Settings db, so use INotificationManager instead
+ INotificationManager noMan = INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ try {
+ noMan.setZenMode(zenMode, null, TAG);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to set zen mode", e);
+ }
+ } else {
+ Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
+ }
+
+ if (index == 2 || index == 3) {
+ int ringerMode = indexToRingerMode(index);
+ mAudioManager.setRingerModeInternal(ringerMode);
+ }
+ mAdapter.notifyDataSetChanged();
mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY);
}
}
@@ -1040,10 +1276,24 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mIsWaitingForEcmExit = false;
changeAirplaneModeSystemSetting(true);
}
+ } else if (Intent.UPDATE_POWER_MENU.equals(action)) {
+ updatePowerMenuActions();
}
}
};
+ protected void updatePowerMenuActions() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mActions = CMSettings.Secure.getStringForUser(resolver,
+ CMSettings.Secure.POWER_MENU_ACTIONS, UserHandle.USER_CURRENT);
+ }
+
+ private BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ };
+
PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
@@ -1125,6 +1375,33 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
}
+ /**
+ * Generate a new bitmap (width x height pixels, ARGB_8888) with the input bitmap scaled
+ * to fit and clipped to an inscribed circle.
+ * @param input Bitmap to resize and clip
+ * @param width Width of output bitmap (and diameter of circle)
+ * @param height Height of output bitmap
+ * @return A shiny new bitmap for you to use
+ */
+ private static Bitmap createCircularClip(Bitmap input, int width, int height) {
+ if (input == null) return null;
+
+ final int inWidth = input.getWidth();
+ final int inHeight = input.getHeight();
+ final Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(output);
+ final Paint paint = new Paint();
+ paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
+ paint.setAntiAlias(true);
+ final RectF srcRect = new RectF(0, 0, inWidth, inHeight);
+ final RectF dstRect = new RectF(0, 0, width, height);
+ final Matrix m = new Matrix();
+ m.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.CENTER);
+ canvas.setMatrix(m);
+ canvas.drawCircle(inWidth / 2, inHeight / 2, inWidth / 2, paint);
+ return output;
+ }
+
private static final class GlobalActionsDialog extends Dialog implements DialogInterface {
private final Context mContext;
private final int mWindowTouchSlop;
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 160d44c..da9312c 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -44,6 +44,7 @@ import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.FrameLayout;
+import android.view.WindowManagerPolicyControl;
import com.android.internal.R;
/**
@@ -116,7 +117,7 @@ public class ImmersiveModeConfirmation {
boolean userSetupComplete) {
mHandler.removeMessages(H.SHOW);
if (isImmersiveMode) {
- final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
+ final boolean disabled = WindowManagerPolicyControl.disableImmersiveConfirmation(pkg);
if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s",
disabled, mConfirmed));
if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed) && userSetupComplete) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0cbf614..cd99038 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -31,6 +31,7 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
@@ -47,6 +48,7 @@ import android.graphics.Rect;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
+import android.hardware.input.InputManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -81,6 +83,11 @@ import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
+import com.android.internal.os.DeviceKeyHandler;
+
+import com.android.internal.util.cm.ActionUtils;
+import cyanogenmod.providers.CMSettings;
+import dalvik.system.DexClassLoader;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -114,9 +121,14 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+import android.view.WindowManagerPolicyControl;
+import android.widget.Toast;
+
import com.android.internal.R;
+import com.android.internal.policy.IKeyguardService;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ScreenShapeHelper;
+import com.android.internal.view.RotationPolicy;
import com.android.internal.widget.PointerLocationView;
import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
@@ -129,6 +141,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
+import java.lang.reflect.Constructor;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
@@ -201,6 +214,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
+ // Available custom actions to perform on a key press.
+ // Must match values for KEY_HOME_LONG_PRESS_ACTION in:
+ // core/java/android/provider/Settings.java
+ private static final int KEY_ACTION_NOTHING = 0;
+ private static final int KEY_ACTION_MENU = 1;
+ private static final int KEY_ACTION_APP_SWITCH = 2;
+ private static final int KEY_ACTION_SEARCH = 3;
+ private static final int KEY_ACTION_VOICE_SEARCH = 4;
+ private static final int KEY_ACTION_IN_APP_SEARCH = 5;
+ private static final int KEY_ACTION_LAUNCH_CAMERA = 6;
+ private static final int KEY_ACTION_SLEEP = 7;
+ private static final int KEY_ACTION_LAST_APP = 8;
+
+ // Masks for checking presence of hardware keys.
+ // Must match values in core/res/res/values/config.xml
+ private static final int KEY_MASK_HOME = 0x01;
+ private static final int KEY_MASK_BACK = 0x02;
+ private static final int KEY_MASK_MENU = 0x04;
+ private static final int KEY_MASK_ASSIST = 0x08;
+ private static final int KEY_MASK_APP_SWITCH = 0x10;
+ private static final int KEY_MASK_CAMERA = 0x20;
+ private static final int KEY_MASK_VOLUME = 0x40;
+
+
/**
* These are the system UI flags that, when changing, can cause the layout
* of the screen to change.
@@ -217,6 +254,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
+ /**
+ * Broadcast Action: WiFi Display video is enabled or disabled
+ *
+ * <p>The intent will have the following extra values:</p>
+ * <ul>
+ * <li><em>state</em> - 0 for disabled, 1 for enabled. </li>
+ * </ul>
+ */
+
+ private static final String ACTION_WIFI_DISPLAY_VIDEO =
+ "org.codeaurora.intent.action.WIFI_DISPLAY_VIDEO";
+
+
// The panic gesture may become active only after the keyguard is dismissed and the immersive
// app shows again. If that doesn't happen for 30s we drop the gesture.
private static final long PANIC_GESTURE_EXPIRATION = 30000;
@@ -254,6 +304,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
+ private DeviceKeyHandler mDeviceKeyHandler;
+
/**
* Lock protecting internal state. Must not call out into window
* manager with lock held. (This lock will be acquired in places
@@ -313,10 +365,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mCanHideNavigationBar = false;
boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
+ boolean mNavigationBarLeftInLandscape = false; // Navigation bar left handed?
int[] mNavigationBarHeightForRotation = new int[4];
int[] mNavigationBarWidthForRotation = new int[4];
- boolean mBootMessageNeedsHiding;
+ WindowState mKeyguardPanel;
+
KeyguardServiceDelegate mKeyguardDelegate;
final Runnable mWindowManagerDrawCallback = new Runnable() {
@Override
@@ -330,6 +384,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void onDrawn() {
if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
+ hideBootMessages();
}
};
@@ -367,6 +422,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mUiMode;
int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
int mLidOpenRotation;
+ boolean mHasRemovableLid;
int mCarDockRotation;
int mDeskDockRotation;
int mUndockedHdmiRotation;
@@ -384,6 +440,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
int mUserRotation = Surface.ROTATION_0;
+ int mUserRotationAngles = -1;
boolean mAccelerometerDefault;
boolean mSupportAutoRotation;
@@ -409,6 +466,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mHasSoftInput = false;
boolean mTranslucentDecorEnabled = true;
boolean mUseTvRouting;
+ int mBackKillTimeout;
+
+ int mDeviceHardwareKeys;
+
+ // Button wake control flags
+ boolean mHomeWakeScreen;
+ boolean mBackWakeScreen;
+ boolean mMenuWakeScreen;
+ boolean mAssistWakeScreen;
+ boolean mAppSwitchWakeScreen;
+ boolean mCameraWakeScreen;
+ boolean mVolumeWakeScreen;
+
+ // Camera button control flags and actions
+ boolean mCameraSleepOnRelease;
+ boolean mIsFocusPressed;
+ boolean mCameraLaunch;
+
+ // During wakeup by volume keys, we still need to capture subsequent events
+ // until the key is released. This is required since the beep sound is produced
+ // post keypressed.
+ boolean mVolumeWakeTriggered;
int mPointerLocationMode = 0; // guarded by mLock
@@ -416,6 +495,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState mFocusedWindow;
IApplicationToken mFocusedApp;
+ // Behavior of volbtn music controls
+ boolean mVolBtnMusicControls;
+ boolean mIsLongPress;
+
PointerLocationView mPointerLocationView;
// The current size of the screen; really; extends into the overscan area of
@@ -443,6 +526,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// fullscreen window flag, these are the stable dimensions without the status bar.
int mStableFullscreenLeft, mStableFullscreenTop;
int mStableFullscreenRight, mStableFullscreenBottom;
+ // For force immersive mode
+ int mForceImmersiveLeft, mForceImmersiveTop;
+ int mForceImmersiveRight, mForceImmersiveBottom;
// During layout, the current screen borders with all outer decoration
// (status bar, input method dock) accounted for.
int mCurLeft, mCurTop, mCurRight, mCurBottom;
@@ -500,6 +586,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mForcingShowNavBar;
int mForcingShowNavBarLayer;
+ boolean mDevForceNavbar = false;
+
// States of keyguard dismiss.
private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
@@ -534,6 +622,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mHomePressed;
boolean mHomeConsumed;
boolean mHomeDoubleTapPending;
+ boolean mMenuPressed;
+ boolean mAppSwitchLongPressed;
Intent mHomeIntent;
Intent mCarDockIntent;
Intent mDeskDockIntent;
@@ -542,6 +632,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mAssistKeyLongPressed;
boolean mPendingMetaAction;
+ // Tracks user-customisable behavior for certain key events
+ private int mLongPressOnHomeBehavior = -1;
+ private int mPressOnMenuBehavior = -1;
+ private int mLongPressOnMenuBehavior = -1;
+ private int mPressOnAssistBehavior = -1;
+ private int mLongPressOnAssistBehavior = -1;
+ private int mPressOnAppSwitchBehavior = -1;
+ private int mLongPressOnAppSwitchBehavior = -1;
+
// support for activating the lock screen while the screen is on
boolean mAllowLockscreenWhenOn;
int mLockScreenTimeout;
@@ -554,6 +653,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
int mIncallPowerBehavior;
+ // Behavior of HOME button during incomming call ring.
+ // (See Settings.Secure.RING_HOME_BUTTON_BEHAVIOR.)
+ int mRingHomeBehavior;
+
Display mDisplay;
private int mDisplayRotation;
@@ -568,9 +671,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mOverscanRight = 0;
int mOverscanBottom = 0;
- // What we do when the user long presses on home
- private int mLongPressOnHomeBehavior;
-
// What we do when the user double-taps on home
private int mDoubleTapOnHomeBehavior;
@@ -637,6 +737,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_POWER_DELAYED_PRESS = 13;
private static final int MSG_POWER_LONG_PRESS = 14;
private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
+ private static final int MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK = 16;
+ private static final int MSG_CAMERA_LONG_PRESS = 17;
+
+ boolean mWifiDisplayConnected = false;
+ int mWifiDisplayCustomRotation = -1;
+
+ private boolean mHasPermanentMenuKey;
+ private boolean mClearedBecauseOfForceShow;
+ private boolean mTopWindowIsKeyguard;
private class PolicyHandler extends Handler {
@Override
@@ -688,6 +797,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
updateDreamingSleepToken(msg.arg1 != 0);
break;
+ case MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK: {
+ KeyEvent event = (KeyEvent) msg.obj;
+ mIsLongPress = true;
+ dispatchMediaKeyWithWakeLockToAudioService(event);
+ dispatchMediaKeyWithWakeLockToAudioService(
+ KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
+ break;
+ }
+ case MSG_CAMERA_LONG_PRESS: {
+ KeyEvent event = (KeyEvent) msg.obj;
+ mIsLongPress = true;
+ break;
+ }
}
}
}
@@ -713,6 +835,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR), false, this,
+ UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
UserHandle.USER_ALL);
@@ -728,6 +853,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.POINTER_LOCATION), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_HOME_LONG_PRESS_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_HOME_DOUBLE_TAP_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_MENU_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_MENU_LONG_PRESS_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_ASSIST_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_ASSIST_LONG_PRESS_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_APP_SWITCH_ACTION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION), false, this,
+ UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
UserHandle.USER_ALL);
@@ -737,6 +886,48 @@ public class PhoneWindowManager implements WindowManagerPolicy {
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.POLICY_CONTROL), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.ACCELEROMETER_ROTATION_ANGLES), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.VOLBTN_MUSIC_CONTROLS), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.BACK_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.MENU_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.ASSIST_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.APP_SWITCH_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.CAMERA_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.CAMERA_SLEEP_ON_RELEASE), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.CAMERA_LAUNCH), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.VOLUME_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.HOME_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.VOLUME_WAKE_SCREEN), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE), false, this,
+ UserHandle.USER_ALL);
updateSettings();
}
@@ -906,7 +1097,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
- if (panic) {
+ if (panic && !WindowManagerPolicyControl.isImmersiveFiltersActive()) {
mHandler.post(mHiddenNavPanic);
}
@@ -1211,6 +1402,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
}
+ Runnable mBackLongPress = new Runnable() {
+ public void run() {
+ if (!unpinActivity(false) && ActionUtils.killForegroundApp(mContext, mCurrentUserId)) {
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ Toast.makeText(mContext, R.string.app_killed_message, Toast.LENGTH_SHORT).show();
+ }
+ }
+ };
+
void showGlobalActionsInternal() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
if (mGlobalActions == null) {
@@ -1290,26 +1490,57 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private void handleLongPressOnHome(int deviceId) {
- if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
- mHomeConsumed = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ private void triggerVirtualKeypress(final int keyCode) {
+ InputManager im = InputManager.getInstance();
+ long now = SystemClock.uptimeMillis();
+ final KeyEvent downEvent = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
+ keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+ KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_KEYBOARD);
+ final KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP);
- if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
- toggleRecentApps();
- } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_ASSIST) {
- launchAssistAction(null, deviceId);
- }
- }
+ im.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ im.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
- private void handleDoubleTapOnHome() {
- if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
- mHomeConsumed = true;
- toggleRecentApps();
- }
+ private void launchCameraAction() {
+ sendCloseSystemWindows();
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
}
+ private void performKeyAction(int behavior, KeyEvent event) {
+ switch (behavior) {
+ case KEY_ACTION_NOTHING:
+ break;
+ case KEY_ACTION_MENU:
+ triggerVirtualKeypress(KeyEvent.KEYCODE_MENU);
+ break;
+ case KEY_ACTION_APP_SWITCH:
+ toggleRecentApps();
+ break;
+ case KEY_ACTION_SEARCH:
+ launchAssistAction(null, event.getDeviceId());
+ break;
+ case KEY_ACTION_VOICE_SEARCH:
+ launchAssistLongPressAction();
+ break;
+ case KEY_ACTION_IN_APP_SEARCH:
+ triggerVirtualKeypress(KeyEvent.KEYCODE_SEARCH);
+ break;
+ case KEY_ACTION_LAUNCH_CAMERA:
+ launchCameraAction();
+ break;
+ case KEY_ACTION_SLEEP:
+ mPowerManager.goToSleep(SystemClock.uptimeMillis());
+ break;
+ case KEY_ACTION_LAST_APP:
+ ActionUtils.switchToLastApp(mContext, mCurrentUserId);
+ break;
+ default:
+ break;
+ }
+ }
+
private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
@Override
public void run() {
@@ -1461,7 +1692,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
- readConfigurationDependentBehaviors();
+ mDeviceHardwareKeys = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_deviceHardwareKeys);
+ mHasRemovableLid = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_hasRemovableLid);
+ mBackKillTimeout = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_backKillTimeout);
+
+ updateKeyAssignments();
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
Context.ACCESSIBILITY_SERVICE);
@@ -1507,7 +1745,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
public void onSwipeFromRight() {
- if (mNavigationBar != null && !mNavigationBarOnBottom) {
+ if (mNavigationBar != null && !mNavigationBarOnBottom &&
+ !mNavigationBarLeftInLandscape) {
+ requestTransientBars(mNavigationBar);
+ }
+ }
+ @Override
+ public void onSwipeFromLeft() {
+ if (mNavigationBar != null && !mNavigationBarOnBottom &&
+ mNavigationBarLeftInLandscape) {
requestTransientBars(mNavigationBar);
}
}
@@ -1535,6 +1781,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
+
+ /* Register for WIFI Display Intents */
+ IntentFilter wifiDisplayFilter = new IntentFilter(ACTION_WIFI_DISPLAY_VIDEO);
+ Intent wifidisplayIntent = context.registerReceiver(
+ mWifiDisplayReceiver, wifiDisplayFilter);
mLongPressVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_longPressVibePattern);
mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
@@ -1568,27 +1819,125 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerInternal.registerAppTransitionListener(
mStatusBarController.getAppTransitionListener());
+
+ String deviceKeyHandlerLib = mContext.getResources().getString(
+ com.android.internal.R.string.config_deviceKeyHandlerLib);
+
+ String deviceKeyHandlerClass = mContext.getResources().getString(
+ com.android.internal.R.string.config_deviceKeyHandlerClass);
+
+ if (!deviceKeyHandlerLib.isEmpty() && !deviceKeyHandlerClass.isEmpty()) {
+ DexClassLoader loader = new DexClassLoader(deviceKeyHandlerLib,
+ new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
+ null,
+ ClassLoader.getSystemClassLoader());
+ try {
+ Class<?> klass = loader.loadClass(deviceKeyHandlerClass);
+ Constructor<?> constructor = klass.getConstructor(Context.class);
+ mDeviceKeyHandler = (DeviceKeyHandler) constructor.newInstance(
+ mContext);
+ if(DEBUG) Slog.d(TAG, "Device key handler loaded");
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not instantiate device key handler "
+ + deviceKeyHandlerClass + " from class "
+ + deviceKeyHandlerLib, e);
+ }
+ }
+
}
- /**
- * Read values from config.xml that may be overridden depending on
- * the configuration of the device.
- * eg. Disable long press on home goes to recents on sw600dp.
- */
- private void readConfigurationDependentBehaviors() {
+ private void updateKeyAssignments() {
+ int activeHardwareKeys = mDeviceHardwareKeys;
+
+ if (mDevForceNavbar) {
+ activeHardwareKeys = 0;
+ }
+ final boolean hasMenu = (activeHardwareKeys & KEY_MASK_MENU) != 0;
+ final boolean hasHome = (activeHardwareKeys & KEY_MASK_HOME) != 0;
+ final boolean hasAssist = (activeHardwareKeys & KEY_MASK_ASSIST) != 0;
+ final boolean hasAppSwitch = (activeHardwareKeys & KEY_MASK_APP_SWITCH) != 0;
+
+ final ContentResolver resolver = mContext.getContentResolver();
+
+ // Initialize all assignments to sane defaults.
+ mPressOnMenuBehavior = KEY_ACTION_MENU;
+
+ mLongPressOnMenuBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnMenuBehavior);
+
+ if (mLongPressOnMenuBehavior == KEY_ACTION_NOTHING &&
+ (hasMenu && !hasAssist)) {
+ mLongPressOnMenuBehavior = KEY_ACTION_SEARCH;
+ }
+ mPressOnAssistBehavior = KEY_ACTION_SEARCH;
+ mLongPressOnAssistBehavior = KEY_ACTION_VOICE_SEARCH;
+ mPressOnAppSwitchBehavior = KEY_ACTION_APP_SWITCH;
+ mLongPressOnAppSwitchBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnAppSwitchBehavior);
+
mLongPressOnHomeBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnHomeBehavior);
- if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
- mLongPressOnHomeBehavior > LONG_PRESS_HOME_ASSIST) {
- mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
+ if (mLongPressOnHomeBehavior < KEY_ACTION_NOTHING ||
+ mLongPressOnHomeBehavior > KEY_ACTION_SLEEP) {
+ mLongPressOnHomeBehavior = KEY_ACTION_NOTHING;
}
mDoubleTapOnHomeBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
- if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
- mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
- mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
+ if (mDoubleTapOnHomeBehavior < KEY_ACTION_NOTHING ||
+ mDoubleTapOnHomeBehavior > KEY_ACTION_SLEEP) {
+ mDoubleTapOnHomeBehavior = KEY_ACTION_NOTHING;
+ }
+
+ boolean hasPermanentMenu = false;
+
+ // Check for custom assignments and whether KEY_ACTION_MENU is assigned.
+ if (hasHome) {
+ mLongPressOnHomeBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_HOME_LONG_PRESS_ACTION,
+ mLongPressOnHomeBehavior, UserHandle.USER_CURRENT);
+ mDoubleTapOnHomeBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_HOME_DOUBLE_TAP_ACTION,
+ mDoubleTapOnHomeBehavior, UserHandle.USER_CURRENT);
+
+ hasPermanentMenu = mLongPressOnHomeBehavior == KEY_ACTION_MENU
+ || mDoubleTapOnHomeBehavior == KEY_ACTION_MENU;
}
+ if (hasMenu) {
+ mPressOnMenuBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_MENU_ACTION,
+ mPressOnMenuBehavior, UserHandle.USER_CURRENT);
+ mLongPressOnMenuBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_MENU_LONG_PRESS_ACTION,
+ mLongPressOnMenuBehavior, UserHandle.USER_CURRENT);
+
+ hasPermanentMenu |= mPressOnMenuBehavior == KEY_ACTION_MENU
+ || mLongPressOnMenuBehavior == KEY_ACTION_MENU;
+ }
+ if (hasAssist) {
+ mPressOnAssistBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_ASSIST_ACTION,
+ mPressOnAssistBehavior, UserHandle.USER_CURRENT);
+ mLongPressOnAssistBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_ASSIST_LONG_PRESS_ACTION,
+ mLongPressOnAssistBehavior, UserHandle.USER_CURRENT);
+
+ hasPermanentMenu |= mPressOnAssistBehavior == KEY_ACTION_MENU
+ || mLongPressOnAssistBehavior == KEY_ACTION_MENU;
+ }
+ if (hasAppSwitch) {
+ mPressOnAppSwitchBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_APP_SWITCH_ACTION,
+ mPressOnAppSwitchBehavior, UserHandle.USER_CURRENT);
+ mLongPressOnAppSwitchBehavior = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION,
+ mLongPressOnAppSwitchBehavior, UserHandle.USER_CURRENT);
+
+ hasPermanentMenu |= mPressOnAppSwitchBehavior == KEY_ACTION_MENU
+ || mLongPressOnAppSwitchBehavior == KEY_ACTION_MENU;
+ }
+
+ mHasPermanentMenuKey = hasPermanentMenu;
}
@Override
@@ -1697,7 +2046,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* navigation bar and touch exploration is not enabled
*/
private boolean canHideNavigationBar() {
- return mHasNavigationBar
+ return hasNavigationBar()
&& !mAccessibilityManager.isTouchExplorationEnabled();
}
@@ -1719,6 +2068,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void updateSettings() {
ContentResolver resolver = mContext.getContentResolver();
boolean updateRotation = false;
+ int mDeviceHardwareWakeKeys = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_deviceHardwareWakeKeys);
synchronized (mLock) {
mEndcallBehavior = Settings.System.getIntForUser(resolver,
Settings.System.END_BUTTON_BEHAVIOR,
@@ -1728,6 +2079,37 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
UserHandle.USER_CURRENT);
+ mRingHomeBehavior = CMSettings.Secure.getIntForUser(resolver,
+ CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR,
+ CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR_DEFAULT,
+ UserHandle.USER_CURRENT);
+ mHomeWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.HOME_WAKE_SCREEN, 1, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_HOME) != 0);
+ mBackWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.BACK_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_BACK) != 0);
+ mMenuWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.MENU_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_MENU) != 0);
+ mAssistWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.ASSIST_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_ASSIST) != 0);
+ mAppSwitchWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.APP_SWITCH_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_APP_SWITCH) != 0);
+ mCameraWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.CAMERA_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_CAMERA) != 0);
+ mCameraSleepOnRelease = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.CAMERA_SLEEP_ON_RELEASE, 0, UserHandle.USER_CURRENT) == 1);
+ mCameraLaunch = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.CAMERA_LAUNCH, 0, UserHandle.USER_CURRENT) == 1);
+ mVolumeWakeScreen = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.VOLUME_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
+ ((mDeviceHardwareWakeKeys & KEY_MASK_VOLUME) != 0);
+ mVolBtnMusicControls = (CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.VOLBTN_MUSIC_CONTROLS, 1, UserHandle.USER_CURRENT) == 1);
// Configure wake gesture.
boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
@@ -1738,6 +2120,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateWakeGestureListenerLp();
}
+ boolean devForceNavbar = CMSettings.Secure.getIntForUser(resolver,
+ CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1;
+ if (devForceNavbar != mDevForceNavbar) {
+ mDevForceNavbar = devForceNavbar;
+ }
+
+ mNavigationBarLeftInLandscape = CMSettings.System.getIntForUser(resolver,
+ CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE, 0, UserHandle.USER_CURRENT) == 1;
+
+ updateKeyAssignments();
+
// Configure rotation lock.
int userRotation = Settings.System.getIntForUser(resolver,
Settings.System.USER_ROTATION, Surface.ROTATION_0,
@@ -1756,6 +2149,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateOrientationListenerLp();
}
+ mUserRotationAngles = Settings.System.getInt(resolver,
+ Settings.System.ACCELEROMETER_ROTATION_ANGLES, -1);
+
if (mSystemReady) {
int pointerLocation = Settings.System.getIntForUser(resolver,
Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
@@ -1780,7 +2176,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
- PolicyControl.reloadFromSetting(mContext);
+ WindowManagerPolicyControl.reloadFromSetting(mContext);
}
if (updateRotation) {
updateRotation(true);
@@ -1897,6 +2293,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
break;
+ case TYPE_KEYGUARD_PANEL:
+ permission =
+ org.cyanogenmod.platform.internal.Manifest.permission.THIRD_PARTY_KEYGUARD;
+ break;
default:
permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
}
@@ -1978,6 +2378,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_SYSTEM_DIALOG:
case TYPE_VOLUME_OVERLAY:
case TYPE_PRIVATE_PRESENTATION:
+ case TYPE_KEYGUARD_PANEL:
break;
}
@@ -2041,13 +2442,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private boolean isBuiltInKeyboardVisible() {
+ return mHaveBuiltInKeyboard && !isHidden(mLidKeyboardAccessibility);
+ }
+
/** {@inheritDoc} */
@Override
public void adjustConfigurationLw(Configuration config, int keyboardPresence,
int navigationPresence) {
mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
- readConfigurationDependentBehaviors();
readLidState();
applyLidSwitchState();
@@ -2113,6 +2517,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the safety window that shows behind keyguard while keyguard is starting
return 14;
case TYPE_STATUS_BAR_SUB_PANEL:
+ case TYPE_KEYGUARD_PANEL:
return 15;
case TYPE_STATUS_BAR:
return 16;
@@ -2189,7 +2594,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
- if (mHasNavigationBar) {
+ if (hasNavigationBar()) {
// For a basic navigation bar, when we are in landscape mode we place
// the navigation bar to the side.
if (mNavigationBarCanMove && fullWidth > fullHeight) {
@@ -2201,7 +2606,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
- if (mHasNavigationBar) {
+ if (hasNavigationBar()) {
// For a basic navigation bar, when we are in portrait mode we place
// the navigation bar to the bottom.
if (!mNavigationBarCanMove || fullWidth < fullHeight) {
@@ -2453,6 +2858,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager");
break;
+ case TYPE_KEYGUARD_PANEL:
+ mContext.enforceCallingOrSelfPermission(
+ org.cyanogenmod.platform.internal.Manifest.permission.THIRD_PARTY_KEYGUARD,
+ "PhoneWindowManager");
+ if (mKeyguardPanel != null) {
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
+ }
+ mKeyguardPanel = win;
+ break;
case TYPE_KEYGUARD_SCRIM:
if (mKeyguardScrim != null) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
@@ -2473,9 +2887,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else if (mKeyguardScrim == win) {
Log.v(TAG, "Removing keyguard scrim");
mKeyguardScrim = null;
- } if (mNavigationBar == win) {
+ } else if (mNavigationBar == win) {
mNavigationBar = null;
mNavigationBarController.setWindow(null);
+ } else if (mKeyguardPanel == win) {
+ mKeyguardPanel = null;
}
}
@@ -2499,7 +2915,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (win.getAttrs().windowAnimations != 0) {
return 0;
}
- // This can be on either the bottom or the right.
+ // This can be on either the bottom, left, or the right.
if (mNavigationBarOnBottom) {
if (transit == TRANSIT_EXIT
|| transit == TRANSIT_HIDE) {
@@ -2511,10 +2927,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
if (transit == TRANSIT_EXIT
|| transit == TRANSIT_HIDE) {
- return R.anim.dock_right_exit;
+ return mNavigationBarLeftInLandscape
+ ? R.anim.dock_left_exit : R.anim.dock_right_exit;
} else if (transit == TRANSIT_ENTER
|| transit == TRANSIT_SHOW) {
- return R.anim.dock_right_enter;
+ return mNavigationBarLeftInLandscape
+ ? R.anim.dock_left_enter : R.anim.dock_right_enter;
}
}
}
@@ -2602,9 +3020,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
- public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
+ public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade,
+ boolean keyguardShowingMedia) {
if (goingToNotificationShade) {
return null;
+ } else if (keyguardShowingMedia) {
+ return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit_noop);
} else {
return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
}
@@ -2652,12 +3073,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
final boolean keyguardOn = keyguardOn();
- final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
final int metaState = event.getMetaState();
final int flags = event.getFlags();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
+ final boolean longPress = (flags & KeyEvent.FLAG_LONG_PRESS) != 0;
+ final boolean virtualKey = event.getDeviceId() == KeyCharacterMap.VIRTUAL_KEYBOARD;
+ final int keyCode = event.getKeyCode();
if (DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
@@ -2692,6 +3115,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPendingMetaAction = false;
}
+ if (keyCode == KeyEvent.KEYCODE_BACK && !down) {
+ mHandler.removeCallbacks(mBackLongPress);
+ }
+
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
@@ -2701,7 +3128,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (!down) {
- cancelPreloadRecentApps();
+ if (mDoubleTapOnHomeBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
mHomePressed = false;
if (mHomeConsumed) {
@@ -2719,12 +3148,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// and his ONLY options are to answer or reject the call.)
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null && telecomManager.isRinging()) {
- Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
- return -1;
+ if ((mRingHomeBehavior
+ & CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR_ANSWER) != 0) {
+ Log.i(TAG, "Answering with HOME button.");
+ telecomManager.acceptRingingCall();
+ return -1;
+ } else {
+ Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+ return -1;
+ }
}
// Delay handling home if a double-tap is possible.
- if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
+ if (mDoubleTapOnHomeBehavior != KEY_ACTION_NOTHING) {
mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
mHomeDoubleTapPending = true;
mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
@@ -2762,44 +3198,83 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mHomeDoubleTapPending) {
mHomeDoubleTapPending = false;
mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
- handleDoubleTapOnHome();
- } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
- || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
+ performKeyAction(mDoubleTapOnHomeBehavior, event);
+ mHomeConsumed = mDoubleTapOnHomeBehavior != KEY_ACTION_SLEEP;
+ } else if (mLongPressOnHomeBehavior == KEY_ACTION_APP_SWITCH
+ || mDoubleTapOnHomeBehavior == KEY_ACTION_APP_SWITCH) {
preloadRecentApps();
}
- } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
- if (!keyguardOn) {
- handleLongPressOnHome(event.getDeviceId());
+ } else if (longPress) {
+ if (!keyguardOn && !mHomeConsumed &&
+ mLongPressOnHomeBehavior != KEY_ACTION_NOTHING) {
+ if (mLongPressOnHomeBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ mHomePressed = true;
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ performKeyAction(mLongPressOnHomeBehavior, event);
+ mHomeConsumed = true;
}
}
return -1;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
// Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON;
+ if (virtualKey || keyguardOn) {
+ // Let the app handle the key
+ return 0;
+ }
- if (down && repeatCount == 0) {
- if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
- Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
- null, null, null, 0, null, null);
- return -1;
- } else if (SHOW_PROCESSES_ON_ALT_MENU &&
- (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
- Intent service = new Intent();
- service.setClassName(mContext, "com.android.server.LoadAverageService");
- ContentResolver res = mContext.getContentResolver();
- boolean shown = Settings.Global.getInt(
- res, Settings.Global.SHOW_PROCESSES, 0) != 0;
- if (!shown) {
- mContext.startService(service);
- } else {
- mContext.stopService(service);
+ if (down) {
+ if (mPressOnMenuBehavior == KEY_ACTION_APP_SWITCH
+ || mLongPressOnMenuBehavior == KEY_ACTION_APP_SWITCH) {
+ preloadRecentApps();
+ }
+ if (repeatCount == 0) {
+ mMenuPressed = true;
+ if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
+ Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
+ null, null, null, 0, null, null);
+ return -1;
+ } else if (SHOW_PROCESSES_ON_ALT_MENU &&
+ (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
+ Intent service = new Intent();
+ service.setClassName(mContext, "com.android.server.LoadAverageService");
+ ContentResolver res = mContext.getContentResolver();
+ boolean shown = Settings.Global.getInt(
+ res, Settings.Global.SHOW_PROCESSES, 0) != 0;
+ if (!shown) {
+ mContext.startService(service);
+ } else {
+ mContext.stopService(service);
+ }
+ Settings.Global.putInt(
+ res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
+ return -1;
+ }
+ } else if (longPress) {
+ if (!keyguardOn && mLongPressOnMenuBehavior != KEY_ACTION_NOTHING) {
+ if (mLongPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ performKeyAction(mLongPressOnMenuBehavior, event);
+ mMenuPressed = false;
+ return -1;
}
- Settings.Global.putInt(
- res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
- return -1;
}
}
+ if (!down && mMenuPressed) {
+ if (mPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ mMenuPressed = false;
+ if (!canceled) {
+ performKeyAction(mPressOnMenuBehavior, event);
+ }
+ }
+ return -1;
} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
if (down) {
if (repeatCount == 0) {
@@ -2816,10 +3291,34 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (!keyguardOn) {
- if (down && repeatCount == 0) {
- preloadRecentApps();
- } else if (!down) {
- toggleRecentApps();
+ if (down) {
+ if (mPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH
+ || mLongPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH) {
+ preloadRecentApps();
+ }
+ if (repeatCount == 0) {
+ mAppSwitchLongPressed = false;
+ } else if (longPress) {
+ if (mLongPressOnAppSwitchBehavior != KEY_ACTION_NOTHING) {
+ if (mLongPressOnAppSwitchBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ performKeyAction(mLongPressOnAppSwitchBehavior, event);
+ mAppSwitchLongPressed = true;
+ }
+ }
+ } else {
+ if (mAppSwitchLongPressed) {
+ mAppSwitchLongPressed = false;
+ } else {
+ if (mPressOnAppSwitchBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ if (!canceled) {
+ performKeyAction(mPressOnAppSwitchBehavior, event);
+ }
+ }
}
}
return -1;
@@ -2836,20 +3335,31 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
if (down) {
+ if (mPressOnAssistBehavior == KEY_ACTION_APP_SWITCH
+ || mLongPressOnAssistBehavior == KEY_ACTION_APP_SWITCH) {
+ preloadRecentApps();
+ }
if (repeatCount == 0) {
mAssistKeyLongPressed = false;
- } else if (repeatCount == 1) {
- mAssistKeyLongPressed = true;
- if (!keyguardOn) {
- launchAssistLongPressAction();
+ } else if (longPress) {
+ if (!keyguardOn && mLongPressOnAssistBehavior != KEY_ACTION_NOTHING) {
+ if (mLongPressOnAssistBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ performKeyAction(mLongPressOnAssistBehavior, event);
+ mAssistKeyLongPressed = true;
}
}
} else {
if (mAssistKeyLongPressed) {
mAssistKeyLongPressed = false;
} else {
- if (!keyguardOn) {
- launchAssistAction(null, event.getDeviceId());
+ if (mPressOnAssistBehavior != KEY_ACTION_APP_SWITCH) {
+ cancelPreloadRecentApps();
+ }
+ if (!canceled) {
+ performKeyAction(mPressOnAssistBehavior, event);
}
}
}
@@ -2922,6 +3432,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
}
return -1;
+ } else if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (unpinActivity(true) || CMSettings.Secure.getInt(mContext.getContentResolver(),
+ CMSettings.Secure.KILL_APP_LONGPRESS_BACK, 0) == 1) {
+ if (down && repeatCount == 0) {
+ mHandler.postDelayed(mBackLongPress, mBackKillTimeout);
+ }
+ }
}
// Shortcuts are invoked through Search+key, so intercept those here
@@ -3030,6 +3547,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return -1;
}
+ // Specific device key handling
+ if (mDeviceKeyHandler != null) {
+ try {
+ // The device only should consume known keys.
+ if (mDeviceKeyHandler.handleKeyEvent(event)) {
+ return -1;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not dispatch event to device key handler", e);
+ }
+ }
+
// Reserve all the META modifier combos for system behavior
if ((metaState & KeyEvent.META_META_ON) != 0) {
return -1;
@@ -3039,6 +3568,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
+ private boolean unpinActivity(boolean checkOnly) {
+ if (!hasNavigationBar()) {
+ try {
+ if (ActivityManagerNative.getDefault().isInLockTaskMode()) {
+ if (!checkOnly) {
+ ActivityManagerNative.getDefault().stopLockTaskModeOnCurrent();
+ }
+ return true;
+ }
+ } catch (RemoteException e) {
+ // ignore
+ }
+ }
+ return false;
+ }
+
/** {@inheritDoc} */
@Override
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
@@ -3315,8 +3860,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
hideRecentApps(false, true);
- } else {
- // Otherwise, just launch Home
+ } else if (mScreenOnFully) {
+ // check if screen is fully on before going home
+ // to avoid hardware home button wake going home
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
}
@@ -3416,8 +3962,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void getInsetHintLw(WindowManager.LayoutParams attrs, int displayRotation,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets) {
- final int fl = PolicyControl.getWindowFlags(null, attrs);
- final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(null, attrs);
+ final int sysuiVis = WindowManagerPolicyControl.getSystemUiVisibility(null, attrs);
final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
@@ -3536,13 +4082,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
- = mCurLeft = mUnrestrictedScreenLeft;
+ = mCurLeft = mForceImmersiveLeft = mUnrestrictedScreenLeft;
mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
- = mCurTop = mUnrestrictedScreenTop;
+ = mCurTop = mForceImmersiveTop = mUnrestrictedScreenTop;
mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
- = mCurRight = displayWidth - overscanRight;
+ = mCurRight = mForceImmersiveRight = displayWidth - overscanRight;
mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
- = mCurBottom = displayHeight - overscanBottom;
+ = mCurBottom = mForceImmersiveBottom = displayHeight - overscanBottom;
mDockLayer = 0x10000000;
mStatusBarLayer = -1;
@@ -3627,6 +4173,34 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// we can tell the app that it is covered by it.
mSystemBottom = mTmpNavigationFrame.top;
}
+ } else if (mNavigationBarLeftInLandscape) {
+ // Landscape screen; nav bar goes to the left.
+ int right = overscanLeft + mNavigationBarWidthForRotation[displayRotation];
+ mTmpNavigationFrame.set(0, 0, right, displayHeight);
+ mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
+ mStableFullscreenLeft = mTmpNavigationFrame.right;
+ if (transientNavBarShowing) {
+ mNavigationBarController.setBarShowingLw(true);
+ } else if (navVisible) {
+ mNavigationBarController.setBarShowingLw(true);
+ mDockLeft = mTmpNavigationFrame.right;
+ mRestrictedScreenLeft = mDockLeft;
+ mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
+ mRestrictedOverscanScreenLeft = mRestrictedScreenLeft;
+ mRestrictedOverscanScreenWidth = mDockRight
+ - mRestrictedOverscanScreenLeft;
+ } else {
+ // We currently want to hide the navigation UI.
+ mNavigationBarController.setBarShowingLw(false);
+ }
+
+ if (navVisible && !navTranslucent && !mNavigationBar.isAnimatingLw()
+ && !mNavigationBarController.wasRecentlyTranslucent()) {
+ // If the nav bar is currently requested to be visible,
+ // and not in the process of animating on or off, then
+ // we can tell the app that it is covered by it.
+ mSystemLeft = mTmpNavigationFrame.right;
+ }
} else {
// Landscape screen; nav bar goes to the right.
int left = displayWidth - overscanRight
@@ -3818,7 +4392,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
? attached.getFrameLw() : df);
}
- private void applyStableConstraints(int sysui, int fl, Rect r) {
+ private void applyForceImmersiveMode(int pfl, Rect r) {
+ if ((pfl & PRIVATE_FLAG_STATUS_HIDE_FORCED) != 0) {
+ r.top = mForceImmersiveTop;
+ }
+ if ((pfl & PRIVATE_FLAG_NAV_HIDE_FORCED) != 0) {
+ if (mNavigationBarOnBottom) {
+ r.bottom = mForceImmersiveBottom;
+ } else {
+ r.right = mForceImmersiveRight;
+ }
+ }
+ }
+
+ private void applyStableConstraints(int sysui, int fl, Rect r, Rect d) {
+ if (mNavigationBarLeftInLandscape) {
+ d.left = r.left;
+ r.left = 0;
+ }
+
if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
// If app is requesting a stable layout, don't let the
// content insets go below the stable values.
@@ -3862,9 +4454,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
offsetInputMethodWindowLw(mLastInputMethodWindow);
}
- final int fl = PolicyControl.getWindowFlags(win, attrs);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(win, attrs);
+ final int pfl = WindowManagerPolicyControl.getPrivateWindowFlags(win, attrs);
final int sim = attrs.softInputMode;
- final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
+ final int sysUiFl = WindowManagerPolicyControl.getSystemUiVisibility(win, null);
final Rect pf = mTmpParentFrame;
final Rect df = mTmpDisplayFrame;
@@ -4045,7 +4638,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
}
- if ((fl & FLAG_FULLSCREEN) == 0) {
+ if ((fl & FLAG_FULLSCREEN) == 0
+ || (pfl & PRIVATE_FLAG_WAS_NOT_FULLSCREEN) != 0) {
if (win.isVoiceInteraction()) {
cf.left = mVoiceContentLeft;
cf.top = mVoiceContentTop;
@@ -4063,6 +4657,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
cf.right = mContentRight;
cf.bottom = mContentBottom;
}
+
+ applyForceImmersiveMode(pfl, cf);
}
} else {
// Full screen windows are always given a layout that is as if the
@@ -4074,7 +4670,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
}
- applyStableConstraints(sysUiFl, fl, cf);
+ applyStableConstraints(sysUiFl, fl, cf, df);
if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
vf.left = mCurLeft;
vf.top = mCurTop;
@@ -4083,6 +4679,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
vf.set(cf);
}
+
+ applyForceImmersiveMode(pfl, vf);
}
} else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
& (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@@ -4093,7 +4691,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// gets everything, period.
if (attrs.type == TYPE_STATUS_BAR_PANEL
|| attrs.type == TYPE_STATUS_BAR_SUB_PANEL
- || attrs.type == TYPE_VOLUME_OVERLAY) {
+ || attrs.type == TYPE_VOLUME_OVERLAY
+ || attrs.type == TYPE_KEYGUARD_PANEL) {
pf.left = df.left = of.left = cf.left = hasNavBar
? mDockLeft : mUnrestrictedScreenLeft;
pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
@@ -4187,7 +4786,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ mRestrictedScreenHeight;
}
- applyStableConstraints(sysUiFl, fl, cf);
+ applyStableConstraints(sysUiFl, fl, cf, df);
if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
vf.left = mCurLeft;
@@ -4197,6 +4796,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
vf.set(cf);
}
+
+ applyForceImmersiveMode(pfl, vf);
} else if (attached != null) {
if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
"): attached to " + attached);
@@ -4254,6 +4855,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
vf.set(cf);
}
+
+ applyForceImmersiveMode(pfl, vf);
}
}
}
@@ -4325,6 +4928,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mContentBottom > top) {
mContentBottom = top;
}
+ if (mForceImmersiveBottom > top) {
+ mForceImmersiveBottom = top;
+ }
if (mVoiceContentBottom > top) {
mVoiceContentBottom = top;
}
@@ -4382,7 +4988,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState attached) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
- final int fl = PolicyControl.getWindowFlags(win, attrs);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(win, attrs);
if (mTopFullscreenOpaqueWindowState == null
&& win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
mForcingShowNavBar = true;
@@ -4567,7 +5173,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mLastSystemUiFlags, mLastSystemUiFlags);
}
} else if (mTopFullscreenOpaqueWindowState != null) {
- final int fl = PolicyControl.getWindowFlags(null, lp);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(null, lp);
if (localLOGV) {
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
+ " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
@@ -4682,22 +5288,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
*/
private boolean setKeyguardOccludedLw(boolean isOccluded) {
boolean wasOccluded = mKeyguardOccluded;
- boolean showing = mKeyguardDelegate.isShowing();
- if (wasOccluded && !isOccluded && showing) {
+ if (wasOccluded && !isOccluded) {
mKeyguardOccluded = false;
mKeyguardDelegate.setOccluded(false);
- mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
- mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
- return true;
- } else if (!wasOccluded && isOccluded && showing) {
+ if (mKeyguardDelegate.isShowing()) {
+ mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+ mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ return true;
+ }
+ } else if (!wasOccluded && isOccluded) {
mKeyguardOccluded = true;
mKeyguardDelegate.setOccluded(true);
- mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
- mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
- return true;
- } else {
- return false;
+ if (mKeyguardDelegate.isShowing()) {
+ mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+ mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+ return true;
+ }
}
+ return false;
}
private boolean isStatusBarKeyguard() {
@@ -4814,6 +5422,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
setHdmiPlugged(!mHdmiPlugged);
}
+ /**
+ * @return Whether music is being played right now "locally" (e.g. on the device's speakers
+ * or wired headphones) or "remotely" (e.g. on a device using the Cast protocol and
+ * controlled by this device, or through remote submix).
+ */
+ private boolean isMusicActive() {
+ final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
+ if (am == null) {
+ Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
+ return false;
+ }
+ return am.isMusicActive();
+ }
+
final Object mScreenshotLock = new Object();
ServiceConnection mScreenshotConnection = null;
@@ -4895,6 +5517,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
+ final int scanCode = event.getScanCode();
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
@@ -4926,8 +5549,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
- // interactive.
+ // interactive, unless the user has explicitly disabled this wake key.
result = ACTION_PASS_TO_USER;
+ isWakeKey = isWakeKey && isWakeKeyEnabled(keyCode);
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
@@ -4942,7 +5566,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) {
- wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey,
+ "android.policy:KEY", true);
}
return result;
}
@@ -4951,6 +5576,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
&& (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
&& event.getRepeatCount() == 0;
+ // Specific device key handling
+ if (mDeviceKeyHandler != null) {
+ try {
+ // The device only should consume known keys.
+ if (mDeviceKeyHandler.handleKeyEvent(event)) {
+ return 0;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not dispatch event to device key handler", e);
+ }
+ }
+
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
@@ -4960,6 +5597,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// On TVs volume keys never go to the foreground app
result &= ~ACTION_PASS_TO_USER;
}
+ // Eat all down & up keys when using volume wake.
+ // This disables volume control, music control, and "beep" on key up.
+ if (isWakeKey && mVolumeWakeScreen) {
+ mVolumeWakeTriggered = true;
+ break;
+ } else if (mVolumeWakeTriggered && !down) {
+ result &= ~ACTION_PASS_TO_USER;
+ mVolumeWakeTriggered = false;
+ break;
+ }
+
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (interactive && !mScreenshotChordVolumeDownKeyTriggered
@@ -5019,23 +5667,101 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
}
}
+ }
+
+ // Disable music and volume control when used as wake key
+ if ((result & ACTION_PASS_TO_USER) == 0 && !mVolumeWakeScreen) {
+ boolean mayChangeVolume = false;
+
+ if (isMusicActive()) {
+ if (mVolBtnMusicControls && (keyCode != KeyEvent.KEYCODE_VOLUME_MUTE)) {
+ // Detect long key presses.
+ if (down) {
+ mIsLongPress = false;
+ // TODO: Long press of MUTE could be mapped to KEYCODE_MEDIA_PLAY_PAUSE
+ int newKeyCode = event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP ?
+ KeyEvent.KEYCODE_MEDIA_NEXT : KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+ scheduleLongPressKeyEvent(event, newKeyCode);
+ // Consume key down events of all presses.
+ break;
+ } else {
+ mHandler.removeMessages(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK);
+ // Consume key up events of long presses only.
+ if (mIsLongPress) {
+ break;
+ }
+ // Change volume only on key up events of short presses.
+ mayChangeVolume = true;
+ }
+ } else {
+ // Long key press detection not applicable, change volume only
+ // on key down events
+ mayChangeVolume = down;
+ }
+ }
- if ((result & ACTION_PASS_TO_USER) == 0) {
+ if (mayChangeVolume) {
if (mUseTvRouting) {
dispatchDirectAudioEvent(event);
} else {
// If we aren't passing to the user and no one else
- // handled it send it to the session manager to
- // figure out.
+ // handled it send it to the session manager to figure
+ // out.
+
+ // Rewrite the event to use key-down as sendVolumeKeyEvent will
+ // only change the volume on key down.
+ KeyEvent newEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
MediaSessionLegacyHelper.getHelper(mContext)
- .sendVolumeKeyEvent(event, true);
+ .sendVolumeKeyEvent(newEvent, true);
}
- break;
}
+ break;
}
break;
}
+ case KeyEvent.KEYCODE_HOME:
+ if (down && !interactive && mHomeWakeScreen) {
+ isWakeKey = true;
+ }
+ break;
+
+ case KeyEvent.KEYCODE_FOCUS:
+ if (down && !interactive && mCameraSleepOnRelease) {
+ mIsFocusPressed = true;
+ } else if ((event.getAction() == KeyEvent.ACTION_UP)
+ && mScreenOnFully && mIsFocusPressed) {
+ // Check if screen is fully on before letting the device go to sleep
+ mPowerManager.goToSleep(SystemClock.uptimeMillis());
+ mIsFocusPressed = false;
+ }
+ break;
+
+ case KeyEvent.KEYCODE_CAMERA:
+ if (down && mIsFocusPressed) {
+ mIsFocusPressed = false;
+ }
+ if (down) {
+ mIsLongPress = false;
+ scheduleLongPressKeyEvent(event, KeyEvent.KEYCODE_CAMERA);
+ // Consume key down events of all presses.
+ break;
+ } else {
+ mHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
+ // Consume key up events of long presses only.
+ if (mIsLongPress && mCameraLaunch) {
+ Intent intent;
+ if (keyguardActive) {
+ intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+ } else {
+ intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ }
+ isWakeKey = true;
+ startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ }
+ }
+ break;
+
case KeyEvent.KEYCODE_ENDCALL: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
@@ -5074,6 +5800,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_POWER: {
+ if (mTopFullscreenOpaqueWindowState != null &&
+ (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags
+ & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0
+ && mScreenOnFully) {
+ return result;
+ }
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
@@ -5182,12 +5914,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (isWakeKey) {
- wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY", true);
}
return result;
}
+ private void scheduleLongPressKeyEvent(KeyEvent origEvent, int keyCode) {
+ KeyEvent event = new KeyEvent(origEvent.getDownTime(), origEvent.getEventTime(),
+ origEvent.getAction(), keyCode, 0);
+ Message msg;
+ if (keyCode == KeyEvent.KEYCODE_CAMERA) {
+ msg = mHandler.obtainMessage(MSG_CAMERA_LONG_PRESS, event);
+ } else {
+ msg = mHandler.obtainMessage(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK, event);
+ }
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, ViewConfiguration.getLongPressTimeout());
+ }
+
/**
* Returns true if the key can have global actions attached to it.
* We reserve all power management keys for the system since they require
@@ -5205,6 +5950,34 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/**
+ * Check if the given keyCode represents a key that is considered a wake key
+ * and is currently enabled by the user in Settings or for another reason.
+ */
+ private boolean isWakeKeyEnabled(int keyCode) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ // Volume keys are still wake keys if the device is docked.
+ return mVolumeWakeScreen || mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ case KeyEvent.KEYCODE_BACK:
+ return mBackWakeScreen;
+ case KeyEvent.KEYCODE_MENU:
+ return mMenuWakeScreen;
+ case KeyEvent.KEYCODE_ASSIST:
+ return mAssistWakeScreen;
+ case KeyEvent.KEYCODE_APP_SWITCH:
+ return mAppSwitchWakeScreen;
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_FOCUS:
+ return mCameraWakeScreen;
+ case KeyEvent.KEYCODE_HOME:
+ return mHomeWakeScreen;
+ }
+ return true;
+ }
+
+ /**
* When the screen is off we ignore some keys that might otherwise typically
* be considered wake keys. We filter them out here.
*
@@ -5217,9 +5990,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_MUTE:
- return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ return mVolumeWakeScreen || mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
- // ignore media and camera keys
+ // ignore media keys
case KeyEvent.KEYCODE_MUTE:
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY:
@@ -5232,8 +6005,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_MEDIA_RECORD:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
- case KeyEvent.KEYCODE_CAMERA:
return false;
+
+ case KeyEvent.KEYCODE_BACK:
+ return mBackWakeScreen;
+ case KeyEvent.KEYCODE_MENU:
+ return mMenuWakeScreen;
+ case KeyEvent.KEYCODE_ASSIST:
+ return mAssistWakeScreen;
+ case KeyEvent.KEYCODE_APP_SWITCH:
+ return mAppSwitchWakeScreen;
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_FOCUS:
+ return mCameraWakeScreen;
+ case KeyEvent.KEYCODE_HOME:
+ return mHomeWakeScreen;
}
return true;
}
@@ -5276,7 +6062,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
IDreamManager dreamManager = getDreamManager();
try {
- if (dreamManager != null && dreamManager.isDreaming()) {
+ if (dreamManager != null && dreamManager.isDreaming() && !dreamManager.isDozing()) {
return true;
}
} catch (RemoteException e) {
@@ -5438,6 +6224,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// current user.
mSettingsObserver.onChange(false);
+ if (mGlobalActions != null) {
+ mGlobalActions.updatePowerMenuActions();
+ }
+
// force a re-application of focused window sysui visibility.
// the window may never have been shown for this user
// e.g. the keyguard when going through the new-user setup flow
@@ -5485,6 +6275,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+
+ BroadcastReceiver mWifiDisplayReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(ACTION_WIFI_DISPLAY_VIDEO)) {
+ int state = intent.getIntExtra("state", 0);
+ if(state == 1) {
+ mWifiDisplayConnected = true;
+ } else {
+ mWifiDisplayConnected = false;
+ }
+ mWifiDisplayCustomRotation =
+ intent.getIntExtra("wfd_UIBC_rot", -1);
+ updateRotation(true);
+ }
+ }
+ };
+
// Called on the PowerManager's Notifier thread.
@Override
public void startedGoingToSleep(int why) {
@@ -5544,10 +6352,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void wakeUpFromPowerKey(long eventTime) {
- wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
+ wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER", true);
}
private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
+ return wakeUp(wakeTime, wakeInTheaterMode, reason, false);
+ }
+
+ private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason,
+ boolean withProximityCheck) {
final boolean theaterModeEnabled = isTheaterModeEnabled();
if (!wakeInTheaterMode && theaterModeEnabled) {
return false;
@@ -5558,7 +6371,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Global.THEATER_MODE_ON, 0);
}
- mPowerManager.wakeUp(wakeTime, reason);
+ if (withProximityCheck) {
+ mPowerManager.wakeUpWithProximityCheck(wakeTime, reason);
+ } else {
+ mPowerManager.wakeUp(wakeTime, reason);
+ }
return true;
}
@@ -5679,10 +6496,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (!mKeyguardDrawnOnce && mAwake) {
mKeyguardDrawnOnce = true;
enableScreen = true;
- if (mBootMessageNeedsHiding) {
- mBootMessageNeedsHiding = false;
- hideBootMessages();
- }
} else {
enableScreen = false;
}
@@ -5702,9 +6515,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void handleHideBootMessage() {
synchronized (mLock) {
- if (!mKeyguardDrawnOnce) {
- mBootMessageNeedsHiding = true;
- return; // keyguard hasn't drawn the first time yet, not done booting
+ if (!mKeyguardDrawComplete) {
+ return; // keyguard hasn't completed drawing, not done booting.
}
}
@@ -5837,8 +6649,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
final int preferredRotation;
- if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
- // Ignore sensor when lid switch is open and rotation is forced.
+ if ((mLidState == LID_OPEN && mLidOpenRotation >= 0)
+ && !(mHasRemovableLid
+ && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED)) {
+ // Ignore sensor when lid switch is open and rotation is forced
+ // and a removable lid was not undocked.
preferredRotation = mLidOpenRotation;
} else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
&& (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
@@ -5856,10 +6671,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// enable 180 degree rotation while docked.
preferredRotation = mDeskDockEnablesAccelerometer
? sensorRotation : mDeskDockRotation;
- } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
+ } else if ((mHdmiPlugged || mWifiDisplayConnected) && mDemoHdmiRotationLock) {
// Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
// Note that the dock orientation overrides the HDMI orientation.
preferredRotation = mDemoHdmiRotation;
+ } else if (mWifiDisplayConnected && (mWifiDisplayCustomRotation > -1)) {
+ // Ignore sensor when WFD is active and UIBC rotation is enabled
+ preferredRotation = mWifiDisplayCustomRotation;
} else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
&& mUndockedHdmiRotation >= 0) {
// Ignore sensor when plugged into HDMI and an undocked orientation has
@@ -5897,10 +6715,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAllowAllRotations = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
}
- if (sensorRotation != Surface.ROTATION_180
- || mAllowAllRotations == 1
- || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
- || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
+
+ // use sensor orientation if it's forced, or if the user has allowed it
+ boolean useSensorRotation =
+ orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER
+ || RotationPolicy.isRotationAllowed(sensorRotation, mUserRotationAngles,
+ mAllowAllRotations != 0);
+ if (useSensorRotation) {
preferredRotation = sensorRotation;
} else {
preferredRotation = lastRotation;
@@ -6303,14 +7125,37 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void applyLidSwitchState() {
- if (mLidState == LID_CLOSED && mLidControlsSleep) {
- mPowerManager.goToSleep(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- }
+ mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
+ if (mLidControlsSleep) {
+ IDreamManager dreamManager = getDreamManager();
+ if (dreamManager != null) {
+ try {
+ dreamManager.setLidState(mLidState);
+ } catch (RemoteException e) {
+ }
+ }
- synchronized (mLock) {
- updateWakeGestureListenerLp();
+ if (mLidState == LID_CLOSED) {
+ if (mFocusedWindow != null && (mFocusedWindow.getAttrs().flags
+ & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
+ // if an application requests that the screen be turned on
+ // and there's a closed device cover, don't turn the screen off!
+ return;
+ }
+
+ TelecomManager telephonyService = getTelecommService();
+ if (!(telephonyService == null
+ || telephonyService.isRinging())) {
+ mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ }
+
+ }
+
+ synchronized (mLock) {
+ updateWakeGestureListenerLp();
+ }
}
}
@@ -6385,7 +7230,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
ActivityInfo ai = null;
ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
intent,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
+ PackageManager.MATCH_DEFAULT_ONLY
+ | PackageManager.GET_META_DATA
+ | PackageManager.GET_RESOLVED_FILTER,
mCurrentUserId);
if (info != null) {
ai = info.activityInfo;
@@ -6608,13 +7455,38 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
- int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
+ int tmpVisibility = WindowManagerPolicyControl.getSystemUiVisibility(win, null)
& ~mResettingSystemUiFlags
& ~mForceClearedSystemUiFlags;
+ boolean wasCleared = mClearedBecauseOfForceShow;
if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
- tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
+ tmpVisibility &=
+ ~WindowManagerPolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
+ mClearedBecauseOfForceShow = true;
+ } else {
+ mClearedBecauseOfForceShow = false;
}
- tmpVisibility = updateLightStatusBarLw(tmpVisibility);
+
+ // The window who requested navbar force showing disappeared and next window wants
+ // to hide navbar. Instead of hiding we will make it transient. SystemUI will take care
+ // about hiding after timeout. This should not happen if next window is keyguard because
+ // transient state have more priority than translucent (why?) and cause bad UX
+ if (wasCleared && !mClearedBecauseOfForceShow
+ && (tmpVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
+ mNavigationBarController.showTransient();
+ tmpVisibility |= View.NAVIGATION_BAR_TRANSIENT;
+ mWindowManagerFuncs.addSystemUIVisibilityFlag(View.NAVIGATION_BAR_TRANSIENT);
+ }
+
+ boolean topWindowWasKeyguard = mTopWindowIsKeyguard;
+ mTopWindowIsKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
+ if (topWindowWasKeyguard && !mTopWindowIsKeyguard
+ && (tmpVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
+ mStatusBarController.showTransient();
+ tmpVisibility |= View.STATUS_BAR_TRANSIENT;
+ mWindowManagerFuncs.addSystemUIVisibilityFlag(View.STATUS_BAR_TRANSIENT);
+ }
+
final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int diff = visibility ^ mLastSystemUiFlags;
final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
@@ -6653,7 +7525,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If the top fullscreen-or-dimming window is also the top fullscreen, respect
// its light flag.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
+ vis |= WindowManagerPolicyControl.getSystemUiVisibility(statusColorWin, null)
& View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else if (statusColorWin != null && statusColorWin.isDimming()) {
// Otherwise if it's dimming, clear the light flag.
@@ -6696,7 +7568,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
(vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
boolean hideStatusBarWM =
mTopFullscreenOpaqueWindowState != null &&
- (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
+ (WindowManagerPolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
& WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
boolean hideStatusBarSysui =
(vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
@@ -6792,6 +7664,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// overridden by qemu.hw.mainkeys in the emulator.
@Override
public boolean hasNavigationBar() {
+ return mHasNavigationBar || mDevForceNavbar;
+ }
+
+ @Override
+ public boolean hasPermanentMenuKey() {
+ return !hasNavigationBar() && mHasPermanentMenuKey;
+ }
+
+ public boolean needsNavigationBar() {
return mHasNavigationBar;
}
@@ -6889,6 +7770,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix);
pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+ pw.print(" mRingHomeBehavior="); pw.print(mRingHomeBehavior);
pw.print(prefix);
pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
@@ -7025,7 +7907,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mGlobalKeyManager.dump(prefix, pw);
mStatusBarController.dump(pw, prefix);
mNavigationBarController.dump(pw, prefix);
- PolicyControl.dump(prefix, pw);
+ WindowManagerPolicyControl.dump(prefix, pw);
if (mWakeGestureListener != null) {
mWakeGestureListener.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/policy/PolicyControl.java b/services/core/java/com/android/server/policy/PolicyControl.java
index dbafc42..0f6fc58 100644
--- a/services/core/java/com/android/server/policy/PolicyControl.java
+++ b/services/core/java/com/android/server/policy/PolicyControl.java
@@ -125,6 +125,10 @@ public class PolicyControl {
}
}
+ public static boolean isImmersiveFiltersActive() {
+ return sImmersiveStatusFilter != null || sImmersiveNavigationFilter != null;
+ }
+
public static void dump(String prefix, PrintWriter pw) {
dump("sImmersiveStatusFilter", sImmersiveStatusFilter, prefix, pw);
dump("sImmersiveNavigationFilter", sImmersiveNavigationFilter, prefix, pw);
diff --git a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
index e4bd21d..5e694a5 100644
--- a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
@@ -42,6 +42,7 @@ public class SystemGesturesPointerEventListener implements PointerEventListener
private static final int SWIPE_FROM_TOP = 1;
private static final int SWIPE_FROM_BOTTOM = 2;
private static final int SWIPE_FROM_RIGHT = 3;
+ private static final int SWIPE_FROM_LEFT = 4;
private final Context mContext;
private final int mSwipeStartThreshold;
@@ -121,6 +122,9 @@ public class SystemGesturesPointerEventListener implements PointerEventListener
} else if (swipe == SWIPE_FROM_RIGHT) {
if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight");
mCallbacks.onSwipeFromRight();
+ } else if (swipe == SWIPE_FROM_LEFT) {
+ if (DEBUG) Slog.d(TAG, "Firing onSwipeFromLeft");
+ mCallbacks.onSwipeFromLeft();
}
}
break;
@@ -203,6 +207,11 @@ public class SystemGesturesPointerEventListener implements PointerEventListener
&& elapsed < SWIPE_TIMEOUT_MS) {
return SWIPE_FROM_BOTTOM;
}
+ if (fromX <= mSwipeStartThreshold
+ && x > fromX + mSwipeDistanceThreshold
+ && elapsed < SWIPE_TIMEOUT_MS) {
+ return SWIPE_FROM_LEFT;
+ }
if (fromX >= screenWidth - mSwipeStartThreshold
&& x < fromX - mSwipeDistanceThreshold
&& elapsed < SWIPE_TIMEOUT_MS) {
@@ -247,6 +256,7 @@ public class SystemGesturesPointerEventListener implements PointerEventListener
void onFling(int durationMs);
void onDown();
void onUpOrCancel();
+ void onSwipeFromLeft();
void onDebug();
}
}
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 9916223..651ee22 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -55,6 +55,7 @@ public abstract class WindowOrientationListener {
private boolean mEnabled;
private int mRate;
private String mSensorType;
+ private boolean mUseSystemClockforRotationSensor;
private Sensor mSensor;
private OrientationJudge mOrientationJudge;
private int mCurrentRotation = -1;
@@ -90,6 +91,9 @@ public abstract class WindowOrientationListener {
mSensorType = context.getResources().getString(
com.android.internal.R.string.config_orientationSensorType);
+ mUseSystemClockforRotationSensor = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_useSystemClockforRotationSensor);
+
if (!TextUtils.isEmpty(mSensorType)) {
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
final int N = sensors.size();
@@ -598,7 +602,8 @@ public abstract class WindowOrientationListener {
// Reset the orientation listener state if the samples are too far apart in time
// or when we see values of (0, 0, 0) which indicates that we polled the
// accelerometer too soon after turning it on and we don't have any data yet.
- final long now = event.timestamp;
+ final long now = mUseSystemClockforRotationSensor
+ ? SystemClock.elapsedRealtimeNanos() : event.timestamp;
final long then = mLastFilteredTimestampNanos;
final float timeDeltaMS = (now - then) * 0.000001f;
final boolean skipSample;
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 7ae3c79..cb09dd4 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -49,6 +49,10 @@ public class KeyguardServiceDelegate {
private final KeyguardState mKeyguardState = new KeyguardState();
private DrawnListener mDrawnListenerWhenConnect;
+ private static final String ACTION_STATE_CHANGE =
+ "com.android.internal.action.KEYGUARD_SERVICE_STATE_CHANGED";
+ private static final String EXTRA_ACTIVE = "active";
+
private static final class KeyguardState {
KeyguardState() {
// Assume keyguard is showing and secure until we know for sure. This is here in
@@ -79,6 +83,13 @@ public class KeyguardServiceDelegate {
void onDrawn();
}
+ private void sendStateChangeBroadcast(boolean bound) {
+ Intent i = new Intent(ACTION_STATE_CHANGE);
+ i.putExtra(EXTRA_ACTIVE, bound);
+ mScrim.getContext().sendBroadcastAsUser(i, UserHandle.ALL,
+ android.Manifest.permission.CONTROL_KEYGUARD);
+ }
+
// A delegate class to map a particular invocation with a ShowListener object.
private final class KeyguardShowDelegate extends IKeyguardDrawnCallback.Stub {
private DrawnListener mDrawnListener;
@@ -171,6 +182,7 @@ public class KeyguardServiceDelegate {
}
if (mKeyguardState.bootCompleted) {
mKeyguardService.onBootCompleted();
+ sendStateChangeBroadcast(true);
}
if (mKeyguardState.occluded) {
mKeyguardService.setOccluded(mKeyguardState.occluded);
@@ -181,6 +193,7 @@ public class KeyguardServiceDelegate {
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
+ sendStateChangeBroadcast(false);
}
};
@@ -364,7 +377,7 @@ public class KeyguardServiceDelegate {
public void showScrim() {
synchronized (mKeyguardState) {
- if (!mKeyguardState.deviceHasKeyguard) return;
+ if (!mKeyguardState.deviceHasKeyguard || !mScrim.isAttachedToWindow()) return;
mScrimHandler.post(new Runnable() {
@Override
public void run() {
@@ -388,6 +401,7 @@ public class KeyguardServiceDelegate {
mKeyguardService.onBootCompleted();
}
mKeyguardState.bootCompleted = true;
+ sendStateChangeBroadcast(true);
}
public void onActivityDrawn() {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 7108f4a..e0bb48f 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -29,10 +29,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.input.InputManagerInternal;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
import android.os.BatteryStats;
import android.os.Handler;
import android.os.Looper;
@@ -78,8 +74,7 @@ final class Notifier {
private static final int MSG_USER_ACTIVITY = 1;
private static final int MSG_BROADCAST = 2;
- private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
- private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
+ private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 3;
private final Object mLock = new Object();
@@ -502,11 +497,6 @@ final class Notifier {
if (DEBUG) {
Slog.d(TAG, "onWirelessChargingStarted");
}
-
- mSuspendBlocker.acquire();
- Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
}
private void updatePendingBroadcastLocked() {
@@ -642,25 +632,6 @@ final class Notifier {
}
};
- private void playWirelessChargingStartedSound() {
- final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
- final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
- if (enabled && soundPath != null) {
- final Uri soundUri = Uri.parse("file://" + soundPath);
- if (soundUri != null) {
- final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
- if (sfx != null) {
- sfx.setStreamType(AudioManager.STREAM_SYSTEM);
- sfx.play();
- }
- }
- }
-
- mSuspendBlocker.release();
- }
-
private final class NotifierHandler extends Handler {
public NotifierHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -676,10 +647,6 @@ final class Notifier {
case MSG_BROADCAST:
sendNextBroadcast();
break;
-
- case MSG_WIRELESS_CHARGING_STARTED:
- playWirelessChargingStartedSound();
- break;
case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
sendBrightnessBoostChangedBroadcast();
break;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 1f45896..70fdfff 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -18,10 +18,12 @@ package com.android.server.power;
import android.app.ActivityManager;
import android.util.SparseIntArray;
+
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.am.BatteryStatsService;
@@ -29,6 +31,8 @@ import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.Watchdog;
+import cyanogenmod.power.PerformanceManagerInternal;
+
import android.Manifest;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
@@ -39,6 +43,9 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManagerInternal;
@@ -63,6 +70,7 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
+import android.telephony.TelephonyManager;
import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
@@ -74,6 +82,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import cyanogenmod.providers.CMSettings;
import libcore.util.Objects;
import static android.os.PowerManagerInternal.POWER_HINT_INTERACTION;
@@ -100,6 +109,8 @@ public final class PowerManagerService extends SystemService
// Message: Sent when the screen brightness boost expires.
private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
+ private static final int MSG_WAKE_UP = 5;
+
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
// Dirty bit: mWakefulness changed
@@ -156,9 +167,18 @@ public final class PowerManagerService extends SystemService
// Power features defined in hardware/libhardware/include/hardware/power.h.
private static final int POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 1;
+ private static final int DEFAULT_BUTTON_ON_DURATION = 5 * 1000;
+
// Default setting for double tap to wake.
private static final int DEFAULT_DOUBLE_TAP_TO_WAKE = 0;
+ private static final int BUTTON_ON_DURATION = 5 * 1000;
+
+ private static final float PROXIMITY_NEAR_THRESHOLD = 5.0f;
+
+ // Max time (microseconds) to allow a CPU boost for
+ private static final int MAX_CPU_BOOST_TIME = 5000000;
+
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
@@ -174,6 +194,16 @@ public final class PowerManagerService extends SystemService
private SettingsObserver mSettingsObserver;
private DreamManagerInternal mDreamManager;
private Light mAttentionLight;
+ private Light mButtonsLight;
+ private Light mKeyboardLight;
+ private Light mCapsLight;
+ private Light mFnLight;
+
+ private int mButtonTimeout;
+ private int mButtonBrightness;
+ private int mButtonBrightnessSettingDefault;
+ private int mKeyboardBrightness;
+ private int mKeyboardBrightnessSettingDefault;
private final Object mLock = new Object();
@@ -351,6 +381,9 @@ public final class PowerManagerService extends SystemService
// Whether device supports double tap to wake.
private boolean mSupportsDoubleTapWakeConfig;
+ // Default value for proximity prevent accidental wakeups
+ private boolean mProximityWakeEnabledByDefaultConfig;
+
// The screen off timeout setting value in milliseconds.
private int mScreenOffTimeoutSetting;
@@ -362,9 +395,12 @@ public final class PowerManagerService extends SystemService
private int mMaximumScreenOffTimeoutFromDeviceAdmin = Integer.MAX_VALUE;
// The stay on while plugged in setting.
- // A bitfield of battery conditions under which to make the screen stay on.
+ // 0: Not enabled; 1: debugging over usb; >2: charging.
private int mStayOnWhilePluggedInSetting;
+ // True if the device should wake up when plugged or unplugged
+ private int mWakeUpWhenPluggedOrUnpluggedSetting;
+
// True if the device should stay on.
private boolean mStayOn;
@@ -393,6 +429,11 @@ public final class PowerManagerService extends SystemService
// Use -1 to disable.
private int mScreenBrightnessOverrideFromWindowManager = -1;
+ // The button brightness setting override from the window manager
+ // to allow the current foreground activity to override the button brightness.
+ // Use -1 to disable.
+ private int mButtonBrightnessOverrideFromWindowManager = -1;
+
// The window manager has determined the user to be inactive via other means.
// Set this to false to disable.
private boolean mUserInactiveOverrideFromWindowManager;
@@ -461,6 +502,9 @@ public final class PowerManagerService extends SystemService
private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
= new ArrayList<PowerManagerInternal.LowPowerModeListener>();
+ //track the blocked uids.
+ private final ArrayList<Integer> mBlockedUids = new ArrayList<Integer>();
+
private native void nativeInit();
private static native void nativeAcquireSuspendBlocker(String name);
@@ -469,6 +513,19 @@ public final class PowerManagerService extends SystemService
private static native void nativeSetAutoSuspend(boolean enable);
private static native void nativeSendPowerHint(int hintId, int data);
private static native void nativeSetFeature(int featureId, int data);
+ private static native int nativeGetFeature(int featureId);
+
+ private boolean mKeyboardVisible = false;
+
+ private SensorManager mSensorManager;
+ private Sensor mProximitySensor;
+ private boolean mProximityWakeEnabled;
+ private int mProximityTimeOut;
+ private boolean mProximityWakeSupported;
+ android.os.PowerManager.WakeLock mProximityWakeLock;
+ SensorEventListener mProximityListener;
+
+ private PerformanceManagerInternal mPerf;
public PowerManagerService(Context context) {
super(context);
@@ -514,6 +571,7 @@ public final class PowerManagerService extends SystemService
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
+ mPerf = LocalServices.getService(PerformanceManagerInternal.class);
}
}
}
@@ -531,6 +589,8 @@ public final class PowerManagerService extends SystemService
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+ mButtonBrightnessSettingDefault = pm.getDefaultButtonBrightness();
+ mKeyboardBrightnessSettingDefault = pm.getDefaultKeyboardBrightness();
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -548,30 +608,40 @@ public final class PowerManagerService extends SystemService
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
+ mButtonsLight = mLightsManager.getLight(LightsManager.LIGHT_ID_BUTTONS);
+ mKeyboardLight = mLightsManager.getLight(LightsManager.LIGHT_ID_KEYBOARD);
+ mCapsLight = mLightsManager.getLight(LightsManager.LIGHT_ID_CAPS);
+ mFnLight = mLightsManager.getLight(LightsManager.LIGHT_ID_FUNC);
// Initialize display power management.
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
- // Register for broadcasts from other components of the system.
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
+ // Initialize proximity sensor
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ }
+
+ // Register for broadcasts from other components of the system.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_DREAMING_STARTED);
- filter.addAction(Intent.ACTION_DREAMING_STOPPED);
- mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_DREAMING_STARTED);
+ filter.addAction(Intent.ACTION_DREAMING_STOPPED);
+ mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_DOCK_EVENT);
- mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_DOCK_EVENT);
+ mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
+ synchronized (mLock) {
// Register for settings changes.
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -613,6 +683,22 @@ public final class PowerManagerService extends SystemService
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.BUTTON_BRIGHTNESS),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.KEYBOARD_BRIGHTNESS),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Secure.getUriFor(
+ CMSettings.Secure.BUTTON_BACKLIGHT_TIMEOUT),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.System.getUriFor(
+ CMSettings.System.PROXIMITY_ON_WAKE),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(CMSettings.Global.getUriFor(
+ CMSettings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+
// Go.
readConfigurationLocked();
updateSettingsLocked();
@@ -660,6 +746,17 @@ public final class PowerManagerService extends SystemService
com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
mSupportsDoubleTapWakeConfig = resources.getBoolean(
com.android.internal.R.bool.config_supportDoubleTapWake);
+ mProximityTimeOut = resources.getInteger(
+ org.cyanogenmod.platform.internal.R.integer.config_proximityCheckTimeout);
+ mProximityWakeSupported = resources.getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_proximityCheckOnWake);
+ mProximityWakeEnabledByDefaultConfig = resources.getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault);
+ if (mProximityWakeSupported) {
+ PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mProximityWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "ProximityWakeLock");
+ }
}
private void updateSettingsLocked() {
@@ -684,9 +781,14 @@ public final class PowerManagerService extends SystemService
Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT,
UserHandle.USER_CURRENT);
mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 1;
+ mWakeUpWhenPluggedOrUnpluggedSetting = CMSettings.Global.getInt(resolver,
+ CMSettings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED,
+ (mWakeUpWhenPluggedOrUnpluggedConfig ? 1 : 0));
+ mProximityWakeEnabled = CMSettings.System.getInt(resolver,
+ CMSettings.System.PROXIMITY_ON_WAKE, mProximityWakeEnabledByDefaultConfig ? 1 : 0) == 1;
if (mSupportsDoubleTapWakeConfig) {
boolean doubleTapWakeEnabled = Settings.Secure.getIntForUser(resolver,
@@ -730,6 +832,17 @@ public final class PowerManagerService extends SystemService
updateLowPowerModeLocked();
}
+ mButtonTimeout = CMSettings.Secure.getIntForUser(resolver,
+ CMSettings.Secure.BUTTON_BACKLIGHT_TIMEOUT,
+ DEFAULT_BUTTON_ON_DURATION, UserHandle.USER_CURRENT);
+
+ mButtonBrightness = CMSettings.Secure.getIntForUser(resolver,
+ CMSettings.Secure.BUTTON_BRIGHTNESS, mButtonBrightnessSettingDefault,
+ UserHandle.USER_CURRENT);
+ mKeyboardBrightness = CMSettings.Secure.getIntForUser(resolver,
+ CMSettings.Secure.KEYBOARD_BRIGHTNESS, mKeyboardBrightnessSettingDefault,
+ UserHandle.USER_CURRENT);
+
mDirty |= DIRTY_SETTINGS;
}
@@ -741,6 +854,7 @@ public final class PowerManagerService extends SystemService
// Turn setting off if powered
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE, 0);
+ // update performance profile
mLowPowerModeSetting = false;
}
final boolean autoLowPowerModeEnabled = !mIsPowered && mAutoLowPowerModeConfigured
@@ -808,6 +922,15 @@ public final class PowerManagerService extends SystemService
}
mWakeLocks.add(wakeLock);
setWakeLockDisabledStateLocked(wakeLock);
+ if(mBlockedUids.contains(new Integer(uid)) && uid != Process.myUid()) {
+ //wakelock acquisition for blocked uid, disable it.
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "uid is blocked disabling wakeLock flags=0x" +
+ Integer.toHexString(flags) + " tag=" + tag + " uid=" + uid +
+ " pid =" + pid);
+ }
+ updateBlockedWakelock(wakeLock, true);
+ }
notifyAcquire = true;
}
@@ -1406,7 +1529,7 @@ public final class PowerManagerService extends SystemService
private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(
boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {
// Don't wake when powered unless configured to do so.
- if (!mWakeUpWhenPluggedOrUnpluggedConfig) {
+ if (mWakeUpWhenPluggedOrUnpluggedSetting == 0) {
return false;
}
@@ -1448,7 +1571,16 @@ public final class PowerManagerService extends SystemService
final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
- mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);
+ switch (mStayOnWhilePluggedInSetting) {
+ case 1: // Debugging only over usb
+ mStayOn = ((mPlugType & BatteryManager.BATTERY_PLUGGED_USB) != 0)
+ && Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ADB_ENABLED, 0) != 0;;
+ break;
+ default: // charging
+ mStayOn = mIsPowered;
+ break;
+ }
} else {
mStayOn = false;
}
@@ -1562,10 +1694,38 @@ public final class PowerManagerService extends SystemService
+ screenOffTimeout - screenDimDuration;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ int buttonBrightness, keyboardBrightness;
+ if (mButtonBrightnessOverrideFromWindowManager >= 0) {
+ buttonBrightness = mButtonBrightnessOverrideFromWindowManager;
+ keyboardBrightness = mButtonBrightnessOverrideFromWindowManager;
+ } else {
+ buttonBrightness = mButtonBrightness;
+ keyboardBrightness = mKeyboardBrightness;
+ }
+
+ mKeyboardLight.setBrightness(mKeyboardVisible ?
+ keyboardBrightness : 0);
+ if (mButtonTimeout != 0
+ && now > mLastUserActivityTime + mButtonTimeout) {
+ mButtonsLight.setBrightness(0);
+ } else {
+ if (!mProximityPositive) {
+ mButtonsLight.setBrightness(buttonBrightness);
+ if (buttonBrightness != 0 && mButtonTimeout != 0) {
+ nextTimeout = now + mButtonTimeout;
+ }
+ }
+ }
+ }
} else {
nextTimeout = mLastUserActivityTime + screenOffTimeout;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mButtonsLight.setBrightness(0);
+ mKeyboardLight.setBrightness(0);
+ }
}
}
}
@@ -1844,7 +2004,7 @@ public final class PowerManagerService extends SystemService
}
// Dream has ended or will be stopped. Update the power state.
- if (isItBedTimeYetLocked()) {
+ if (isItBedTimeYetLocked() && !mDreamsActivatedOnSleepByDefaultConfig) {
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
@@ -2874,6 +3034,10 @@ public final class PowerManagerService extends SystemService
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
break;
+ case MSG_WAKE_UP:
+ cleanupProximity();
+ ((Runnable) msg.obj).run();
+ break;
}
}
}
@@ -3053,6 +3217,22 @@ public final class PowerManagerService extends SystemService
}
}
+ private void cleanupProximity() {
+ synchronized (mProximityWakeLock) {
+ cleanupProximityLocked();
+ }
+ }
+
+ private void cleanupProximityLocked() {
+ if (mProximityWakeLock.isHeld()) {
+ mProximityWakeLock.release();
+ }
+ if (mProximityListener != null) {
+ mSensorManager.unregisterListener(mProximityListener);
+ mProximityListener = null;
+ }
+ }
+
private final class BinderService extends IPowerManager.Stub {
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
@@ -3208,7 +3388,46 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
- public void wakeUp(long eventTime, String reason, String opPackageName) {
+ public void setKeyboardVisibility(boolean visible) {
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "setKeyboardVisibility: " + visible);
+ }
+ if (mKeyboardVisible != visible) {
+ mKeyboardVisible = visible;
+ if (!visible) {
+ // If hiding keyboard, turn off leds
+ setKeyboardLight(false, 1);
+ setKeyboardLight(false, 2);
+ }
+ synchronized (mLock) {
+ mDirty |= DIRTY_USER_ACTIVITY;
+ updatePowerStateLocked();
+ }
+ }
+ }
+ }
+
+ @Override // Binder call
+ public void setKeyboardLight(boolean on, int key) {
+ if (key == 1) {
+ if (on)
+ mCapsLight.setColor(0x00ffffff);
+ else
+ mCapsLight.turnOff();
+ } else if (key == 2) {
+ if (on)
+ mFnLight.setColor(0x00ffffff);
+ else
+ mFnLight.turnOff();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ private void wakeUp(final long eventTime, final String reason, final String opPackageName,
+ boolean checkProximity) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -3217,12 +3436,86 @@ public final class PowerManagerService extends SystemService
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
- final long ident = Binder.clearCallingIdentity();
- try {
- wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ };
+ if (checkProximity) {
+ runWithProximityCheck(r);
+ } else {
+ r.run();
+ }
+ }
+
+ private void runWithProximityCheck(Runnable r) {
+ if (mHandler.hasMessages(MSG_WAKE_UP)) {
+ // There is already a message queued;
+ return;
}
+
+ TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ boolean hasIncomingCall = tm.getCallState() == TelephonyManager.CALL_STATE_RINGING;
+
+ if (mProximityWakeSupported && mProximityWakeEnabled && mProximitySensor != null
+ && !hasIncomingCall) {
+ Message msg = mHandler.obtainMessage(MSG_WAKE_UP);
+ msg.obj = r;
+ mHandler.sendMessageDelayed(msg, mProximityTimeOut);
+ runPostProximityCheck(r);
+ } else {
+ r.run();
+ }
+ }
+
+ private void runPostProximityCheck(final Runnable r) {
+ if (mSensorManager == null) {
+ r.run();
+ return;
+ }
+ synchronized (mProximityWakeLock) {
+ mProximityWakeLock.acquire();
+ mProximityListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ cleanupProximityLocked();
+ if (!mHandler.hasMessages(MSG_WAKE_UP)) {
+ Slog.w(TAG, "The proximity sensor took too long, wake event already triggered!");
+ return;
+ }
+ mHandler.removeMessages(MSG_WAKE_UP);
+ float distance = event.values[0];
+ if (distance >= PROXIMITY_NEAR_THRESHOLD ||
+ distance >= mProximitySensor.getMaximumRange()) {
+ r.run();
+ } else {
+ Slog.w(TAG, "Not waking up. Proximity sensor blocked.");
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+ };
+ mSensorManager.registerListener(mProximityListener,
+ mProximitySensor, SensorManager.SENSOR_DELAY_FASTEST);
+ }
+ }
+
+ @Override // Binder call
+ public void wakeUpWithProximityCheck(long eventTime, String reason, String opPackageName) {
+ wakeUp(eventTime, reason, opPackageName, true);
+ }
+
+ @Override // Binder call
+ public void wakeUp(long eventTime, String reason, String opPackageName) {
+ wakeUp(eventTime, reason, opPackageName, false);
}
@Override // Binder call
@@ -3487,6 +3780,11 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
+ public void cpuBoost(int duration) {
+ mPerf.cpuBoost(duration);
+ }
+
+ @Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -3503,6 +3801,53 @@ public final class PowerManagerService extends SystemService
Binder.restoreCallingIdentity(ident);
}
}
+
+ /* updates the blocked uids, so if a wake lock is acquired for it
+ * can be released.
+ */
+ public void updateBlockedUids(int uid, boolean isBlocked) {
+ boolean changed = false;
+ if (DEBUG_SPEW) Slog.v(TAG, "updateBlockedUids: uid = " + uid +
+ "isBlocked = " + isBlocked);
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (DEBUG_SPEW) Slog.v(TAG, "UpdateBlockedUids is not allowed");
+ return;
+ }
+ synchronized(mLock) {
+ for (int index = 0; index < mWakeLocks.size(); index++) {
+ WakeLock wl = mWakeLocks.get(index);
+ if(wl != null) {
+ // update the wakelock for the blocked uid
+ if ((wl.mOwnerUid == uid || checkWorkSourceObjectId(uid, wl)) ||
+ (wl.mTag.startsWith("*sync*") && wl.mOwnerUid == Process.SYSTEM_UID)) {
+ if(updateBlockedWakelock(wl, isBlocked)){
+ changed = true;
+ }
+ }
+ }
+ }
+ if(isBlocked) {
+ mBlockedUids.add(new Integer(uid));
+ }
+ else {
+ mBlockedUids.clear();
+ }
+ }
+ if(changed){
+ mDirty |= DIRTY_WAKE_LOCKS;
+ updatePowerStateLocked();
+ }
+ }
+ }
+
+ private void setButtonBrightnessOverrideFromWindowManagerInternal(int brightness) {
+ synchronized (mLock) {
+ if (mButtonBrightnessOverrideFromWindowManager != brightness) {
+ mButtonBrightnessOverrideFromWindowManager = brightness;
+ mDirty |= DIRTY_SETTINGS;
+ updatePowerStateLocked();
+ }
+ }
}
private final class LocalService extends PowerManagerInternal {
@@ -3517,8 +3862,15 @@ public final class PowerManagerService extends SystemService
@Override
public void setButtonBrightnessOverrideFromWindowManager(int screenBrightness) {
- // Do nothing.
- // Button lights are not currently supported in the new implementation.
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setButtonBrightnessOverrideFromWindowManagerInternal(screenBrightness);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
}
@Override
@@ -3599,5 +3951,52 @@ public final class PowerManagerService extends SystemService
public void powerHint(int hintId, int data) {
powerHintInternal(hintId, data);
}
+
+ @Override
+ public boolean setPowerSaveMode(boolean mode) {
+ return setLowPowerModeInternal(mode);
+ }
+
+ @Override
+ public int getFeature(int featureId) {
+ return nativeGetFeature(featureId);
+ }
+
+ @Override
+ public void setFeature(int featureId, int data) {
+ nativeSetFeature(featureId, data);
+ }
+ }
+
+ private boolean updateBlockedWakelock(WakeLock wakeLock, boolean update) {
+ if (wakeLock != null && ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+ == PowerManager.PARTIAL_WAKE_LOCK )) {
+ if(wakeLock.mDisabled != update){
+ wakeLock.mDisabled = update;
+ if (wakeLock.mDisabled) {
+ // This wake lock is no longer being respected.
+ notifyWakeLockReleasedLocked(wakeLock);
+ } else {
+ notifyWakeLockAcquiredLocked(wakeLock);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean checkWorkSourceObjectId(int uid, WakeLock wl) {
+ try {
+ for (int index = 0; index < wl.mWorkSource.size(); index++) {
+ if (uid == wl.mWorkSource.get(index)) {
+ if (DEBUG_SPEW) Slog.v(TAG, "WS uid matched");
+ return true;
+ }
+ }
+ }
+ catch (Exception e) {
+ return false;
+ }
+ return false;
}
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index dd8648d..34b6e2b 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +22,7 @@ import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.IActivityManager;
+import android.app.KeyguardManager;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothManager;
@@ -32,7 +34,13 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.os.FileUtils;
import android.os.Handler;
+import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -44,19 +52,32 @@ import android.os.Vibrator;
import android.os.SystemVibrator;
import android.os.storage.IMountService;
import android.os.storage.IMountShutdownObserver;
+import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
+import android.widget.ListView;
import com.android.internal.telephony.ITelephony;
import com.android.server.pm.PackageManagerService;
-
+import com.android.server.power.PowerManagerService;
import android.util.Log;
+import android.view.IWindowManager;
import android.view.WindowManager;
+import java.lang.reflect.Method;
+
+import cyanogenmod.providers.CMSettings;
+import dalvik.system.PathClassLoader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.OutputStreamWriter;
+
+import org.cyanogenmod.internal.util.ThemeUtils;
public final class ShutdownThread extends Thread {
// constants
@@ -74,6 +95,8 @@ public final class ShutdownThread extends Thread {
private static final int RADIO_STOP_PERCENT = 18;
private static final int MOUNT_SERVICE_STOP_PERCENT = 20;
+ private static final String SOFT_REBOOT = "soft_reboot";
+
// length of vibration before shutting down
private static final int SHUTDOWN_VIBRATE_MS = 500;
@@ -85,7 +108,11 @@ public final class ShutdownThread extends Thread {
private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status";
private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
+ // recovery command
+ private static File RECOVERY_COMMAND_FILE = new File("/cache/recovery/command");
+
private static boolean mReboot;
+ private static boolean mRebootWipe = false;
private static boolean mRebootSafeMode;
private static boolean mRebootUpdate;
private static String mRebootReason;
@@ -111,10 +138,20 @@ public final class ShutdownThread extends Thread {
private PowerManager.WakeLock mCpuWakeLock;
private PowerManager.WakeLock mScreenWakeLock;
private Handler mHandler;
+ private static MediaPlayer mMediaPlayer;
+ private static final String OEM_BOOTANIMATION_FILE = "/oem/media/shutdownanimation.zip";
+ private static final String SYSTEM_BOOTANIMATION_FILE = "/system/media/shutdownanimation.zip";
+ private static final String SYSTEM_ENCRYPTED_BOOTANIMATION_FILE = "/system/media/shutdownanimation-encrypted.zip";
+
+ private static final String SHUTDOWN_MUSIC_FILE = "/system/media/shutdown.wav";
+ private static final String OEM_SHUTDOWN_MUSIC_FILE = "/oem/media/shutdown.wav";
+
+ private boolean isShutdownMusicPlaying = false;
private static AlertDialog sConfirmDialog;
private ProgressDialog mProgressDialog;
+ private static AudioManager mAudioManager;
private ShutdownThread() {
}
@@ -127,9 +164,20 @@ public final class ShutdownThread extends Thread {
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void shutdown(final Context context, boolean confirm) {
+ final Context uiContext = getUiContext(context);
mReboot = false;
mRebootSafeMode = false;
- shutdownInner(context, confirm);
+ shutdownInner(uiContext, confirm);
+ }
+
+ private static boolean isAdvancedRebootPossible(final Context context) {
+ KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+ boolean keyguardLocked = km.inKeyguardRestrictedInputMode() && km.isKeyguardSecure();
+ boolean advancedRebootEnabled = CMSettings.Secure.getInt(context.getContentResolver(),
+ CMSettings.Secure.ADVANCED_REBOOT, 0) == 1;
+ boolean isPrimaryUser = UserHandle.getCallingUserId() == UserHandle.USER_OWNER;
+
+ return advancedRebootEnabled && !keyguardLocked && isPrimaryUser;
}
static void shutdownInner(final Context context, boolean confirm) {
@@ -142,33 +190,90 @@ public final class ShutdownThread extends Thread {
}
}
+ boolean showRebootOption = false;
+
+ String[] actionsArray;
+ String actions = CMSettings.Secure.getStringForUser(context.getContentResolver(),
+ CMSettings.Secure.POWER_MENU_ACTIONS, UserHandle.USER_CURRENT);
+ if (actions == null) {
+ actionsArray = context.getResources().getStringArray(
+ com.android.internal.R.array.config_globalActionsList);
+ } else {
+ actionsArray = actions.split("\\|");
+ }
+
+ for (int i = 0; i < actionsArray.length; i++) {
+ if (actionsArray[i].equals("reboot")) {
+ showRebootOption = true;
+ break;
+ }
+ }
final int longPressBehavior = context.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
- final int resourceId = mRebootSafeMode
+ int resourceId = mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_confirm
: (longPressBehavior == 2
? com.android.internal.R.string.shutdown_confirm_question
: com.android.internal.R.string.shutdown_confirm);
+ if (showRebootOption && !mRebootSafeMode) {
+ resourceId = com.android.internal.R.string.reboot_confirm;
+ }
Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
if (confirm) {
final CloseDialogReceiver closer = new CloseDialogReceiver(context);
+ final boolean advancedReboot = isAdvancedRebootPossible(context);
+ final Context uiContext = getUiContext(context);
+
if (sConfirmDialog != null) {
sConfirmDialog.dismiss();
+ sConfirmDialog = null;
}
- sConfirmDialog = new AlertDialog.Builder(context)
+ AlertDialog.Builder confirmDialogBuilder = new AlertDialog.Builder(uiContext)
.setTitle(mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
- : com.android.internal.R.string.power_off)
- .setMessage(resourceId)
- .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
+ : showRebootOption
+ ? com.android.internal.R.string.reboot_title
+ : com.android.internal.R.string.power_off);
+
+ if (!advancedReboot || mRebootSafeMode) {
+ confirmDialogBuilder.setMessage(resourceId);
+ } else {
+ confirmDialogBuilder
+ .setSingleChoiceItems(com.android.internal.R.array.shutdown_reboot_options,
+ 0, null);
+ }
+
+ confirmDialogBuilder.setPositiveButton(com.android.internal.R.string.yes,
+ new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
+ if (!mRebootSafeMode && advancedReboot) {
+ boolean softReboot = false;
+ ListView reasonsList = ((AlertDialog)dialog).getListView();
+ int selected = reasonsList.getCheckedItemPosition();
+ if (selected != ListView.INVALID_POSITION) {
+ String actions[] = context.getResources().getStringArray(
+ com.android.internal.R.array.shutdown_reboot_actions);
+ if (selected >= 0 && selected < actions.length) {
+ mRebootReason = actions[selected];
+ if (actions[selected].equals(SOFT_REBOOT)) {
+ doSoftReboot();
+ return;
+ }
+ }
+ }
+
+ mReboot = true;
+ }
beginShutdownSequence(context);
- }
- })
- .setNegativeButton(com.android.internal.R.string.no, null)
- .create();
+ }
+ });
+
+ confirmDialogBuilder.setNegativeButton(com.android.internal.R.string.no, null);
+ sConfirmDialog = confirmDialogBuilder.create();
+
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
@@ -178,6 +283,18 @@ public final class ShutdownThread extends Thread {
}
}
+ private static void doSoftReboot() {
+ try {
+ final IActivityManager am =
+ ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
+ if (am != null) {
+ am.restart();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "failure trying to perform soft reboot", e);
+ }
+ }
+
private static class CloseDialogReceiver extends BroadcastReceiver
implements DialogInterface.OnDismissListener {
private Context mContext;
@@ -209,13 +326,35 @@ public final class ShutdownThread extends Thread {
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void reboot(final Context context, String reason, boolean confirm) {
+ final Context uiContext = getUiContext(context);
mReboot = true;
mRebootSafeMode = false;
mRebootUpdate = false;
mRebootReason = reason;
- shutdownInner(context, confirm);
+ shutdownInner(uiContext, confirm);
}
+ private static String getShutdownMusicFilePath() {
+ final String[] fileName = {OEM_SHUTDOWN_MUSIC_FILE, SHUTDOWN_MUSIC_FILE};
+ File checkFile = null;
+ for(String music : fileName) {
+ checkFile = new File(music);
+ if (checkFile.exists()) {
+ return music;
+ }
+ }
+ return null;
+ }
+
+ private static void lockDevice() {
+ IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager
+ .getService(Context.WINDOW_SERVICE));
+ try {
+ wm.updateRotation(false, false);
+ } catch (RemoteException e) {
+ Log.w(TAG, "boot animation can not lock device!");
+ }
+ }
/**
* Request a reboot into safe mode. Must be called from a Looper thread in which its UI
* is shown.
@@ -262,6 +401,13 @@ public final class ShutdownThread extends Thread {
// UI: spinning circle only (no progress bar)
if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists();
+ if (RECOVERY_COMMAND_FILE.exists()) {
+ try {
+ mRebootWipe = new String(FileUtils.readTextFile(
+ RECOVERY_COMMAND_FILE, 0, null)).contains("wipe");
+ } catch (IOException e) {
+ }
+ }
if (mRebootUpdate) {
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
pd.setMessage(context.getText(
@@ -271,22 +417,41 @@ public final class ShutdownThread extends Thread {
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setProgress(0);
pd.setIndeterminate(false);
- } else {
+ } else if (mRebootWipe) {
// Factory reset path. Set the dialog message accordingly.
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_reset_message));
pd.setIndeterminate(true);
+ } else {
+ pd.setTitle(context.getText(com.android.internal.R.string.reboot_title));
+ pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress));
+ pd.setIndeterminate(true);
}
} else {
- pd.setTitle(context.getText(com.android.internal.R.string.power_off));
- pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+ if (mReboot) {
+ pd.setTitle(context.getText(com.android.internal.R.string.reboot_title));
+ pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress));
+ } else {
+ pd.setTitle(context.getText(com.android.internal.R.string.power_off));
+ pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+ }
pd.setIndeterminate(true);
}
- pd.setCancelable(false);
- pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- pd.show();
+ //acquire audio focus to make the other apps to stop playing muisc
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager.requestAudioFocus(null,
+ AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
+
+ if (!checkAnimationFileExist()) {
+ // throw up an indeterminate system dialog to indicate radio is
+ // shutting down.
+ pd.setCancelable(false);
+ pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+
+ pd.show();
+ }
sInstance.mProgressDialog = pd;
sInstance.mContext = context;
@@ -417,6 +582,40 @@ public final class ShutdownThread extends Thread {
sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
}
+ String shutDownFile = null;
+
+ //showShutdownAnimation() is called from here to sync
+ //music and animation properly
+ if(checkAnimationFileExist()) {
+ lockDevice();
+ showShutdownAnimation();
+
+ if (!isSilentMode()
+ && (shutDownFile = getShutdownMusicFilePath()) != null) {
+ isShutdownMusicPlaying = true;
+ shutdownMusicHandler.obtainMessage(0, shutDownFile).sendToTarget();
+ }
+ }
+
+ Log.i(TAG, "wait for shutdown music");
+ final long endTimeForMusic = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
+ synchronized (mActionDoneSync) {
+ while (isShutdownMusicPlaying) {
+ long delay = endTimeForMusic - SystemClock.elapsedRealtime();
+ if (delay <= 0) {
+ Log.w(TAG, "play shutdown music timeout!");
+ break;
+ }
+ try {
+ mActionDoneSync.wait(delay);
+ } catch (InterruptedException e) {
+ }
+ }
+ if (!isShutdownMusicPlaying) {
+ Log.i(TAG, "play shutdown music complete.");
+ }
+ }
+
// Shutdown radios.
shutdownRadios(MAX_RADIO_WAIT_TIME);
if (mRebootUpdate) {
@@ -507,11 +706,10 @@ public final class ShutdownThread extends Thread {
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
final IBluetoothManager bluetooth =
IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
- BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
+ BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
try {
- nfcOff = nfc == null ||
- nfc.getState() == NfcAdapter.STATE_OFF;
+ nfcOff = nfc == null || nfc.getState() == NfcAdapter.STATE_OFF;
if (!nfcOff) {
Log.w(TAG, "Turning off NFC...");
nfc.disable(false); // Don't persist new state
@@ -619,6 +817,7 @@ public final class ShutdownThread extends Thread {
* @param reason reason for reboot
*/
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
+ deviceRebootOrShutdown(reboot, reason);
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
PowerManagerService.lowLevelReboot(reason);
@@ -722,4 +921,90 @@ public final class ShutdownThread extends Thread {
Log.w(TAG, "Timed out waiting for uncrypt.");
}
}
+
+ private static void deviceRebootOrShutdown(boolean reboot, String reason) {
+ Class<?> cl;
+ String deviceShutdownClassName = "com.qti.server.power.ShutdownOem";
+ try {
+ cl = Class.forName(deviceShutdownClassName);
+ Method m;
+ try {
+ m = cl.getMethod("rebootOrShutdown", new Class[] {boolean.class, String.class});
+ m.invoke(cl.newInstance(), reboot, reason);
+ } catch (NoSuchMethodException ex) {
+ Log.e(TAG, "rebootOrShutdown method not found in class " + deviceShutdownClassName);
+ } catch (Exception ex) {
+ Log.e(TAG, "Unknown exception hit while trying to invode rebootOrShutdown");
+ }
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Unable to find class " + deviceShutdownClassName);
+ } catch (Exception e) {
+ Log.e(TAG, "Unknown exception while trying to invoke rebootOrShutdown");
+ }
+ }
+
+ private static boolean checkAnimationFileExist() {
+ if (new File(OEM_BOOTANIMATION_FILE).exists()
+ || new File(SYSTEM_BOOTANIMATION_FILE).exists()
+ || new File(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE).exists())
+ return true;
+ else
+ return false;
+ }
+
+ private static boolean isSilentMode() {
+ return mAudioManager.isSilentMode();
+ }
+
+ private static void showShutdownAnimation() {
+ /*
+ * When boot completed, "service.bootanim.exit" property is set to 1.
+ * Bootanimation checks this property to stop showing the boot animation.
+ * Since we use the same code for shutdown animation, we
+ * need to reset this property to 0. If this is not set to 0 then shutdown
+ * will stop and exit after displaying the first frame of the animation
+ */
+ SystemProperties.set("service.bootanim.exit", "0");
+
+ SystemProperties.set("ctl.start", "bootanim");
+ }
+
+ private Handler shutdownMusicHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ String path = (String) msg.obj;
+ mMediaPlayer = new MediaPlayer();
+ try
+ {
+ mMediaPlayer.reset();
+ mMediaPlayer.setDataSource(path);
+ mMediaPlayer.prepare();
+ mMediaPlayer.start();
+ mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ synchronized (mActionDoneSync) {
+ isShutdownMusicPlaying = false;
+ mActionDoneSync.notifyAll();
+ }
+ }
+ });
+ } catch (IOException e) {
+ Log.d(TAG, "play shutdown music error:" + e);
+ }
+ }
+ };
+
+ private static Context getUiContext(Context context) {
+ Context uiContext = null;
+ if (context != null) {
+ uiContext = ThemeUtils.createUiContext(context);
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
+ uiContext.setTheme(com.android.internal.R.style.Theme_Leanback_Dialog_Alert);
+ } else {
+ uiContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
+ }
+ }
+ return uiContext != null ? uiContext : context;
+ }
}
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index a035826..a775c5a 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -146,7 +146,7 @@ final class TvInputHal implements Handler.Callback {
private void firstFrameCapturedFromNative(int deviceId, int streamId) {
mHandler.sendMessage(
- mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, streamId));
+ mHandler.obtainMessage(EVENT_FIRST_FRAME_CAPTURED, deviceId, streamId));
}
// Handler.Callback implementation
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index a71961c..2185b19 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -309,6 +309,13 @@ public final class TwilightService extends SystemService {
}
sendEmptyMessageDelayed(MSG_ENABLE_LOCATION_UPDATES, mLastUpdateInterval);
}
+
+ if (!networkLocationEnabled && mLocation == null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Network location unavailable");
+ }
+ retrieveLocation();
+ }
break;
case MSG_DO_TWILIGHT_UPDATE:
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 7784884..ee926a4 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -106,6 +106,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
static final String WALLPAPER = "wallpaper";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
+ static final String KEYGUARD_WALLPAPER = "keyguard_wallpaper";
+ static final String KEYGUARD_WALLPAPER_INFO = "keyguard_wallpaper_info.xml";
/**
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
@@ -116,17 +118,21 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
private class WallpaperObserver extends FileObserver {
final WallpaperData mWallpaper;
+ final KeyguardWallpaperData mKeyguardWallpaper;
final File mWallpaperDir;
final File mWallpaperFile;
final File mWallpaperInfoFile;
+ final File mKeyguardWallpaperFile;
- public WallpaperObserver(WallpaperData wallpaper) {
+ public WallpaperObserver(WallpaperData wallpaper, KeyguardWallpaperData keyguardWallpaper) {
super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
mWallpaperDir = getWallpaperDir(wallpaper.userId);
mWallpaper = wallpaper;
mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
+ mKeyguardWallpaper = keyguardWallpaper;
+ mKeyguardWallpaperFile = new File(mWallpaperDir, KEYGUARD_WALLPAPER);
}
@Override
@@ -145,6 +151,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
Binder.restoreCallingIdentity(origId);
}
if (mWallpaperFile.equals(changedFile)) {
+ // changing the wallpaper means we'll need to back up the new one
+ long origId = Binder.clearCallingIdentity();
+ BackupManager bm = new BackupManager(mContext);
+ bm.dataChanged();
+ Binder.restoreCallingIdentity(origId);
+
notifyCallbacksLocked(mWallpaper);
final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
if (mWallpaper.wallpaperComponent == null
@@ -157,6 +169,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
false, mWallpaper, null);
saveSettingsLocked(mWallpaper);
}
+ } else if (mKeyguardWallpaperFile.equals(changedFile)) {
+ notifyCallbacksLocked(mKeyguardWallpaper);
+ if (event == CLOSE_WRITE
+ || mKeyguardWallpaper.imageWallpaperPending) {
+ mKeyguardWallpaper.imageWallpaperPending = false;
+ saveSettingsLocked(mKeyguardWallpaper);
+ }
}
}
}
@@ -176,6 +195,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
final ComponentName mImageWallpaper;
SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
+ SparseArray<KeyguardWallpaperData> mKeyguardWallpaperMap
+ = new SparseArray<KeyguardWallpaperData>();
int mCurrentUserId;
@@ -227,6 +248,37 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ static class KeyguardWallpaperData {
+
+ int userId;
+
+ File wallpaperFile;
+
+ /**
+ * Client is currently writing a new image wallpaper.
+ */
+ boolean imageWallpaperPending;
+
+ /**
+ * Resource name if using a picture from the wallpaper gallery
+ */
+ String name = "";
+
+ /**
+ * List of callbacks registered they should each be notified when the wallpaper is changed.
+ */
+ private RemoteCallbackList<IWallpaperManagerCallback> callbacks
+ = new RemoteCallbackList<IWallpaperManagerCallback>();
+
+ int width = -1;
+ int height = -1;
+
+ KeyguardWallpaperData(int userId) {
+ this.userId = userId;
+ wallpaperFile = new File(getWallpaperDir(userId), KEYGUARD_WALLPAPER);
+ }
+ }
+
class WallpaperConnection extends IWallpaperConnection.Stub
implements ServiceConnection {
final WallpaperInfo mInfo;
@@ -486,6 +538,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mMonitor.register(context, null, UserHandle.ALL, true);
getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
loadSettingsLocked(UserHandle.USER_OWNER);
+ loadKeyguardSettingsLocked(UserHandle.USER_OWNER);
}
private static File getWallpaperDir(int userId) {
@@ -504,8 +557,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
public void systemRunning() {
if (DEBUG) Slog.v(TAG, "systemReady");
WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
+ KeyguardWallpaperData keyguardWallpaper = mKeyguardWallpaperMap.get(UserHandle.USER_OWNER);
switchWallpaper(wallpaper, null);
- wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
+ wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper, keyguardWallpaper);
wallpaper.wallpaperObserver.startWatching();
IntentFilter userFilter = new IntentFilter();
@@ -572,6 +626,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
wallpaper.wallpaperObserver = null;
}
mWallpaperMap.remove(userId);
+ mKeyguardWallpaperMap.remove(userId);
}
}
}
@@ -584,6 +639,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
wallpaperFile.delete();
File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
wallpaperInfoFile.delete();
+ File keyguardWallpaperFile = new File(getWallpaperDir(userId), KEYGUARD_WALLPAPER);
+ keyguardWallpaperFile.delete();
+ File keyguardWallpaperInfoFile = new File(getWallpaperDir(userId),
+ KEYGUARD_WALLPAPER_INFO);
+ keyguardWallpaperInfoFile.delete();
}
}
@@ -591,9 +651,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
synchronized (mLock) {
mCurrentUserId = userId;
WallpaperData wallpaper = getWallpaperSafeLocked(userId);
+ KeyguardWallpaperData keyguardWallpaper = getKeyguardWallpaperSafeLocked(userId);
// Not started watching yet, in case wallpaper data was loaded for other reasons.
if (wallpaper.wallpaperObserver == null) {
- wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
+ wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper, keyguardWallpaper);
wallpaper.wallpaperObserver.startWatching();
}
switchWallpaper(wallpaper, reply);
@@ -669,6 +730,40 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ /**
+ * @hide
+ */
+ public void clearKeyguardWallpaper() {
+ if (DEBUG) Slog.v(TAG, "clearWallpaper");
+ synchronized (mLock) {
+ clearKeyguardWallpaperLocked(UserHandle.getCallingUserId(), null);
+ }
+ }
+
+ void clearKeyguardWallpaperLocked(int userId, IRemoteCallback reply) {
+ KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(userId);
+ final long ident = Binder.clearCallingIdentity();
+ wallpaper.imageWallpaperPending = false;
+ wallpaper.height = -1;
+ wallpaper.width = -1;
+ wallpaper.name = "";
+
+ File f = new File(getWallpaperDir(userId), KEYGUARD_WALLPAPER);
+ if (f.exists()) {
+ f.delete();
+ }
+ if (userId != mCurrentUserId)
+ return;
+ Binder.restoreCallingIdentity(ident);
+
+ if (reply != null) {
+ try {
+ reply.sendResult(null);
+ } catch (RemoteException e1) {
+ }
+ }
+ }
+
public boolean hasNamedWallpaper(String name) {
synchronized (mLock) {
List<UserInfo> users;
@@ -837,6 +932,31 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ /** @hide */
+ public ParcelFileDescriptor getKeyguardWallpaper(IWallpaperManagerCallback cb,
+ Bundle outParams) {
+ synchronized (mLock) {
+ int wallpaperUserId = mCurrentUserId;
+ KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(wallpaperUserId);
+ try {
+ if (outParams != null) {
+ outParams.putInt("width", wallpaper.width);
+ outParams.putInt("height", wallpaper.height);
+ }
+ wallpaper.callbacks.register(cb);
+ File f = new File(getWallpaperDir(wallpaperUserId), KEYGUARD_WALLPAPER);
+ if (!f.exists()) {
+ return null;
+ }
+ return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ /* Shouldn't happen as we check to see if the file exists */
+ Slog.w(TAG, "Error getting wallpaper", e);
+ }
+ return null;
+ }
+ }
+
public WallpaperInfo getWallpaperInfo() {
int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
@@ -848,6 +968,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ /** @hide */
+ public boolean isKeyguardWallpaperSet() {
+ int userId = UserHandle.getCallingUserId();
+ synchronized (mLock) {
+ KeyguardWallpaperData data = mKeyguardWallpaperMap.get(userId);
+ return data.wallpaperFile.exists();
+ }
+ }
+
public ParcelFileDescriptor setWallpaper(String name, String callingPackage) {
checkPermission(android.Manifest.permission.SET_WALLPAPER);
if (!isWallpaperSupported(callingPackage)) {
@@ -901,6 +1030,58 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ public ParcelFileDescriptor setKeyguardWallpaper(String name, String callingPackage) {
+ checkPermission(android.Manifest.permission.SET_KEYGUARD_WALLPAPER);
+ if (!isWallpaperSupported(callingPackage)) {
+ return null;
+ }
+ synchronized (mLock) {
+ if (DEBUG) Slog.v(TAG, "setKeyguardWallpaper");
+ int userId = UserHandle.getCallingUserId();
+ KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(userId);
+ if (wallpaper == null) {
+ throw new IllegalStateException("Keyguard wallpaper not yet initialized for user "
+ + userId);
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ ParcelFileDescriptor pfd = updateKeyguardWallpaperBitmapLocked(name, wallpaper);
+ if (pfd != null) {
+ wallpaper.imageWallpaperPending = true;
+ }
+ return pfd;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ public ParcelFileDescriptor updateKeyguardWallpaperBitmapLocked(String name,
+ KeyguardWallpaperData wallpaper) {
+ if (name == null) name = "";
+ try {
+ File dir = getWallpaperDir(wallpaper.userId);
+ if (!dir.exists()) {
+ dir.mkdir();
+ FileUtils.setPermissions(
+ dir.getPath(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+ -1, -1);
+ }
+ File file = new File(dir, KEYGUARD_WALLPAPER);
+ ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
+ MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
+ if (!SELinux.restorecon(file)) {
+ return null;
+ }
+ wallpaper.name = name;
+ return fd;
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Error setting wallpaper", e);
+ }
+ return null;
+ }
+
// ToDo: Remove this version of the function
public void setWallpaperComponent(ComponentName name) {
checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
@@ -1125,6 +1306,22 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
}
+ private void notifyCallbacksLocked(KeyguardWallpaperData wallpaper) {
+ final int n = wallpaper.callbacks.beginBroadcast();
+ for (int i = 0; i < n; i++) {
+ try {
+ wallpaper.callbacks.getBroadcastItem(i).onKeyguardWallpaperChanged();
+ } catch (RemoteException e) {
+
+ // The RemoteCallbackList will take care of removing
+ // the dead object for us.
+ }
+ }
+ wallpaper.callbacks.finishBroadcast();
+ final Intent intent = new Intent(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
+ }
+
private void checkPermission(String permission) {
if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
@@ -1142,7 +1339,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
private static JournaledFile makeJournaledFile(int userId) {
- final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
+ return makeJournaledFile(WALLPAPER_INFO, userId);
+ }
+
+ private static JournaledFile makeJournaledFile(String name, int userId) {
+ final String base = new File(getWallpaperDir(userId), name).getAbsolutePath();
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
@@ -1195,6 +1396,36 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ private void saveSettingsLocked(KeyguardWallpaperData wallpaper) {
+ JournaledFile journal = makeJournaledFile(KEYGUARD_WALLPAPER_INFO, wallpaper.userId);
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(journal.chooseForWrite(), false);
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, "utf-8");
+ out.startDocument(null, true);
+
+ out.startTag(null, "kwp");
+ out.attribute(null, "width", Integer.toString(wallpaper.width));
+ out.attribute(null, "height", Integer.toString(wallpaper.height));
+ out.attribute(null, "name", wallpaper.name);
+ out.endTag(null, "kwp");
+
+ out.endDocument();
+ stream.close();
+ journal.commit();
+ } catch (IOException e) {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException ex) {
+ // Ignore
+ }
+ journal.rollback();
+ }
+ }
+
private void migrateFromOld() {
File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
@@ -1232,6 +1463,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
return wallpaper;
}
+ private KeyguardWallpaperData getKeyguardWallpaperSafeLocked(int userId) {
+ KeyguardWallpaperData wallpaper = mKeyguardWallpaperMap.get(userId);
+ if (wallpaper == null) {
+ loadKeyguardSettingsLocked(userId);
+ wallpaper = mKeyguardWallpaperMap.get(userId);
+ }
+ return wallpaper;
+ }
+
+
private void loadSettingsLocked(int userId) {
if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
@@ -1326,6 +1567,80 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ private void loadKeyguardSettingsLocked(int userId) {
+ if (DEBUG) Slog.v(TAG, "loadKeyguardSettingsLocked");
+
+ JournaledFile journal = makeJournaledFile(KEYGUARD_WALLPAPER_INFO, userId);
+ FileInputStream stream = null;
+ File file = journal.chooseForRead();
+ KeyguardWallpaperData keyguardWallpaper = mKeyguardWallpaperMap.get(userId);
+ if (keyguardWallpaper == null) {
+ keyguardWallpaper = new KeyguardWallpaperData(userId);
+ mKeyguardWallpaperMap.put(userId, keyguardWallpaper);
+ }
+ boolean success = false;
+ try {
+ stream = new FileInputStream(file);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, null);
+
+ int type;
+ do {
+ type = parser.next();
+ if (type == XmlPullParser.START_TAG) {
+ String tag = parser.getName();
+ if ("kwp".equals(tag)) {
+ keyguardWallpaper.width = Integer.parseInt(parser.getAttributeValue(null,
+ "width"));
+ keyguardWallpaper.height = Integer.parseInt(parser
+ .getAttributeValue(null, "height"));
+ keyguardWallpaper.name = parser.getAttributeValue(null, "name");
+ if (DEBUG) {
+ Slog.v(TAG, "mWidth:" + keyguardWallpaper.width);
+ Slog.v(TAG, "mHeight:" + keyguardWallpaper.height);
+ Slog.v(TAG, "mName:" + keyguardWallpaper.name);
+ }
+ }
+ }
+ } while (type != XmlPullParser.END_DOCUMENT);
+ success = true;
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "no current wallpaper -- first boot?");
+ } catch (NullPointerException e) {
+ Slog.w(TAG, "failed parsing " + file + " " + e);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "failed parsing " + file + " " + e);
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "failed parsing " + file + " " + e);
+ } catch (IOException e) {
+ Slog.w(TAG, "failed parsing " + file + " " + e);
+ } catch (IndexOutOfBoundsException e) {
+ Slog.w(TAG, "failed parsing " + file + " " + e);
+ }
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+
+ if (!success) {
+ keyguardWallpaper.width = -1;
+ keyguardWallpaper.height = -1;
+ keyguardWallpaper.name = "";
+ }
+
+ // We always want to have some reasonable width hint.
+ int baseSize = getMaximumSizeDimension();
+ if (keyguardWallpaper.width < baseSize) {
+ keyguardWallpaper.width = baseSize;
+ }
+ if (keyguardWallpaper.height < baseSize) {
+ keyguardWallpaper.height = baseSize;
+ }
+ }
+
private int getMaximumSizeDimension() {
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
diff --git a/services/core/java/com/android/server/wm/BlurLayer.java b/services/core/java/com/android/server/wm/BlurLayer.java
new file mode 100644
index 0000000..b54ac9e
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BlurLayer.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2014 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.wm;
+
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import java.io.PrintWriter;
+
+public class BlurLayer {
+ private static final String TAG = "BlurLayer";
+ private static final boolean DEBUG = false;
+
+ /** Reference to the owner of this object. */
+ final DisplayContent mDisplayContent;
+
+ /** Actual surface that blurs */
+ SurfaceControl mBlurSurface;
+
+ /** Last value passed to mBlurSurface.setBlur() */
+ float mBlur = 0;
+
+ /** Last value passed to mBlurSurface.setLayer() */
+ int mLayer = -1;
+
+ /** Next values to pass to mBlurSurface.setPosition() and mBlurSurface.setSize() */
+ Rect mBounds = new Rect();
+
+ /** Last values passed to mBlurSurface.setPosition() and mBlurSurface.setSize() */
+ Rect mLastBounds = new Rect();
+
+ /** True after mBlurSurface.show() has been called, false after mBlurSurface.hide(). */
+ private boolean mShowing = false;
+
+ /** Value of mBlur when beginning transition to mTargetBlur */
+ float mStartBlur = 0;
+
+ /** Final value of mBlur following transition */
+ float mTargetBlur = 0;
+
+ /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
+ long mStartTime;
+
+ /** Time in milliseconds to take to transition from mStartBlur to mTargetBlur */
+ long mDuration;
+
+ /** Owning stack */
+ final TaskStack mStack;
+
+ BlurLayer(WindowManagerService service, TaskStack stack, DisplayContent displayContent) {
+ mStack = stack;
+ mDisplayContent = displayContent;
+ final int displayId = mDisplayContent.getDisplayId();
+ if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
+ SurfaceControl.openTransaction();
+ try {
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ mBlurSurface = new WindowStateAnimator.SurfaceTrace(service.mFxSession,
+ "BlurSurface",
+ 16, 16, PixelFormat.OPAQUE,
+ SurfaceControl.FX_SURFACE_BLUR | SurfaceControl.HIDDEN);
+ } else {
+ mBlurSurface = new SurfaceControl(service.mFxSession, TAG,
+ 16, 16, PixelFormat.OPAQUE,
+ SurfaceControl.FX_SURFACE_BLUR | SurfaceControl.HIDDEN);
+ }
+ if (WindowManagerService.SHOW_TRANSACTIONS ||
+ WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(TAG,
+ " BLUR " + mBlurSurface + ": CREATE");
+ mBlurSurface.setLayerStack(displayId);
+ } catch (Exception e) {
+ Slog.e(WindowManagerService.TAG, "Exception creating Blur surface", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
+ /** Return true if blur layer is showing */
+ boolean isBlurring() {
+ return mTargetBlur != 0;
+ }
+
+ /** Return true if in a transition period */
+ boolean isAnimating() {
+ return mTargetBlur != mBlur;
+ }
+
+ float getTargetBlur() {
+ return mTargetBlur;
+ }
+
+ void setLayer(int layer) {
+ if (mLayer != layer) {
+ mLayer = layer;
+ mBlurSurface.setLayer(layer);
+ }
+ }
+
+ int getLayer() {
+ return mLayer;
+ }
+
+ private void setBlur(float blur) {
+ if (mBlur != blur) {
+ if (DEBUG) Slog.v(TAG, "setBlur blur=" + blur);
+ try {
+ mBlurSurface.setBlur(blur);
+ if (blur == 0 && mShowing) {
+ if (DEBUG) Slog.v(TAG, "setBlur hiding");
+ mBlurSurface.hide();
+ mShowing = false;
+ } else if (blur > 0 && !mShowing) {
+ if (DEBUG) Slog.v(TAG, "setBlur showing");
+ mBlurSurface.show();
+ mShowing = true;
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting blur immediately", e);
+ }
+ mBlur = blur;
+ }
+ }
+
+ void adjustBounds() {
+ final int dw, dh;
+ final float xPos, yPos;
+ if (!mStack.isFullscreen()) {
+ dw = mBounds.width();
+ dh = mBounds.height();
+ xPos = mBounds.left;
+ yPos = mBounds.top;
+ } else {
+ // Set surface size to screen size.
+ final DisplayInfo info = mDisplayContent.getDisplayInfo();
+ dw = info.logicalWidth;
+ dh = info.logicalHeight;
+ xPos = 0;
+ yPos = 0;
+ }
+
+ mBlurSurface.setPosition(xPos, yPos);
+ mBlurSurface.setSize(dw, dh);
+ mLastBounds.set(mBounds);
+ }
+
+ void setBounds(Rect bounds) {
+ mBounds.set(bounds);
+ if (isBlurring() && !mLastBounds.equals(bounds)) {
+ try {
+ SurfaceControl.openTransaction();
+ adjustBounds();
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure setting size", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
+ /**
+ * @param duration The time to test.
+ * @return True if the duration would lead to an earlier end to the current animation.
+ */
+ private boolean durationEndsEarlier(long duration) {
+ return SystemClock.uptimeMillis() + duration < mStartTime + mDuration;
+ }
+
+ /** Jump to the end of the animation.
+ * NOTE: Must be called with Surface transaction open. */
+ void show() {
+ if (isAnimating()) {
+ if (DEBUG) Slog.v(TAG, "show: immediate");
+ show(mLayer, mTargetBlur, 0);
+ }
+ }
+
+ /**
+ * Begin an animation to a new dim value.
+ * NOTE: Must be called with Surface transaction open.
+ *
+ * @param layer The layer to set the surface to.
+ * @param blur The dim value to end at.
+ * @param duration How long to take to get there in milliseconds.
+ */
+ void show(int layer, float blur, long duration) {
+ if (DEBUG) Slog.v(TAG, "show: layer=" + layer + " blur=" + blur
+ + " duration=" + duration);
+ if (mBlurSurface == null) {
+ Slog.e(TAG, "show: no Surface");
+ // Make sure isAnimating() returns false.
+ mTargetBlur = mBlur = 0;
+ return;
+ }
+
+ if (!mLastBounds.equals(mBounds)) {
+ adjustBounds();
+ }
+ setLayer(layer);
+
+ long curTime = SystemClock.uptimeMillis();
+ final boolean animating = isAnimating();
+ if ((animating && (mTargetBlur != blur || durationEndsEarlier(duration)))
+ || (!animating && mBlur != blur)) {
+ if (duration <= 0) {
+ // No animation required, just set values.
+ setBlur(blur);
+ } else {
+ // Start or continue animation with new parameters.
+ mStartBlur = mBlur;
+ mStartTime = curTime;
+ mDuration = duration;
+ }
+ }
+ if (DEBUG) Slog.v(TAG, "show: mStartBlur=" + mStartBlur + " mStartTime=" + mStartTime);
+ mTargetBlur = blur;
+ }
+
+ /** Immediate hide.
+ * NOTE: Must be called with Surface transaction open. */
+ void hide() {
+ if (mShowing) {
+ if (DEBUG) Slog.v(TAG, "hide: immediate");
+ hide(0);
+ }
+ }
+
+ /**
+ * Gradually fade to transparent.
+ * NOTE: Must be called with Surface transaction open.
+ *
+ * @param duration Time to fade in milliseconds.
+ */
+ void hide(long duration) {
+ if (mShowing && (mTargetBlur != 0 || durationEndsEarlier(duration))) {
+ if (DEBUG) Slog.v(TAG, "hide: duration=" + duration);
+ show(mLayer, 0, duration);
+ }
+ }
+
+ /**
+ * Advance the dimming per the last #show(int, float, long) call.
+ * NOTE: Must be called with Surface transaction open.
+ *
+ * @return True if animation is still required after this step.
+ */
+ boolean stepAnimation() {
+ if (mBlurSurface == null) {
+ Slog.e(TAG, "stepAnimation: null Surface");
+ // Ensure that isAnimating() returns false;
+ mTargetBlur = mBlur = 0;
+ return false;
+ }
+
+ if (isAnimating()) {
+ final long curTime = SystemClock.uptimeMillis();
+ final float blurDelta = mTargetBlur - mStartBlur;
+ float blur = mStartBlur + blurDelta * (curTime - mStartTime) / mDuration;
+ if (blurDelta > 0 && blur > mTargetBlur ||
+ blurDelta < 0 && blur < mTargetBlur) {
+ // Don't exceed limits.
+ blur = mTargetBlur;
+ }
+ if (DEBUG) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " blur=" + blur);
+ setBlur(blur);
+ }
+
+ return isAnimating();
+ }
+
+ /** Cleanup */
+ void destroySurface() {
+ if (DEBUG) Slog.v(TAG, "destroySurface.");
+ if (mBlurSurface != null) {
+ mBlurSurface.destroy();
+ mBlurSurface = null;
+ }
+ }
+
+ public void printTo(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("mBlurSurface="); pw.print(mBlurSurface);
+ pw.print(" mLayer="); pw.print(mLayer);
+ pw.print(" mBlur="); pw.println(mBlur);
+ pw.print(prefix); pw.print("mLastBounds="); pw.print(mLastBounds.toShortString());
+ pw.print(" mBounds="); pw.println(mBounds.toShortString());
+ pw.print(prefix); pw.print("Last animation: ");
+ pw.print(" mDuration="); pw.print(mDuration);
+ pw.print(" mStartTime="); pw.print(mStartTime);
+ pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
+ pw.print(prefix); pw.print(" mStartBlur="); pw.print(mStartBlur);
+ pw.print(" mTargetBlur="); pw.println(mTargetBlur);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7774057..2edf552 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -317,6 +317,35 @@ class DisplayContent {
}
}
+ boolean animateBlurLayers() {
+ boolean result = false;
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ result |= mStacks.get(stackNdx).animateBlurLayers();
+ }
+ return result;
+ }
+
+ void resetBlurring() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).resetBlurringTag();
+ }
+ }
+
+ boolean isBlurring() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ if (mStacks.get(stackNdx).isBlurring()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void stopBlurringIfNeeded() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).stopBlurringIfNeeded();
+ }
+ }
+
void close() {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).close();
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 7dd716e..7e5c807 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -51,6 +51,7 @@ class ScreenRotationAnimation {
BlackFrame mExitingBlackFrame;
BlackFrame mEnteringBlackFrame;
int mWidth, mHeight;
+ int mSnapshotRotation;
int mOriginalRotation;
int mOriginalWidth, mOriginalHeight;
@@ -221,13 +222,26 @@ class ScreenRotationAnimation {
originalWidth = displayInfo.logicalWidth;
originalHeight = displayInfo.logicalHeight;
}
- if (originalRotation == Surface.ROTATION_90
- || originalRotation == Surface.ROTATION_270) {
- mWidth = originalHeight;
- mHeight = originalWidth;
+ // Allow for abnormal hardware orientation
+ mSnapshotRotation = (4 - android.os.SystemProperties.getInt("ro.sf.hwrotation",0) / 90) % 4;
+ if (mSnapshotRotation == Surface.ROTATION_0 || mSnapshotRotation == Surface.ROTATION_180) {
+ if (originalRotation == Surface.ROTATION_90
+ || originalRotation == Surface.ROTATION_270) {
+ mWidth = originalHeight;
+ mHeight = originalWidth;
+ } else {
+ mWidth = originalWidth;
+ mHeight = originalHeight;
+ }
} else {
- mWidth = originalWidth;
- mHeight = originalHeight;
+ if (originalRotation == Surface.ROTATION_90
+ || originalRotation == Surface.ROTATION_270) {
+ mWidth = originalWidth;
+ mHeight = originalHeight;
+ } else {
+ mWidth = originalHeight;
+ mHeight = originalWidth;
+ }
}
mOriginalRotation = originalRotation;
@@ -346,7 +360,7 @@ class ScreenRotationAnimation {
// Compute the transformation matrix that must be applied
// to the snapshot to make it stay in the same original position
// with the current screen rotation.
- int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);
+ int delta = DisplayContent.deltaRotation(rotation, mSnapshotRotation);
createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a8ba0f9..f0793b8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -429,6 +429,34 @@ final class Session extends IWindowSession.Stub
}
}
+ /**
+ * @hide
+ */
+ public int getLastWallpaperX() {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mService.getLastWallpaperX();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public int getLastWallpaperY() {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mService.getLastWallpaperY();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, Bundle extras, boolean sync) {
synchronized(mService.mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ba608bd..7e437c7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -37,6 +37,8 @@ public class TaskStack {
/** Amount of time in milliseconds to animate the dim surface from one value to another,
* when no window animation is driving it. */
private static final int DEFAULT_DIM_DURATION = 200;
+ private static final int DEFAULT_BLUR_DURATION = 50;
+ private static final float MAX_BLUR_AMOUNT = 1.0f;
/** Unique identifier */
final int mStackId;
@@ -78,6 +80,10 @@ public class TaskStack {
* then stop any dimming. */
boolean mDimmingTag;
+ boolean mBlurringTag;
+ BlurLayer mBlurLayer;
+ WindowStateAnimator mBlurWinAnimator;
+
/** Application tokens that are exiting, but still on screen for animations. */
final AppTokenList mExitingAppTokens = new AppTokenList();
@@ -162,6 +168,7 @@ public class TaskStack {
}
mDimLayer.setBounds(bounds);
+ mBlurLayer.setBounds(bounds);
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
mRotation = rotation;
@@ -363,6 +370,7 @@ public class TaskStack {
mDisplayContent = displayContent;
mDimLayer = new DimLayer(mService, this, displayContent);
mAnimationBackgroundSurface = new DimLayer(mService, this, displayContent);
+ mBlurLayer = new BlurLayer(mService, this, displayContent);
updateDisplayInfo();
}
@@ -386,7 +394,6 @@ public class TaskStack {
if (doAnotherLayoutPass) {
mService.requestTraversalLocked();
}
-
close();
}
@@ -397,6 +404,10 @@ public class TaskStack {
}
}
+ private long getBlurBehindFadeDuration(long duration) {
+ return getDimBehindFadeDuration(duration);
+ }
+
private long getDimBehindFadeDuration(long duration) {
TypedValue tv = new TypedValue();
mService.mContext.getResources().getValue(
@@ -503,6 +514,82 @@ public class TaskStack {
}
}
+ boolean animateBlurLayers() {
+ boolean result = false;
+ final int blurLayer;
+ final float blurAmount;
+ if (mBlurWinAnimator == null) {
+ blurLayer = mBlurLayer.getLayer();
+ blurAmount = 0;
+ } else {
+ blurLayer = mBlurWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_BLUR;
+ blurAmount = mBlurWinAnimator.mWin.mAttrs.blurAmount;
+ }
+ final float targetBlur = mBlurLayer.getTargetBlur();
+ if (targetBlur != blurAmount) {
+ if (mBlurWinAnimator == null) {
+ mBlurLayer.hide(DEFAULT_BLUR_DURATION);
+ } else {
+ long duration = (mBlurWinAnimator.mAnimating && mBlurWinAnimator.mAnimation != null)
+ ? mBlurWinAnimator.mAnimation.computeDurationHint()
+ : DEFAULT_BLUR_DURATION;
+ if (targetBlur > blurAmount) {
+ duration = getBlurBehindFadeDuration(duration);
+ }
+ if (duration > DEFAULT_BLUR_DURATION)
+ duration = DEFAULT_BLUR_DURATION;
+ mBlurLayer.show(blurLayer, blurAmount, duration);
+ }
+ } else if (mBlurLayer.getLayer() != blurLayer) {
+ mBlurLayer.setLayer(blurLayer);
+ }
+ if (mBlurLayer.isAnimating()) {
+ if (!mService.okToDisplay()) {
+ // Jump to the end of the animation.
+ mBlurLayer.show();
+ } else {
+ result = mBlurLayer.stepAnimation();
+ }
+ }
+ return result;
+ }
+
+ void resetBlurringTag() {
+ mBlurringTag = false;
+ }
+
+ void setBlurringTag() {
+ mBlurringTag = true;
+ }
+
+ boolean testBlurringTag() {
+ return mBlurringTag;
+ }
+
+ boolean isBlurring() {
+ return mBlurLayer.isBlurring();
+ }
+
+ boolean isBlurring(WindowStateAnimator winAnimator) {
+ return mBlurWinAnimator == winAnimator && mBlurLayer.isBlurring();
+ }
+
+ void stopBlurringIfNeeded() {
+ if (!mBlurringTag && isBlurring()) {
+ mBlurWinAnimator = null;
+ }
+ }
+
+ void startBlurringIfNeeded(WindowStateAnimator newWinAnimator) {
+ final WindowStateAnimator existingBlurWinAnimator = mBlurWinAnimator;
+ // Don't turn on for an unshown surface, or for any layer but the highest blur layer.
+ if (newWinAnimator.mSurfaceShown && (existingBlurWinAnimator == null
+ || !existingBlurWinAnimator.mSurfaceShown
+ || existingBlurWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
+ mBlurWinAnimator = newWinAnimator;
+ }
+ }
+
void switchUser() {
int top = mTasks.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
@@ -524,6 +611,10 @@ public class TaskStack {
mDimLayer.destroySurface();
mDimLayer = null;
}
+ if (mBlurLayer != null) {
+ mBlurLayer.destroySurface();
+ mBlurLayer = null;
+ }
mDisplayContent = null;
}
@@ -542,6 +633,11 @@ public class TaskStack {
mDimLayer.printTo(prefix + " ", pw);
pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
}
+ if (mBlurLayer.isBlurring()) {
+ pw.print(prefix); pw.println("mBlurLayer:");
+ mBlurLayer.printTo(prefix, pw);
+ pw.print(prefix); pw.print("mBlurWinAnimator="); pw.println(mBlurWinAnimator);
+ }
if (!mExitingAppTokens.isEmpty()) {
pw.println();
pw.println(" Exiting application tokens:");
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index e226e3d..3ae783e 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -23,6 +23,7 @@ import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.FontMetricsInt;
+import android.os.SystemProperties;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@@ -76,6 +77,14 @@ class Watermark {
else c2 -= '0';
builder.append((char)(255-((c1*16)+c2)));
}
+
+ int appendDisplayVersion = (WindowManagerService.getPropertyInt(tokens, 10,
+ TypedValue.COMPLEX_UNIT_PX, 0, dm));
+ if (appendDisplayVersion != 0) {
+ builder.append(" - ");
+ builder.append(SystemProperties.get("ro.cm.display.version"));
+ }
+
mText = builder.toString();
if (false) {
Log.i(WindowManagerService.TAG, "Final text: " + mText);
@@ -149,27 +158,32 @@ class Watermark {
if (c != null) {
c.drawColor(0, PorterDuff.Mode.CLEAR);
- int deltaX = mDeltaX;
- int deltaY = mDeltaY;
-
- // deltaX shouldn't be close to a round fraction of our
- // x step, or else things will line up too much.
- int div = (dw+mTextWidth)/deltaX;
- int rem = (dw+mTextWidth) - (div*deltaX);
- int qdelta = deltaX/4;
- if (rem < qdelta || rem > (deltaX-qdelta)) {
- deltaX += deltaX/3;
- }
+ if (mDeltaX != 0 || mDeltaY != 0) {
+ int deltaX = mDeltaX;
+ int deltaY = mDeltaY;
+
+ // deltaX shouldn't be close to a round fraction of our
+ // x step, or else things will line up too much.
+ int div = (dw+mTextWidth)/deltaX;
+ int rem = (dw+mTextWidth) - (div*deltaX);
+ int qdelta = deltaX/4;
+ if (rem < qdelta || rem > (deltaX-qdelta)) {
+ deltaX += deltaX/3;
+ }
- int y = -mTextHeight;
- int x = -mTextWidth;
- while (y < (dh+mTextHeight)) {
- c.drawText(mText, x, y, mTextPaint);
- x += deltaX;
- if (x >= dw) {
- x -= (dw+mTextWidth);
- y += deltaY;
+ int y = -mTextHeight;
+ int x = -mTextWidth;
+ while (y < (dh+mTextHeight)) {
+ c.drawText(mText, x, y, mTextPaint);
+ x += deltaX;
+ if (x >= dw) {
+ x -= (dw+mTextWidth);
+ y += deltaY;
+ }
}
+ } else {
+ c.drawText(mText, dw - mTextWidth,
+ dh - mTextHeight*4, mTextPaint);
}
mSurface.unlockCanvasAndPost(c);
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 85a9624..5de1837 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -36,6 +36,7 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.view.Display;
import android.view.SurfaceControl;
+import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -92,10 +93,13 @@ public class WindowAnimator {
boolean mKeyguardGoingAway;
boolean mKeyguardGoingAwayToNotificationShade;
boolean mKeyguardGoingAwayDisableWindowAnimations;
+ boolean mKeyguardGoingAwayShowingMedia;
/** Use one animation for all entering activities after keyguard is dismissed. */
Animation mPostKeyguardExitAnimation;
+ private final boolean mBlurUiEnabled;
+
// forceHiding states.
static final int KEYGUARD_NOT_SHOWN = 0;
static final int KEYGUARD_SHOWN = 1;
@@ -116,6 +120,9 @@ public class WindowAnimator {
mContext = service.mContext;
mPolicy = service.mPolicy;
+ mBlurUiEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_ui_blur_enabled);
+
mAnimationFrameCallback = new Choreographer.FrameCallback() {
public void doFrame(long frameTimeNs) {
synchronized (mService.mWindowMap) {
@@ -203,6 +210,8 @@ public class WindowAnimator {
allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
// Show SHOW_WHEN_LOCKED windows that turn on the screen
allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
+ // Show windows that use TYPE_STATUS_BAR_SUB_PANEL when locked
+ allowWhenLocked |= win.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD_PANEL;
if (appShowWhenLocked != null) {
allowWhenLocked |= appShowWhenLocked == win.mAppToken
@@ -214,7 +223,7 @@ public class WindowAnimator {
// Only hide windows if the keyguard is active and not animating away.
boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
- && mForceHiding != KEYGUARD_ANIMATING_OUT;
+ && (mForceHiding != KEYGUARD_ANIMATING_OUT && !mBlurUiEnabled);
return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY);
}
@@ -223,7 +232,7 @@ public class WindowAnimator {
final WindowList windows = mService.getWindowListLocked(displayId);
- if (mKeyguardGoingAway) {
+ if (mKeyguardGoingAway && !mBlurUiEnabled) {
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState win = windows.get(i);
if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
@@ -237,7 +246,8 @@ public class WindowAnimator {
// Create a new animation to delay until keyguard is gone on its own.
winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
- winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
+ winAnimator.mAnimation.setDuration(
+ mBlurUiEnabled ? 0 : KEYGUARD_ANIM_TIMEOUT_MS);
winAnimator.mAnimationIsEntrance = false;
winAnimator.mAnimationStartTime = -1;
winAnimator.mKeyguardGoingAwayAnimation = true;
@@ -327,7 +337,8 @@ public class WindowAnimator {
if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
mForceHiding = KEYGUARD_ANIMATING_OUT;
} else {
- mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
+ mForceHiding = win.isDrawnLw() && !mBlurUiEnabled ?
+ KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
}
}
if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
@@ -486,7 +497,7 @@ public class WindowAnimator {
&& !mKeyguardGoingAwayDisableWindowAnimations) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
Animation a = mPolicy.createForceHideWallpaperExitAnimation(
- mKeyguardGoingAwayToNotificationShade);
+ mKeyguardGoingAwayToNotificationShade, mKeyguardGoingAwayShowingMedia);
if (a != null) {
wallpaper.mWinAnimator.setAnimation(a);
}
@@ -697,6 +708,7 @@ public class WindowAnimator {
}
mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
+ mAnimating |= mService.getDisplayContentLocked(displayId).animateBlurLayers();
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c40947b..dcb1e18 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -154,7 +154,9 @@ import java.util.List;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -247,7 +249,17 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Dim surface layer is immediately below target window.
*/
- static final int LAYER_OFFSET_DIM = 1;
+ static final int LAYER_OFFSET_DIM = 1+1;
+
+ /**
+ * Blur surface layer is immediately below dim layer.
+ */
+ static final int LAYER_OFFSET_BLUR = 2+1;
+
+ /**
+ * Blur_with_masking layer is immediately below blur layer.
+ */
+ static final int LAYER_OFFSET_BLUR_WITH_MASKING = 1;
/**
* FocusedStackFrame layer is immediately above focused window.
@@ -298,6 +310,7 @@ public class WindowManagerService extends IWindowManager.Stub
private static final String SYSTEM_SECURE = "ro.secure";
private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
+ private static final String PERSIST_SYS_LCD_DENSITY = "persist.sys.lcd_density";
private static final String DENSITY_OVERRIDE = "ro.config.density_override";
private static final String SIZE_OVERRIDE = "ro.config.size_override";
@@ -307,6 +320,8 @@ public class WindowManagerService extends IWindowManager.Stub
final private KeyguardDisableHandler mKeyguardDisableHandler;
+ private final int mSfHwRotation;
+
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -997,6 +1012,9 @@ public class WindowManagerService extends IWindowManager.Stub
SurfaceControl.closeTransaction();
}
+ // Load hardware rotation from prop
+ mSfHwRotation = android.os.SystemProperties.getInt("ro.sf.hwrotation",0) / 90;
+
showEmulatorDisplayOverlayIfNeeded();
}
@@ -2144,6 +2162,36 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ public int getLastWallpaperX() {
+ int curTokenIndex = mWallpaperTokens.size();
+ while (curTokenIndex > 0) {
+ curTokenIndex--;
+ WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ int curWallpaperIndex = token.windows.size();
+ while (curWallpaperIndex > 0) {
+ curWallpaperIndex--;
+ WindowState wallpaperWin = token.windows.get(curWallpaperIndex);
+ return wallpaperWin.mXOffset;
+ }
+ }
+ return -1;
+ }
+
+ public int getLastWallpaperY() {
+ int curTokenIndex = mWallpaperTokens.size();
+ while (curTokenIndex > 0) {
+ curTokenIndex--;
+ WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ int curWallpaperIndex = token.windows.size();
+ while (curWallpaperIndex > 0) {
+ curWallpaperIndex--;
+ WindowState wallpaperWin = token.windows.get(curWallpaperIndex);
+ return wallpaperWin.mYOffset;
+ }
+ }
+ return -1;
+ }
+
boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
boolean sync) {
boolean changed = false;
@@ -2733,7 +2781,7 @@ public class WindowManagerService extends IWindowManager.Stub
// to hold off on removing the window until the animation is done.
// If the display is frozen, just remove immediately, since the
// animation wouldn't be seen.
- if (win.mHasSurface && okToDisplay()) {
+ if (win.mHasSurface && okToDisplay() && !win.mBinderDied) {
// If we are not currently running the exit animation, we
// need to see about starting one.
wasVisible = win.isWinVisibleLw();
@@ -3799,7 +3847,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
public int getOrientationLocked() {
- if (mDisplayFrozen) {
+ if (mDisplayFrozen || mAppsFreezingScreen > 0) {
if (mLastWindowForcedOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Display is frozen, return "
+ mLastWindowForcedOrientation);
@@ -3824,8 +3872,8 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
int req = win.mAttrs.screenOrientation;
- if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
- (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
+ if ((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
+ (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)) {
continue;
}
@@ -3855,7 +3903,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (DEBUG_ORIENTATION) Slog.v(TAG,
"No one is requesting an orientation when the screen is locked");
- return mLastKeyguardForcedOrientation;
+ return mLastWindowForcedOrientation = mLastKeyguardForcedOrientation;
}
}
@@ -4312,7 +4360,7 @@ public class WindowManagerService extends IWindowManager.Stub
AppWindowToken ttoken = findAppWindowToken(transferFrom);
if (ttoken != null) {
WindowState startingWindow = ttoken.startingWindow;
- if (startingWindow != null) {
+ if (startingWindow != null && ttoken.startingView != null) {
// In this case, the starting icon has already been displayed, so start
// letting windows get shown immediately without any more transitions.
mSkipAppTransitionAnimation = true;
@@ -5460,7 +5508,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void keyguardGoingAway(boolean disableWindowAnimations,
- boolean keyguardGoingToNotificationShade) {
+ boolean keyguardGoingToNotificationShade, boolean keyguardShowingMedia) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
@@ -5471,6 +5519,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAnimator.mKeyguardGoingAway = true;
mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
+ mAnimator.mKeyguardGoingAwayShowingMedia = keyguardShowingMedia;
requestTraversalLocked();
}
}
@@ -5615,6 +5664,11 @@ public class WindowManagerService extends IWindowManager.Stub
mPointerEventDispatcher.unregisterInputEventListener(listener);
}
+ @Override
+ public void addSystemUIVisibilityFlag(int flags) {
+ mLastStatusBarVisibility |= flags;
+ }
+
// Called by window manager policy. Not exposed externally.
@Override
public int getLidState() {
@@ -5771,7 +5825,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean wallpaperEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableWallpaperService)
&& !mOnlyCore;
- boolean haveKeyguard = true;
+ boolean haveKeyguard = false;
// TODO(multidisplay): Expand to all displays?
final WindowList windows = getDefaultWindowListLocked();
final int N = windows.size();
@@ -6196,10 +6250,13 @@ public class WindowManagerService extends IWindowManager.Stub
int retryCount = 0;
WindowState appWin = null;
- final boolean appIsImTarget = mInputMethodTarget != null
- && mInputMethodTarget.mAppToken != null
- && mInputMethodTarget.mAppToken.appToken != null
- && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
+ boolean appIsImTarget;
+ synchronized(mWindowMap) {
+ appIsImTarget = mInputMethodTarget != null
+ && mInputMethodTarget.mAppToken != null
+ && mInputMethodTarget.mAppToken.appToken != null
+ && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
+ }
final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
@@ -6353,6 +6410,8 @@ public class WindowManagerService extends IWindowManager.Stub
// The screenshot API does not apply the current screen rotation.
int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
+ // Allow for abnormal hardware orientation
+ rot = (rot + mSfHwRotation) % 4;
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
@@ -8539,6 +8598,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public int getInitialDisplayDensity(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ return DisplayMetrics.DENSITY_DEVICE_DEFAULT;
+ }
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
@@ -8552,6 +8614,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public int getBaseDisplayDensity(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ return DisplayMetrics.DENSITY_PREFERRED;
+ }
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
@@ -8579,6 +8644,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
if (displayContent != null) {
+ SystemProperties.set(PERSIST_SYS_LCD_DENSITY, Integer.toString(density));
setForcedDisplayDensityLocked(displayContent, density);
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
@@ -8587,6 +8653,10 @@ public class WindowManagerService extends IWindowManager.Stub
} finally {
Binder.restoreCallingIdentity(ident);
}
+ try {
+ ActivityManagerNative.getDefault().restart();
+ } catch (RemoteException e) {
+ }
}
// displayContent must not be null
@@ -8615,6 +8685,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
if (displayContent != null) {
+ SystemProperties.set(PERSIST_SYS_LCD_DENSITY, null);
setForcedDisplayDensityLocked(displayContent,
displayContent.mInitialDisplayDensity);
Settings.Global.putString(mContext.getContentResolver(),
@@ -8624,6 +8695,10 @@ public class WindowManagerService extends IWindowManager.Stub
} finally {
Binder.restoreCallingIdentity(ident);
}
+ try {
+ ActivityManagerNative.getDefault().restart();
+ } catch (RemoteException e) {
+ }
}
// displayContent must not be null
@@ -8884,7 +8959,7 @@ public class WindowManagerService extends IWindowManager.Stub
anyLayerChanged = true;
}
final TaskStack stack = w.getStack();
- if (layerChanged && stack != null && stack.isDimming(winAnimator)) {
+ if (layerChanged && stack != null && (stack.isDimming(winAnimator) || stack.isBlurring(winAnimator))) {
// Force an animation pass just to update the mDimLayer layer.
scheduleAnimationLocked();
}
@@ -9786,6 +9861,31 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ private void handleFlagBlurBehind(WindowState w) {
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+ if ((attrs.flags & FLAG_BLUR_BEHIND) != 0
+ && w.isDisplayedLw()
+ && !w.mExiting) {
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+ final TaskStack stack = w.getStack();
+ if (stack == null) {
+ return;
+ }
+ stack.setBlurringTag();
+ if (!stack.isBlurring(winAnimator)) {
+ if (localLOGV) Slog.v(TAG, "Win " + w + " start blurring");
+ stack.startBlurringIfNeeded(winAnimator);
+ }
+ }
+ }
+
+ private void handlePrivateFlagBlurWithMasking(WindowState w) {
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+ boolean hideForced = !w.isDisplayedLw() || w.mExiting;
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+ winAnimator.updateBlurWithMaskingState(attrs, hideForced);
+ }
+
private void updateAllDrawnLocked(DisplayContent displayContent) {
// See if any windows have been drawn, so they (and others
// associated with them) can now be shown.
@@ -9961,6 +10061,7 @@ public class WindowManagerService extends IWindowManager.Stub
mInnerFields.mObscured = false;
mInnerFields.mSyswin = false;
displayContent.resetDimming();
+ displayContent.resetBlurring();
// Only used if default window
final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
@@ -9985,6 +10086,11 @@ public class WindowManagerService extends IWindowManager.Stub
handleFlagDimBehind(w);
}
+ if (stack != null && !stack.testBlurringTag()) {
+ handleFlagBlurBehind(w);
+ }
+ handlePrivateFlagBlurWithMasking(w);
+
if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
&& w.isVisibleLw()) {
// This is the wallpaper target and its obscured state
@@ -10124,6 +10230,7 @@ public class WindowManagerService extends IWindowManager.Stub
true /* inTraversal, must call performTraversalInTrans... below */);
getDisplayContentLocked(displayId).stopDimmingIfNeeded();
+ getDisplayContentLocked(displayId).stopBlurringIfNeeded();
if (updateAllDrawn) {
updateAllDrawnLocked(displayContent);
@@ -11079,6 +11186,16 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public boolean hasPermanentMenuKey() {
+ return mPolicy.hasPermanentMenuKey();
+ }
+
+ @Override
+ public boolean needsNavigationBar() {
+ return mPolicy.needsNavigationBar();
+ }
+
+ @Override
public void lockNow(Bundle options) {
mPolicy.lockNow(options);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c2548de..3bef41b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -333,6 +333,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
/** Is this window now (or just being) removed? */
boolean mRemoved;
+ /** Is this window going to be removed from binderDied callback? */
+ boolean mBinderDied;
+
/**
* Temp for keeping track of windows that have been removed when
* rebuilding window list.
@@ -1209,9 +1212,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
WindowState win = mService.windowForClientLocked(mSession, mClient, false);
Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
+ win.mBinderDied = true;
mService.removeWindowLocked(win);
} else if (mHasSurface) {
Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
+ WindowState.this.mBinderDied = true;
mService.removeWindowLocked(WindowState.this);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 42042b9..342a2ac 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -29,6 +29,7 @@ import static com.android.server.wm.WindowManagerService.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerService.localLOGV;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import android.content.Context;
import android.graphics.Matrix;
@@ -94,6 +95,13 @@ class WindowStateAnimator {
SurfaceControl mSurfaceControl;
SurfaceControl mPendingDestroySurface;
+ int mLayerStack;
+
+ SurfaceControl mSurfaceControlBlur;
+ SurfaceControl mPendingDestroySurfaceBlur;
+ boolean mSurfaceBlurShown; // last value
+ boolean mSurfaceBlurScaleNeeded;
+ final static int BLUR_LAYER_OFFSET = WindowManagerService.LAYER_OFFSET_BLUR_WITH_MASKING;
/**
* Set when we have changed the size of the surface, to know that
@@ -503,6 +511,12 @@ class WindowStateAnimator {
} catch (RuntimeException e) {
Slog.w(TAG, "Exception hiding surface in " + mWin);
}
+ if (mSurfaceControlBlur != null) {
+ try { mSurfaceControlBlur.hide(); }
+ catch (RuntimeException e) {
+ Slog.w(TAG, "Exception hiding surface blur in " + mWin);
+ }
+ }
}
}
}
@@ -791,6 +805,24 @@ class WindowStateAnimator {
flags |= SurfaceControl.SECURE;
}
+ final boolean consumingNavBar =
+ (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ && (attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
+ && (attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+
+ final DisplayContent displayContent = w.getDisplayContent();
+
+ int defaultWidth = 1;
+ int defaultHeight = 1;
+ if (displayContent != null) {
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ // When we need to expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ // set the default width and height of the window to the size of the display
+ // we can use.
+ defaultWidth = consumingNavBar ? displayInfo.logicalWidth : displayInfo.appWidth;
+ defaultHeight = consumingNavBar ? displayInfo.logicalHeight : displayInfo.appHeight;
+ }
+
int width;
int height;
if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) {
@@ -799,17 +831,17 @@ class WindowStateAnimator {
width = w.mRequestedWidth;
height = w.mRequestedHeight;
} else {
- width = w.mCompatFrame.width();
- height = w.mCompatFrame.height();
+ width = consumingNavBar ? defaultWidth : w.mCompatFrame.width();
+ height = consumingNavBar ? defaultHeight : w.mCompatFrame.height();
}
// Something is wrong and SurfaceFlinger will not like this,
// try to revert to sane values
if (width <= 0) {
- width = 1;
+ width = defaultWidth;
}
if (height <= 0) {
- height = 1;
+ height = defaultHeight;
}
float left = w.mFrame.left + w.mXOffset;
@@ -916,9 +948,9 @@ class WindowStateAnimator {
try {
mSurfaceControl.setPosition(left, top);
mSurfaceLayer = mAnimLayer;
- final DisplayContent displayContent = w.getDisplayContent();
if (displayContent != null) {
- mSurfaceControl.setLayerStack(displayContent.getDisplay().getLayerStack());
+ mLayerStack = displayContent.getDisplay().getLayerStack();
+ mSurfaceControl.setLayerStack(mLayerStack);
}
mSurfaceControl.setLayer(mAnimLayer);
mSurfaceControl.setAlpha(0);
@@ -935,6 +967,7 @@ class WindowStateAnimator {
}
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Created surface " + this);
+ updateBlurWithMaskingState(attrs, false);
}
return mSurfaceControl;
}
@@ -978,6 +1011,13 @@ class WindowStateAnimator {
}
mPendingDestroySurface = mSurfaceControl;
}
+
+ if (mSurfaceControlBlur != null && mPendingDestroySurfaceBlur != mSurfaceControlBlur) {
+ if (mPendingDestroySurfaceBlur != null) {
+ mPendingDestroySurfaceBlur.destroy();
+ }
+ mPendingDestroySurfaceBlur = mSurfaceControlBlur;
+ }
} else {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
RuntimeException e = null;
@@ -988,6 +1028,9 @@ class WindowStateAnimator {
WindowManagerService.logSurface(mWin, "DESTROY", e);
}
mSurfaceControl.destroy();
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.destroy();
+ }
}
mService.hideWallpapersLocked(mWin);
} catch (RuntimeException e) {
@@ -998,6 +1041,7 @@ class WindowStateAnimator {
mSurfaceShown = false;
mSurfaceControl = null;
+ mSurfaceControlBlur = null;
mWin.mHasSurface = false;
mDrawState = NO_SURFACE;
}
@@ -1015,6 +1059,9 @@ class WindowStateAnimator {
WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
}
mPendingDestroySurface.destroy();
+ if (mPendingDestroySurfaceBlur != null) {
+ mPendingDestroySurfaceBlur.destroy();
+ }
mService.hideWallpapersLocked(mWin);
}
} catch (RuntimeException e) {
@@ -1024,6 +1071,7 @@ class WindowStateAnimator {
}
mSurfaceDestroyDeferred = false;
mPendingDestroySurface = null;
+ mPendingDestroySurfaceBlur = null;
}
void computeShownFrameLocked() {
@@ -1400,6 +1448,9 @@ class WindowStateAnimator {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"POS " + left + ", " + top, null);
mSurfaceControl.setPosition(left, top);
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.setPosition(left, top);
+ }
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + w
+ " pos=(" + left + "," + top + ")", e);
@@ -1419,6 +1470,9 @@ class WindowStateAnimator {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"SIZE " + width + "x" + height, null);
mSurfaceControl.setSize(width, height);
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.setSize(width, height);
+ }
mSurfaceControl.setMatrix(
mDsDx * w.mHScale, mDtDx * w.mVScale,
mDsDy * w.mHScale, mDtDy * w.mVScale);
@@ -1430,6 +1484,12 @@ class WindowStateAnimator {
stack.startDimmingIfNeeded(this);
}
}
+ if ((w.mAttrs.flags & LayoutParams.FLAG_BLUR_BEHIND) != 0) {
+ final TaskStack stack = w.getStack();
+ if (stack != null) {
+ stack.startBlurringIfNeeded(this);
+ }
+ }
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
@@ -1515,6 +1575,14 @@ class WindowStateAnimator {
mDsDx * w.mHScale, mDtDx * w.mVScale,
mDsDy * w.mHScale, mDtDy * w.mVScale);
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.setAlpha(mShownAlpha);
+ mSurfaceControlBlur.setLayer(mAnimLayer-BLUR_LAYER_OFFSET);
+ mSurfaceControlBlur.setMatrix(
+ mDsDx*w.mHScale, mDtDx*w.mVScale,
+ mDsDy*w.mHScale, mDtDy*w.mVScale);
+ }
+
if (mLastHidden && mDrawState == HAS_DRAWN) {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"SHOW (performLayout)", null);
@@ -1605,6 +1673,9 @@ class WindowStateAnimator {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
"POS " + left + ", " + top, null);
mSurfaceControl.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
+ }
updateSurfaceWindowCrop(false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
@@ -1783,6 +1854,9 @@ class WindowStateAnimator {
if (mSurfaceControl != null) {
mSurfaceShown = true;
mSurfaceControl.show();
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.show();
+ }
if (mWin.mTurnOnScreen) {
if (DEBUG_VISIBILITY) Slog.v(TAG,
"Show surface turning screen on: " + mWin);
@@ -1977,4 +2051,66 @@ class WindowStateAnimator {
sb.append('}');
return sb.toString();
}
+
+ void updateBlurWithMaskingState(WindowManager.LayoutParams attrs, boolean hideForced) {
+ boolean blurVisible = !hideForced && 0 != (attrs.privateFlags &
+ (WindowManager.LayoutParams.PRIVATE_FLAG_BLUR_WITH_MASKING |
+ WindowManager.LayoutParams.PRIVATE_FLAG_BLUR_WITH_MASKING_SCALED) );
+ boolean blurScaleNeeded = blurVisible && 0 != (attrs.privateFlags &
+ WindowManager.LayoutParams.PRIVATE_FLAG_BLUR_WITH_MASKING_SCALED);
+
+ if (mSurfaceBlurShown == blurVisible && mSurfaceBlurScaleNeeded == blurScaleNeeded) return;
+ mSurfaceBlurShown = blurVisible;
+ mSurfaceBlurScaleNeeded = blurScaleNeeded;
+
+ if (!blurVisible) {
+ // we don't destroy mSurfaceControlBlur
+ if (mSurfaceControlBlur != null) {
+ mSurfaceControlBlur.hide();
+ } else {
+ // nothing to do
+ }
+ return;
+ }
+
+ if (mSurfaceControl == null) return;
+
+ if (blurVisible) {
+ if (null == mSurfaceControlBlur) {
+ int flags = SurfaceControl.HIDDEN | SurfaceControl.FX_SURFACE_BLUR;
+ final boolean isHwAccelerated = (attrs.flags &
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+ final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
+ if (!PixelFormat.formatHasAlpha(attrs.format)) {
+ flags |= SurfaceControl.OPAQUE;
+ }
+
+ mSurfaceControlBlur = new SurfaceControl(
+ mSession.mSurfaceSession,
+ attrs.getTitle().toString() + " blur",
+ (int)mSurfaceW, (int)mSurfaceH, format, flags);
+ }
+
+ SurfaceControl.openTransaction();
+ try {
+ mSurfaceControlBlur.setPosition(mSurfaceX, mSurfaceY);
+ mSurfaceControlBlur.setLayerStack(mLayerStack);
+ mSurfaceControlBlur.setLayer(mAnimLayer-BLUR_LAYER_OFFSET);
+ mSurfaceControlBlur.setAlpha(mShownAlpha);
+ mSurfaceControlBlur.setBlur(1.0f);
+ mSurfaceControlBlur.setBlurMaskSurface(mSurfaceControl);
+ final int BLUR_MASKING_SAMPLING = 4;
+ mSurfaceControlBlur.setBlurMaskSampling(blurScaleNeeded ? BLUR_MASKING_SAMPLING : 1);
+ mSurfaceControlBlur.setBlurMaskAlphaThreshold(attrs.blurMaskAlphaThreshold);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error creating blur surface", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+
+ if (mSurfaceShown) {
+ mSurfaceControlBlur.show();
+ }
+ }
+ }
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 98d8d08..69488b1 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -72,3 +72,10 @@ LOCAL_SHARED_LIBRARIES += \
libGLESv2 \
libnetutils \
+ifeq ($(BOARD_USES_QC_TIME_SERVICES),true)
+LOCAL_CFLAGS += -DHAVE_QC_TIME_SERVICES=1
+LOCAL_SHARED_LIBRARIES += libtime_genoff
+$(shell mkdir -p $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/)
+$(shell touch $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/export_includes)
+endif
+
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 3fd0f84..34d863c 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -40,6 +40,14 @@
#include <linux/android_alarm.h>
#include <linux/rtc.h>
+#include <memory>
+
+#if HAVE_QC_TIME_SERVICES
+extern "C" {
+#include <private/time_genoff.h>
+}
+#endif
+
namespace android {
static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
@@ -49,6 +57,7 @@ static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
CLOCK_BOOTTIME_ALARM,
CLOCK_BOOTTIME,
CLOCK_MONOTONIC,
+ CLOCK_POWEROFF_ALARM,
CLOCK_REALTIME,
};
/* to match the legacy alarm driver implementation, we need an extra
@@ -61,6 +70,7 @@ public:
virtual ~AlarmImpl();
virtual int set(int type, struct timespec *ts) = 0;
+ virtual int clear(int type, struct timespec *ts) = 0;
virtual int setTime(struct timeval *tv) = 0;
virtual int waitForAlarm() = 0;
@@ -75,6 +85,7 @@ public:
AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
int set(int type, struct timespec *ts);
+ int clear(int type, struct timespec *ts);
int setTime(struct timeval *tv);
int waitForAlarm();
};
@@ -87,6 +98,7 @@ public:
~AlarmImplTimerFd();
int set(int type, struct timespec *ts);
+ int clear(int type, struct timespec *ts);
int setTime(struct timeval *tv);
int waitForAlarm();
@@ -114,6 +126,30 @@ int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
}
+int AlarmImplAlarmDriver::clear(int type, struct timespec *ts)
+{
+ return ioctl(fds[0], ANDROID_ALARM_CLEAR(type), ts);
+}
+
+#if HAVE_QC_TIME_SERVICES
+static int setTimeServicesTime(time_bases_type base, long int secs)
+{
+ int rc = 0;
+ time_genoff_info_type time_set;
+ uint64_t value = secs;
+ time_set.base = base;
+ time_set.unit = TIME_SECS;
+ time_set.operation = T_SET;
+ time_set.ts_val = &value;
+ rc = time_genoff_operation(&time_set);
+ if (rc) {
+ ALOGE("Error setting generic offset: %d. Still setting system time\n", rc);
+ rc = -1;
+ }
+ return rc;
+}
+#endif
+
int AlarmImplAlarmDriver::setTime(struct timeval *tv)
{
struct timespec ts;
@@ -122,6 +158,10 @@ int AlarmImplAlarmDriver::setTime(struct timeval *tv)
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
+#if HAVE_QC_TIME_SERVICES
+ setTimeServicesTime(ATS_USER, (tv->tv_sec));
+#endif
+
if (res < 0)
ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
return res;
@@ -160,6 +200,23 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts)
return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
}
+int AlarmImplTimerFd::clear(int type, struct timespec *ts)
+{
+ if (type > ANDROID_ALARM_TYPE_COUNT) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+
+ struct itimerspec spec;
+ memset(&spec, 0, sizeof(spec));
+ memcpy(&spec.it_value, ts, sizeof(spec.it_value));
+
+ return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
+}
+
int AlarmImplTimerFd::setTime(struct timeval *tv)
{
struct rtc_time rtc;
@@ -323,14 +380,14 @@ static bool rtc_is_hctosys(unsigned int rtc_id)
static int wall_clock_rtc()
{
- DIR *dir = opendir(rtc_sysfs);
- if (!dir) {
+ std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(rtc_sysfs), closedir);
+ if (!dir.get()) {
ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno));
return -1;
}
struct dirent *dirent;
- while (errno = 0, dirent = readdir(dir)) {
+ while (errno = 0, dirent = readdir(dir.get())) {
unsigned int rtc_id;
int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id);
@@ -367,6 +424,10 @@ static jlong init_timerfd()
for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
+ if ((fds[i] < 0) && (android_alarm_to_clockid[i] == CLOCK_POWEROFF_ALARM)) {
+ ALOGV("timerfd does not support CLOCK_POWEROFF_ALARM, using CLOCK_REALTIME_ALARM instead");
+ fds[i] = timerfd_create(CLOCK_REALTIME_ALARM, 0);
+ }
if (fds[i] < 0) {
ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i],
strerror(errno));
@@ -441,6 +502,23 @@ static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativ
}
}
+static void android_server_AlarmManagerService_clear(JNIEnv*, jobject, jlong nativeData, jint type,
+jlong seconds, jlong nanoseconds)
+{
+ AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
+ struct timespec ts;
+ ts.tv_sec = seconds;
+ ts.tv_nsec = nanoseconds;
+
+ int result = impl->clear(type, &ts);
+ if (result < 0)
+ {
+ ALOGE("Unable to clear alarm %lld.%09lld: %s\n",
+ static_cast<long long>(seconds),
+ static_cast<long long>(nanoseconds), strerror(errno));
+ }
+}
+
static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
{
AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
@@ -465,6 +543,7 @@ static JNINativeMethod sMethods[] = {
{"init", "()J", (void*)android_server_AlarmManagerService_init},
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
{"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
+ {"clear", "(JIJJ)V", (void*)android_server_AlarmManagerService_clear},
{"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
{"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
{"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
diff --git a/services/core/jni/com_android_server_PersistentDataBlockService.cpp b/services/core/jni/com_android_server_PersistentDataBlockService.cpp
index e842eeb..9b0393b 100644
--- a/services/core/jni/com_android_server_PersistentDataBlockService.cpp
+++ b/services/core/jni/com_android_server_PersistentDataBlockService.cpp
@@ -17,6 +17,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <JNIHelp.h>
#include <jni.h>
+#include <ScopedUtfChars.h>
#include <utils/misc.h>
#include <sys/ioctl.h>
@@ -77,23 +78,31 @@ namespace android {
static jlong com_android_server_PersistentDataBlockService_getBlockDeviceSize(JNIEnv *env, jclass, jstring jpath)
{
- const char *path = env->GetStringUTFChars(jpath, 0);
- int fd = open(path, O_RDONLY);
+ ScopedUtfChars path(env, jpath);
+ int fd = open(path.c_str(), O_RDONLY);
if (fd < 0)
return 0;
- return get_block_device_size(fd);
+ const uint64_t size = get_block_device_size(fd);
+
+ close(fd);
+
+ return size;
}
static int com_android_server_PersistentDataBlockService_wipe(JNIEnv *env, jclass, jstring jpath) {
- const char *path = env->GetStringUTFChars(jpath, 0);
- int fd = open(path, O_WRONLY);
+ ScopedUtfChars path(env, jpath);
+ int fd = open(path.c_str(), O_WRONLY);
if (fd < 0)
return 0;
- return wipe_block_device(fd);
+ const int ret = wipe_block_device(fd);
+
+ close(fd);
+
+ return ret;
}
static JNINativeMethod sMethods[] = {
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 64514a9..3f46ec6 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -25,12 +25,24 @@
namespace android {
+void* sensorInit(void *arg) {
+ ALOGI("System server: starting sensor init.\n");
+ // Start the sensor service
+ SensorService::instantiate();
+ ALOGI("System server: sensor init done.\n");
+ return NULL;
+}
+
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
char propBuf[PROPERTY_VALUE_MAX];
+ pthread_t sensor_init_thread;
+
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
- // Start the sensor service
- SensorService::instantiate();
+ // We are safe to move this to a new thread because
+ // Android frame work has taken care to check whether the
+ // service is started or not before using it.
+ pthread_create( &sensor_init_thread, NULL, &sensorInit, NULL);
}
}
diff --git a/services/core/jni/com_android_server_UsbMidiDevice.cpp b/services/core/jni/com_android_server_UsbMidiDevice.cpp
index 06b9bc3..e12a016 100644
--- a/services/core/jni/com_android_server_UsbMidiDevice.cpp
+++ b/services/core/jni/com_android_server_UsbMidiDevice.cpp
@@ -43,12 +43,26 @@ android_server_UsbMidiDevice_get_subdevice_count(JNIEnv *env, jobject /* thiz */
jint card, jint device)
{
char path[100];
+ int fd;
+ const int kMaxRetries = 10;
+ const int kSleepMicroseconds = 2000;
snprintf(path, sizeof(path), "/dev/snd/controlC%d", card);
- int fd = open(path, O_RDWR);
- if (fd < 0) {
- ALOGE("could not open %s", path);
- return 0;
+ // This control device may not have been created yet. So we should
+ // try to open it several times to prevent intermittent failure
+ // from a race condition.
+ int retryCounter = 0;
+ while ((fd = open(path, O_RDWR)) < 0) {
+ if (++retryCounter > kMaxRetries) {
+ ALOGE("timed out after %d tries, could not open %s", retryCounter, path);
+ return 0;
+ } else {
+ ALOGW("attempt #%d, could not open %s", retryCounter, path);
+ // Increase the sleep interval each time.
+ // 10 retries will total 2 * sum(1..10) = 110 milliseconds.
+ // Typically the device should be ready in 5-10 milliseconds.
+ usleep(kSleepMicroseconds * retryCounter);
+ }
}
struct snd_rawmidi_info info;
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index e29d0a9..94467a5 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -197,6 +197,8 @@ public:
void setSystemUiVisibility(int32_t visibility);
void setPointerSpeed(int32_t speed);
void setShowTouches(bool enabled);
+ void setStylusIconEnabled(bool enabled);
+ void setVolumeKeysRotation(int mode);
void setInteractive(bool interactive);
void reloadCalibration();
@@ -263,6 +265,12 @@ private:
// Show touches feature enable/disable.
bool showTouches;
+ // Show icon when stylus is used
+ bool stylusIconEnabled;
+
+ // Volume keys rotation mode (0 - off, 1 - phone, 2 - tablet)
+ int32_t volumeKeysRotationMode;
+
// Sprite controller singleton, created on first use.
sp<SpriteController> spriteController;
@@ -299,6 +307,8 @@ NativeInputManager::NativeInputManager(jobject contextObj,
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
+ mLocked.stylusIconEnabled = false;
+ mLocked.volumeKeysRotationMode = 0;
}
mInteractive = true;
@@ -446,6 +456,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
outConfig->showTouches = mLocked.showTouches;
+ outConfig->stylusIconEnabled = mLocked.stylusIconEnabled;
+ outConfig->volumeKeysRotationMode = mLocked.volumeKeysRotationMode;
outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport);
outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport);
@@ -770,6 +782,38 @@ void NativeInputManager::setShowTouches(bool enabled) {
InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
}
+void NativeInputManager::setStylusIconEnabled(bool enabled) {
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mLocked.stylusIconEnabled == enabled) {
+ return;
+ }
+
+ ALOGI("Setting stylus icon enabled to %s.", enabled ? "enabled" : "disabled");
+ mLocked.stylusIconEnabled = enabled;
+ } // release lock
+
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_STYLUS_ICON_ENABLED);
+}
+
+void NativeInputManager::setVolumeKeysRotation(int mode) {
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mLocked.volumeKeysRotationMode == mode) {
+ return;
+ }
+
+ ALOGI("Volume keys: rotation mode set to %d.", mode);
+ mLocked.volumeKeysRotationMode = mode;
+ } // release lock
+
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_VOLUME_KEYS_ROTATION);
+}
+
void NativeInputManager::setInteractive(bool interactive) {
mInteractive = interactive;
}
@@ -1292,6 +1336,20 @@ static void nativeSetShowTouches(JNIEnv* /* env */,
im->setShowTouches(enabled);
}
+static void nativeSetStylusIconEnabled(JNIEnv* env,
+ jclass clazz, jlong ptr, jboolean enabled) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->setStylusIconEnabled(enabled);
+}
+
+static void nativeSetVolumeKeysRotation(JNIEnv* env,
+ jclass clazz, jlong ptr, int mode) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->setVolumeKeysRotation(mode);
+}
+
static void nativeSetInteractive(JNIEnv* env,
jclass clazz, jlong ptr, jboolean interactive) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1409,6 +1467,10 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) nativeSetPointerSpeed },
{ "nativeSetShowTouches", "(JZ)V",
(void*) nativeSetShowTouches },
+ { "nativeSetStylusIconEnabled", "(JZ)V",
+ (void*) nativeSetStylusIconEnabled },
+ { "nativeSetVolumeKeysRotation", "(JI)V",
+ (void*) nativeSetVolumeKeysRotation },
{ "nativeSetInteractive", "(JZ)V",
(void*) nativeSetInteractive },
{ "nativeReloadCalibration", "(J)V",
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index b2b2783..f8051f0 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +42,8 @@ enum {
LIGHT_INDEX_ATTENTION = 5,
LIGHT_INDEX_BLUETOOTH = 6,
LIGHT_INDEX_WIFI = 7,
+ LIGHT_INDEX_CAPS = 8,
+ LIGHT_INDEX_FUNC = 9,
LIGHT_COUNT
};
@@ -86,6 +89,10 @@ static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
= get_device(module, LIGHT_ID_BLUETOOTH);
devices->lights[LIGHT_INDEX_WIFI]
= get_device(module, LIGHT_ID_WIFI);
+ devices->lights[LIGHT_INDEX_CAPS]
+ = get_device(module, LIGHT_ID_CAPS);
+ devices->lights[LIGHT_INDEX_FUNC]
+ = get_device(module, LIGHT_ID_FUNC);
} else {
memset(devices, 0, sizeof(Devices));
}
@@ -104,21 +111,34 @@ static void finalize_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr)
}
static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
- jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
+ jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode,
+ jint brightnessLevel, jint multipleLeds)
{
Devices* devices = (Devices*)ptr;
light_state_t state;
+ int colorAlpha;
if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
return ;
}
+ if (brightnessLevel > 0 && brightnessLevel <= 0xFF) {
+ colorAlpha = (colorARGB & 0xFF000000) >> 24;
+ if (colorAlpha == 0x00) {
+ colorAlpha = 0xFF;
+ }
+ colorAlpha = (colorAlpha * brightnessLevel) / 0xFF;
+ colorARGB = (colorAlpha << 24) + (colorARGB & 0x00FFFFFF);
+ }
+
memset(&state, 0, sizeof(light_state_t));
state.color = colorARGB;
state.flashMode = flashMode;
state.flashOnMS = onMS;
state.flashOffMS = offMS;
state.brightnessMode = brightnessMode;
+ state.ledsModes = 0 |
+ (multipleLeds ? LIGHT_MODE_MULTIPLE_LEDS : 0);
{
ALOGD_IF_SLOW(50, "Excessive delay setting light");
@@ -129,7 +149,7 @@ static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
static JNINativeMethod method_table[] = {
{ "init_native", "()J", (void*)init_native },
{ "finalize_native", "(J)V", (void*)finalize_native },
- { "setLight_native", "(JIIIIII)V", (void*)setLight_native },
+ { "setLight_native", "(JIIIIIIII)V", (void*)setLight_native },
};
int register_android_server_LightsService(JNIEnv *env)
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 5c27b1f..91eeb8b 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -641,7 +641,7 @@ static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, job
}
static void android_location_GpsLocationProvider_agps_set_reference_location_cellid(
- JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
+ JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid, jint psc)
{
AGpsRefLocation location;
@@ -657,6 +657,11 @@ static void android_location_GpsLocationProvider_agps_set_reference_location_cel
location.u.cellID.mcc = mcc;
location.u.cellID.mnc = mnc;
location.u.cellID.lac = lac;
+#ifdef AGPS_USE_PSC
+ location.u.cellID.psc = psc;
+#else
+ (void)psc;
+#endif
location.u.cellID.cid = cid;
break;
default:
@@ -1477,7 +1482,7 @@ static JNINativeMethod sMethods[] = {
"(ILjava/lang/String;)V",
(void*)android_location_GpsLocationProvider_agps_set_id},
{"native_agps_set_ref_location_cellid",
- "(IIIII)V",
+ "(IIIIII)V",
(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},
{"native_set_agps_server",
"(ILjava/lang/String;I)V",
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 1662755..509a6ca 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -148,11 +148,7 @@ static void nativeSendPowerHint(JNIEnv *env, jclass clazz, jint hintId, jint dat
int data_param = data;
if (gPowerModule && gPowerModule->powerHint) {
- if(data)
- gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, &data_param);
- else {
- gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, NULL);
- }
+ gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, &data_param);
}
}
@@ -164,6 +160,16 @@ static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint dat
}
}
+static jint nativeGetFeature(JNIEnv *env, jclass clazz, jint featureId) {
+ int value = -1;
+
+ if (gPowerModule && gPowerModule->getFeature) {
+ value = gPowerModule->getFeature(gPowerModule, (feature_t)featureId);
+ }
+
+ return (jint)value;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -182,6 +188,8 @@ static JNINativeMethod gPowerManagerServiceMethods[] = {
(void*) nativeSendPowerHint },
{ "nativeSetFeature", "(II)V",
(void*) nativeSetFeature },
+ { "nativeGetFeature", "(I)I",
+ (void*) nativeGetFeature },
};
#define FIND_CLASS(var, className) \
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 507bc9c..b7c19db 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -32,6 +32,8 @@
#include <utils/NativeHandle.h>
#include <hardware/tv_input.h>
+#include <jni/TvInputHalExtensions.h>
+
namespace android {
static struct {
@@ -71,37 +73,6 @@ static struct {
////////////////////////////////////////////////////////////////////////////////
-class BufferProducerThread : public Thread {
-public:
- BufferProducerThread(tv_input_device_t* device, int deviceId, const tv_stream_t* stream);
-
- virtual status_t readyToRun();
-
- void setSurface(const sp<Surface>& surface);
- void onCaptured(uint32_t seq, bool succeeded);
- void shutdown();
-
-private:
- Mutex mLock;
- Condition mCondition;
- sp<Surface> mSurface;
- tv_input_device_t* mDevice;
- int mDeviceId;
- tv_stream_t mStream;
- sp<ANativeWindowBuffer_t> mBuffer;
- enum {
- CAPTURING,
- CAPTURED,
- RELEASED,
- } mBufferState;
- uint32_t mSeq;
- bool mShutdown;
-
- virtual bool threadLoop();
-
- void setSurfaceLocked(const sp<Surface>& surface);
-};
-
BufferProducerThread::BufferProducerThread(
tv_input_device_t* device, int deviceId, const tv_stream_t* stream)
: Thread(false),
@@ -132,14 +103,14 @@ status_t BufferProducerThread::readyToRun() {
return NO_ERROR;
}
-void BufferProducerThread::setSurface(const sp<Surface>& surface) {
+int BufferProducerThread::setSurface(const sp<Surface>& surface) {
Mutex::Autolock autoLock(&mLock);
- setSurfaceLocked(surface);
+ return setSurfaceLocked(surface);
}
-void BufferProducerThread::setSurfaceLocked(const sp<Surface>& surface) {
+int BufferProducerThread::setSurfaceLocked(const sp<Surface>& surface) {
if (surface == mSurface) {
- return;
+ return NO_ERROR;
}
if (mBufferState == CAPTURING) {
@@ -157,6 +128,8 @@ void BufferProducerThread::setSurfaceLocked(const sp<Surface>& surface) {
mSurface = surface;
mCondition.broadcast();
+
+ return NO_ERROR;
}
void BufferProducerThread::onCaptured(uint32_t seq, bool succeeded) {
@@ -390,15 +363,37 @@ int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>
if (connection.mThread != NULL) {
connection.mThread->shutdown();
}
- connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream);
- connection.mThread->run();
+
+ connection.mThread = TvInputHalFactory::get()->createBufferProducerThread(mDevice, deviceId, &stream);
+ if (connection.mThread == NULL) {
+ ALOGE("No memory for BufferProducerThread");
+
+ // clean up
+ if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) {
+ ALOGE("Couldn't remove stream");
+ }
+ return NO_MEMORY;
+ }
}
}
connection.mSurface = surface;
if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) {
connection.mSurface->setSidebandStream(connection.mSourceHandle);
} else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) {
- connection.mThread->setSurface(surface);
+ if (NO_ERROR != connection.mThread->setSurface(surface))
+ {
+ ALOGE("failed to setSurface");
+ // clean up
+ connection.mThread.clear();
+ if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) {
+ ALOGE("Couldn't remove stream");
+ }
+ if (connection.mSurface != NULL) {
+ connection.mSurface.clear();
+ }
+ return UNKNOWN_ERROR;
+ }
+ connection.mThread->run();
}
return NO_ERROR;
}
@@ -413,13 +408,6 @@ int JTvInputHal::removeStream(int deviceId, int streamId) {
// Nothing to do
return NO_ERROR;
}
- if (Surface::isValid(connection.mSurface)) {
- connection.mSurface.clear();
- }
- if (connection.mSurface != NULL) {
- connection.mSurface->setSidebandStream(NULL);
- connection.mSurface.clear();
- }
if (connection.mThread != NULL) {
connection.mThread->shutdown();
connection.mThread.clear();
@@ -431,6 +419,13 @@ int JTvInputHal::removeStream(int deviceId, int streamId) {
if (connection.mSourceHandle != NULL) {
connection.mSourceHandle.clear();
}
+ if (Surface::isValid(connection.mSurface)) {
+ connection.mSurface.clear();
+ }
+ if (connection.mSurface != NULL) {
+ connection.mSurface->setSidebandStream(NULL);
+ connection.mSurface.clear();
+ }
return NO_ERROR;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index dedf1d9..302d23a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -95,6 +95,7 @@ import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
+import android.security.KeyStore;
import android.service.persistentdata.PersistentDataBlockManager;
import android.text.TextUtils;
import android.util.Log;
@@ -4198,6 +4199,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ @Override
+ public boolean requireSecureKeyguard(int userHandle) {
+ if (!mHasFeature) {
+ return false;
+ }
+
+ int passwordQuality = getPasswordQuality(null, userHandle);
+ if (passwordQuality > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ return true;
+ }
+
+ int encryptionStatus = getStorageEncryptionStatus(userHandle);
+ if (encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
+ || encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING) {
+ return true;
+ }
+ final int keyguardDisabledFeatures = getKeyguardDisabledFeatures(null, userHandle);
+ return (keyguardDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
+ }
+
// Returns the active device owner or null if there is no device owner.
private ActiveAdmin getDeviceOwnerAdmin() {
String deviceOwnerPackageName = getDeviceOwner();
@@ -4236,6 +4257,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mDeviceOwner.clearDeviceOwner();
mDeviceOwner.writeOwnerFile();
updateDeviceOwnerLocked();
+ // Restore backup manager.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ IBackupManager ibm = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ ibm.setBackupServiceActive(UserHandle.USER_OWNER, true);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed activating backup service.", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 08816b9..aa8026b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -25,9 +25,11 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
+import android.database.ContentObserver;
import android.os.Build;
import android.os.Environment;
import android.os.FactoryTest;
@@ -61,6 +63,7 @@ import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
import com.android.server.fingerprint.FingerprintService;
import com.android.server.hdmi.HdmiControlService;
+import com.android.server.gesture.GestureService;
import com.android.server.input.InputManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.lights.LightsService;
@@ -92,6 +95,7 @@ import com.android.server.wallpaper.WallpaperManagerService;
import com.android.server.webkit.WebViewUpdateService;
import com.android.server.wm.WindowManagerService;
+import cyanogenmod.providers.CMSettings;
import dalvik.system.VMRuntime;
import java.io.File;
@@ -173,6 +177,19 @@ public final class SystemServer {
mFactoryTestMode = FactoryTest.getMode();
}
+ private class AdbPortObserver extends ContentObserver {
+ public AdbPortObserver() {
+ super(null);
+ }
+ @Override
+ public void onChange(boolean selfChange) {
+ int adbPort = CMSettings.Secure.getInt(mContentResolver,
+ CMSettings.Secure.ADB_PORT, 0);
+ // setting this will control whether ADB runs on TCP/IP or USB
+ SystemProperties.set("adb.network.port", Integer.toString(adbPort));
+ }
+ }
+
private void run() {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
@@ -438,6 +455,8 @@ public final class SystemServer {
boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false);
boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
+ String[] externalServices = context.getResources()
+ .getStringArray(com.android.internal.R.array.config_externalCMServices);
try {
Slog.i(TAG, "Reading configuration...");
@@ -499,7 +518,7 @@ public final class SystemServer {
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
- !mFirstBoot, mOnlyCore);
+ true, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
@@ -542,6 +561,7 @@ public final class SystemServer {
LockSettingsService lockSettings = null;
AssetAtlasService atlas = null;
MediaRouterService mediaRouter = null;
+ GestureService gestureService = null;
// Bring up services needed for UI.
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
@@ -952,6 +972,17 @@ public final class SystemServer {
new GraphicsStatsService(context));
}
+ if (context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableGestureService)) {
+ try {
+ Slog.i(TAG, "Gesture Sensor Service");
+ gestureService = new GestureService(context, inputManager);
+ ServiceManager.addService("gesture", gestureService);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting Gesture Sensor Service", e);
+ }
+ }
+
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
}
@@ -997,6 +1028,15 @@ public final class SystemServer {
mSystemServiceManager.startService(MediaProjectionManagerService.class);
}
+ // make sure the ADB_ENABLED setting value matches the secure property value
+ CMSettings.Secure.putInt(mContentResolver, CMSettings.Secure.ADB_PORT,
+ Integer.parseInt(SystemProperties.get("service.adb.tcp.port", "-1")));
+
+ // register observer to listen for settings changes
+ mContentResolver.registerContentObserver(
+ CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT),
+ false, new AdbPortObserver());
+
// Before things start rolling, be sure we have decided whether
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
@@ -1012,6 +1052,15 @@ public final class SystemServer {
// MMS service broker
mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
+ for (String service : externalServices) {
+ try {
+ Slog.i(TAG, service);
+ mSystemServiceManager.startService(service);
+ } catch (Throwable e) {
+ reportWtf("starting " + service , e);
+ }
+ }
+
// It is now time to start up the app processes...
try {
@@ -1078,6 +1127,14 @@ public final class SystemServer {
reportWtf("making Display Manager Service ready", e);
}
+ if (gestureService != null) {
+ try {
+ gestureService.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Gesture Sensor Service ready", e);
+ }
+ }
+
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
final NetworkStatsService networkStatsF = networkStats;
@@ -1120,6 +1177,15 @@ public final class SystemServer {
Slog.i(TAG, "WebViewFactory preparation");
WebViewFactory.prepareWebViewInSystemServer();
+ // Start Nfc before SystemUi to ensure NfcTile and other apps gets a
+ // valid NfcAdapter from NfcManager
+ try {
+ startNfcService(context);
+ } catch (Throwable e) {
+ // Don't crash. Nfc is an optional service. Just annotate that isn't ready
+ Slog.e(TAG, "Nfc service didn't start. Nfc will not be available.", e);
+ }
+
try {
startSystemUi(context);
} catch (Throwable e) {
@@ -1238,4 +1304,23 @@ public final class SystemServer {
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.OWNER);
}
+
+ static final void startNfcService(Context context) {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ if (pm == null) {
+ Slog.w(TAG, "Cannot get package manager, assuming no NFC feature");
+ return;
+ }
+ try {
+ if (pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName("com.android.nfc",
+ "com.android.nfc.NfcBootstrapService"));
+ context.startServiceAsUser(intent, UserHandle.OWNER);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Package manager query failed, assuming no NFC feature", e);
+ return;
+ }
+ }
}
diff --git a/services/libtvextensions/Android.mk b/services/libtvextensions/Android.mk
new file mode 100644
index 0000000..0a9e9bf
--- /dev/null
+++ b/services/libtvextensions/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ jni/TvInputHalFactory.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/services/libtvextensions \
+
+LOCAL_CFLAGS += -Wno-multichar
+
+ifeq ($(TARGET_ENABLE_QC_TVINPUT_HAL_EXTENSIONS),true)
+ LOCAL_CFLAGS += -DENABLE_TVINPUT_HAL_EXTENSIONS
+endif
+
+LOCAL_MODULE:= libTvInputHalExtensions
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/services/libtvextensions/common/ExtensionsLoader.hpp b/services/libtvextensions/common/ExtensionsLoader.hpp
new file mode 100644
index 0000000..010e614
--- /dev/null
+++ b/services/libtvextensions/common/ExtensionsLoader.hpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <dlfcn.h>
+#include <common/TvInputHalExtensionsCommon.h>
+
+namespace android {
+
+/*
+ * Create strongly-typed objects of type T
+ * If the customization library exists and does contain a "named" constructor,
+ * invoke and create an instance
+ * Else create the object of type T itself
+ *
+ * Contains a static instance to dlopen'd library, But may end up
+ * opening the library mutiple times. Following snip from dlopen man page is
+ * reassuring "...Only a single copy of an object file is brought into the
+ * address space, even if dlopen() is invoked multiple times in reference to
+ * the file, and even if different pathnames are used to reference the file.."
+ */
+
+template <typename T>
+T *ExtensionsLoader<T>::createInstance(const char *createFunctionName) {
+ ALOGV("createInstance(%dbit) : %s", sizeof(intptr_t)*8, createFunctionName);
+ // create extended object if extensions-lib is available and
+ // TVINPUT_HAL_EXTENSIONS is enabled
+#if ENABLE_TVINPUT_HAL_EXTENSIONS
+ createFunction_t createFunc = loadCreateFunction(createFunctionName);
+ if (createFunc) {
+ return reinterpret_cast<T *>((*createFunc)());
+ }
+#endif
+ // Else, create the default object
+ return new T;
+}
+
+template <typename T>
+void ExtensionsLoader<T>::loadLib() {
+ if (!mLibHandle) {
+ mLibHandle = ::dlopen(CUSTOMIZATION_LIB_NAME, RTLD_LAZY);
+ if (!mLibHandle) {
+ ALOGV("%s", dlerror());
+ return;
+ }
+ ALOGV("Opened %s", CUSTOMIZATION_LIB_NAME);
+ }
+}
+
+template <typename T>
+createFunction_t ExtensionsLoader<T>::loadCreateFunction(const char *createFunctionName) {
+ loadLib();
+ if (!mLibHandle) {
+ return NULL;
+ }
+ createFunction_t func = (createFunction_t)dlsym(mLibHandle, createFunctionName);
+ if (!func) {
+ ALOGW("symbol %s not found: %s",createFunctionName, dlerror());
+ }
+ return func;
+}
+
+//static
+template <typename T>
+void *ExtensionsLoader<T>::mLibHandle = NULL;
+
+} //namespace android
diff --git a/services/libtvextensions/common/TvInputHalExtensionsCommon.h b/services/libtvextensions/common/TvInputHalExtensionsCommon.h
new file mode 100644
index 0000000..3db4c7b
--- /dev/null
+++ b/services/libtvextensions/common/TvInputHalExtensionsCommon.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _TVINPUTHAL_EXTENSIONS_COMMON_H_
+#define _TVINPUTHAL_EXTENSIONS_COMMON_H_
+
+namespace android {
+
+static const char * CUSTOMIZATION_LIB_NAME = "libTvInputHalEnhancements.so";
+
+typedef void *(*createFunction_t)(void);
+
+template <typename T>
+struct ExtensionsLoader {
+
+ static T *createInstance(const char *createFunctionName);
+
+private:
+ static void loadLib();
+ static createFunction_t loadCreateFunction(const char *createFunctionName);
+ static void *mLibHandle;
+};
+
+/*
+ * Boiler-plate to declare the class as a singleton (with a static getter)
+ * which can be loaded (dlopen'd) via ExtensionsLoader
+ */
+#define DECLARE_LOADABLE_SINGLETON(className) \
+protected: \
+ className(); \
+ virtual ~className(); \
+ static className *sInst; \
+private: \
+ className(const className&); \
+ className &operator=(className &); \
+public: \
+ static className *get() { \
+ return sInst; \
+ } \
+ friend struct ExtensionsLoader<className>;
+
+} //namespace android
+
+#endif // _TVINPUTHAL_EXTENSIONS_COMMON_H_
diff --git a/services/libtvextensions/jni/BufferProducerThread.h b/services/libtvextensions/jni/BufferProducerThread.h
new file mode 100644
index 0000000..6699edc
--- /dev/null
+++ b/services/libtvextensions/jni/BufferProducerThread.h
@@ -0,0 +1,89 @@
+/* Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Not a contribution.
+ */
+/*
+ * Copyright 2014 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 TVINPUT_HAL_INTERFACE_H_
+#define TVINPUT_HAL_INTERFACE_H_
+
+#include "jni.h"
+
+#include <gui/Surface.h>
+#include <hardware/tv_input.h>
+
+namespace android {
+
+class BufferProducerThread : public Thread {
+public:
+ BufferProducerThread(tv_input_device_t* device, int deviceId, const tv_stream_t* stream);
+
+ virtual status_t readyToRun();
+
+ virtual int setSurface(const sp<Surface>& surface);
+ virtual void onCaptured(uint32_t seq, bool succeeded);
+ virtual void shutdown();
+
+protected:
+ Mutex mLock;
+ Condition mCondition;
+ sp<Surface> mSurface;
+ tv_input_device_t* mDevice;
+ int mDeviceId;
+ tv_stream_t mStream;
+ sp<ANativeWindowBuffer_t> mBuffer;
+ enum {
+ CAPTURING,
+ CAPTURED,
+ RELEASED,
+ } mBufferState;
+ uint32_t mSeq;
+ bool mShutdown;
+
+ virtual bool threadLoop();
+
+ virtual int setSurfaceLocked(const sp<Surface>& surface);
+};
+
+} // namespace android
+
+#endif // TVINPUT_HAL_INTERFACE_H_
diff --git a/services/libtvextensions/jni/TvInputHalExtensions.h b/services/libtvextensions/jni/TvInputHalExtensions.h
new file mode 100644
index 0000000..479e544
--- /dev/null
+++ b/services/libtvextensions/jni/TvInputHalExtensions.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _TVINPUTHAL_EXTENSIONS_H_
+#define _TVINPUTHAL_EXTENSIONS_H_
+
+#include <utils/RefBase.h>
+#include <common/TvInputHalExtensionsCommon.h>
+#include <jni/BufferProducerThread.h>
+
+namespace android {
+
+class BufferProducerThread;
+
+/*
+ * Factory to create objects of base-classes in libstagefright
+ */
+struct TvInputHalFactory {
+ virtual sp<BufferProducerThread> createBufferProducerThread(tv_input_device_t* device,
+ int deviceId,
+ const tv_stream_t* stream);
+
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(TvInputHalFactory);
+};
+
+}
+
+#endif // _TVINPUTHAL_EXTENSIONS_H_
diff --git a/services/libtvextensions/jni/TvInputHalFactory.cpp b/services/libtvextensions/jni/TvInputHalFactory.cpp
new file mode 100644
index 0000000..b752066
--- /dev/null
+++ b/services/libtvextensions/jni/TvInputHalFactory.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "TvInputHalFactory"
+#include <utils/Log.h>
+
+#include "common/ExtensionsLoader.hpp"
+#include "jni/TvInputHalExtensions.h"
+
+namespace android {
+
+ sp<BufferProducerThread> TvInputHalFactory::createBufferProducerThread(tv_input_device_t* device,
+ int deviceId,
+ const tv_stream_t* stream) {
+ return new BufferProducerThread(device, deviceId, stream);
+}
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+TvInputHalFactory::TvInputHalFactory() {
+}
+
+TvInputHalFactory::~TvInputHalFactory() {
+}
+
+//static
+TvInputHalFactory *TvInputHalFactory::sInst =
+ ExtensionsLoader<TvInputHalFactory>::createInstance("createExtendedFactory");
+
+} //namespace android
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index ed1db6f..9c44c7a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -23,15 +23,27 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import android.content.Context;
import android.content.pm.PackageParser;
+import android.content.res.AssetManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.SystemProperties;
import android.test.AndroidTestCase;
+import android.test.mock.MockContext;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LongSparseArray;
import com.android.internal.os.AtomicFile;
import java.lang.reflect.Constructor;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import com.android.internal.R;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -160,6 +172,12 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
folder.delete();
}
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+ }
+
private void writeOldFiles() {
deleteSystemFolder();
writePackagesXml();
@@ -245,7 +263,7 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
writeOldFiles();
createUserManagerServiceRef();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
verifyKeySetMetaData(settings);
}
@@ -257,11 +275,11 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
writeOldFiles();
createUserManagerServiceRef();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
/* write out, read back in and verify the same */
settings.writeLPr();
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
verifyKeySetMetaData(settings);
}
@@ -269,7 +287,7 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
@@ -289,12 +307,12 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
writeOldFiles();
createUserManagerServiceRef();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
settings.writeLPr();
// Create Settings again to make it read from the new files
settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
@@ -305,7 +323,7 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(null, null, 0, false, null));
// Enable/Disable a package
PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
@@ -335,4 +353,38 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
hasEnabled = ps.getEnabledComponents(0) != null && ps.getEnabledComponents(0).size() > 0;
assertEquals(false, hasEnabled);
}
+
+ // Checks if a package that is locked to a different region is rejected
+ // from being installed
+ public void testPrebundledDifferentRegionReject() {
+ Settings settings = new Settings(getContext().getFilesDir());
+ String expectedPackageNeededForRegion = "org.cyanogenmod.restricted.package";
+ Resources resources = Mockito.mock(Resources.class);
+ String[] regionRestrictedPackages = new String[] {
+ expectedPackageNeededForRegion
+ };
+ Mockito.when(resources.getStringArray(R.array.config_restrict_to_region_locked_devices))
+ .thenReturn(regionRestrictedPackages);
+ assertFalse(settings.shouldPrebundledPackageBeInstalled(resources,
+ expectedPackageNeededForRegion, resources));
+ }
+
+ // Checks if a package that is locked to the current region is accepted
+ // This also covers the test for a package that needs to be installed on a
+ // non region locked device
+ public void testPrebundledMatchingRegionAccept() {
+ Settings settings = new Settings(getContext().getFilesDir());
+ String expectedPackageNeededForRegion = "org.cyanogenmod.restricted.package";
+ Resources resources = Mockito.mock(Resources.class);
+ String[] regionLockedPackages = new String[] {
+ expectedPackageNeededForRegion
+ };
+ Mockito.when(resources.getStringArray(R.array.config_region_locked_packages))
+ .thenReturn(regionLockedPackages);
+
+ Mockito.when(resources.getStringArray(R.array.config_restrict_to_region_locked_devices))
+ .thenReturn(regionLockedPackages);
+ assertTrue(settings.shouldPrebundledPackageBeInstalled(resources,
+ expectedPackageNeededForRegion, resources));
+ }
}
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
index feabf0a..2a9c382 100644
--- a/services/usb/Android.mk
+++ b/services/usb/Android.mk
@@ -9,4 +9,6 @@ LOCAL_SRC_FILES += \
LOCAL_JAVA_LIBRARIES := services.core
+LOCAL_JAVA_LIBRARIES += org.cyanogenmod.platform.internal
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 31763e7..701272e 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -439,7 +439,7 @@ public final class UsbAlsaManager {
UsbAudioDevice audioDevice = mAudioDevices.remove(usbDevice);
if (audioDevice != null) {
- if (audioDevice.mHasPlayback || audioDevice.mHasPlayback) {
+ if (audioDevice.mHasPlayback || audioDevice.mHasCapture) {
notifyDeviceState(audioDevice, false);
// if there any external devices left, select one of them
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 81ca6a3..3fecfb6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -32,6 +32,7 @@ import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
+import android.os.Binder;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -52,6 +53,15 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
+import cyanogenmod.providers.CMSettings;
+
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -161,6 +171,13 @@ public class UsbDeviceManager {
}
}
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ mHandler.processQSChangedLocked();
+ }
+ };
+
/*
* Listens for uevent messages from the kernel to monitor the USB state
*/
@@ -323,7 +340,7 @@ public class UsbDeviceManager {
private boolean mCurrentFunctionsApplied;
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
- private boolean mAdbNotificationShown;
+ private int mAdbNotificationId;
private int mCurrentUser = UserHandle.USER_NULL;
public UsbHandler(Looper looper) {
@@ -349,9 +366,25 @@ public class UsbDeviceManager {
Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
false, new AdbSettingsObserver());
+ ContentObserver adbNotificationObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateAdbNotification();
+ }
+ };
+
+ mContentResolver.registerContentObserver(
+ CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT),
+ false, adbNotificationObserver);
+ mContentResolver.registerContentObserver(
+ CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_NOTIFY),
+ false, adbNotificationObserver);
+
// Watch for USB configuration changes
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+
+ QSUtils.registerObserverForQSChanges(mContext, mQSListener);
} catch (Exception e) {
Slog.e(TAG, "Error initializing UsbHandler", e);
}
@@ -795,15 +828,35 @@ public class UsbDeviceManager {
private void updateAdbNotification() {
if (mNotificationManager == null) return;
- final int id = com.android.internal.R.string.adb_active_notification_title;
- if (mAdbEnabled && mConnected) {
- if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
+ final int id;
+ boolean usbAdbActive = mAdbEnabled && mConnected;
+ boolean netAdbActive = mAdbEnabled &&
+ CMSettings.Secure.getInt(mContentResolver, CMSettings.Secure.ADB_PORT, -1) > 0;
+ boolean hideNotification = "0".equals(SystemProperties.get("persist.adb.notify"))
+ || CMSettings.Secure.getInt(mContext.getContentResolver(),
+ CMSettings.Secure.ADB_NOTIFY, 1) == 0;
+
+ if (hideNotification) {
+ id = 0;
+ } else if (usbAdbActive && netAdbActive) {
+ id = com.android.internal.R.string.adb_both_active_notification_title;
+ } else if (usbAdbActive) {
+ id = com.android.internal.R.string.adb_active_notification_title;
+ } else if (netAdbActive) {
+ id = com.android.internal.R.string.adb_net_active_notification_title;
+ } else {
+ id = 0;
+ }
- if (!mAdbNotificationShown) {
+ if (id != mAdbNotificationId) {
+ if (mAdbNotificationId != 0) {
+ mNotificationManager.cancelAsUser(null, mAdbNotificationId, UserHandle.ALL);
+ }
+ if (id != 0) {
Resources r = mContext.getResources();
CharSequence title = r.getText(id);
CharSequence message = r.getText(
- com.android.internal.R.string.adb_active_notification_message);
+ com.android.internal.R.string.adb_active_generic_notification_message);
Intent intent = Intent.makeRestartActivityTask(
new ComponentName("com.android.settings",
@@ -825,13 +878,17 @@ public class UsbDeviceManager {
.setContentIntent(pi)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.build();
- mAdbNotificationShown = true;
+
mNotificationManager.notifyAsUser(null, id, notification,
UserHandle.ALL);
}
- } else if (mAdbNotificationShown) {
- mAdbNotificationShown = false;
- mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
+ mAdbNotificationId = id;
+ }
+
+ if (id > 0) {
+ publishAdbCustomTile();
+ } else {
+ unpublishAdbCustomTile();
}
}
@@ -861,6 +918,88 @@ public class UsbDeviceManager {
pw.println("IOException: " + e);
}
}
+
+ private void publishAdbCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = new UserHandle(userId);
+ final int icon = QSUtils.getDynamicQSTileResIconId(mContext, userId,
+ QSConstants.DYNAMIC_TILE_ADB);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(mContext, userId,
+ QSConstants.DYNAMIC_TILE_ADB);
+ final Context resourceContext = QSUtils.getQSTileContext(mContext, userId);
+
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(getAdbCustomTileLabel())
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setOnClickIntent(getCustomTilePendingIntent())
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_ADB,
+ UsbDeviceManager.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishAdbCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_ADB,
+ UsbDeviceManager.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private PendingIntent getCustomTilePendingIntent() {
+ Intent i = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return PendingIntent.getActivity(mContext, 0, i, PendingIntent.FLAG_UPDATE_CURRENT, null);
+ }
+
+ private String getAdbCustomTileLabel() {
+ boolean usbAdbActive = mAdbEnabled && mConnected;
+ boolean netAdbActive = mAdbEnabled &&
+ CMSettings.Secure.getInt(mContentResolver, CMSettings.Secure.ADB_PORT, -1) > 0;
+
+ int id = 0;
+ if (usbAdbActive && netAdbActive) {
+ id = com.android.internal.R.string.adb_active_custom_tile_both;
+ } else if (usbAdbActive) {
+ id = com.android.internal.R.string.adb_active_custom_tile_usb;
+ } else if (netAdbActive) {
+ id = com.android.internal.R.string.adb_active_custom_tile_net;
+ }
+
+ Resources res = mContext.getResources();
+ return res.getString(
+ com.android.internal.R.string.adb_active_custom_tile,
+ res.getString(id));
+ }
+
+ private void processQSChangedLocked() {
+ final int userId = UserHandle.myUserId();
+ boolean usbAdbActive = mAdbEnabled && mConnected;
+ boolean netAdbActive = mAdbEnabled &&
+ CMSettings.Secure.getInt(mContentResolver, CMSettings.Secure.ADB_PORT, -1) > 0;
+ boolean notifEnabled = "1".equals(SystemProperties.get("persist.adb.notify"))
+ || CMSettings.Secure.getInt(mContext.getContentResolver(),
+ CMSettings.Secure.ADB_NOTIFY, 1) == 1;
+ boolean isActive = notifEnabled && (usbAdbActive || netAdbActive);
+ boolean enabled = (userId == UserHandle.USER_OWNER) && isActive;
+ if (enabled) {
+ publishAdbCustomTile();
+ } else {
+ unpublishAdbCustomTile();
+ }
+ }
}
/* returns the currently attached USB accessory */
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 2cf42f0..674952c 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -739,7 +739,7 @@ class UsbSettingsManager {
}
// Send broadcast to running activity with registered intent
- mUserContext.sendBroadcast(intent);
+ mUserContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// Start activity with registered intent
resolveActivity(intent, matches, defaultPackage, device, null);
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 6511705..8af52f2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -207,13 +207,43 @@ public final class Call {
public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
/**
+ * Call has voice privacy capability.
+ * @hide
+ */
+ public static final int CAPABILITY_VOICE_PRIVACY = 0x00400000;
+
+ /**
+ * Local device supports downgrading a video call to a voice-only call.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00800000;
+
+ /**
+ * Remote device supports downgrading a video call to a voice-only call.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x01000000;
+
+ /**
+ * Add participant in an active or conference call option
+ * @hide
+ */
+ public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
+
+ /**
+ * Remote device supports call transfers.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_TRANSFER = 0x04000000;
+
+ /**
* Call sends responses through connection.
* @hide
*/
- public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00400000;
+ public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x08000000;
//******************************************************************************************
- // Next CAPABILITY value: 0x00800000
+ // Next CAPABILITY value: 0x10000000
//******************************************************************************************
/**
@@ -242,8 +272,38 @@ public final class Call {
*/
public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
+ /**
+ * Whether the call was forwarded from another party (GSM only)
+ * @hide
+ */
+ public static final int PROPERTY_WAS_FORWARDED = 0x00000020;
+
+ /**
+ * Whether the call is held remotely
+ * @hide
+ */
+ public static final int PROPERTY_HELD_REMOTELY = 0x00000040;
+
+ /**
+ * Whether the dialing state is waiting for the busy remote side
+ * @hide
+ */
+ public static final int PROPERTY_DIALING_IS_WAITING = 0x00000080;
+
+ /**
+ * Whether an additional call came in and was forwarded while the call was active
+ * @hide
+ */
+ public static final int PROPERTY_ADDITIONAL_CALL_FORWARDED = 0x00000100;
+
+ /**
+ * Whether incoming calls are barred at the remote side
+ * @hide
+ */
+ public static final int PROPERTY_REMOTE_INCOMING_CALLS_BARRED = 0x00000200;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00000020
+ // Next PROPERTY value: 0x00000400
//******************************************************************************************
private final Uri mHandle;
@@ -254,6 +314,7 @@ public final class Call {
private final int mCallCapabilities;
private final int mCallProperties;
private final DisconnectCause mDisconnectCause;
+ private final long mCreateTimeMillis;
private final long mConnectTimeMillis;
private final GatewayInfo mGatewayInfo;
private final int mVideoState;
@@ -327,6 +388,12 @@ public final class Call {
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
}
+ if (can(capabilities, CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL)) {
+ builder.append(" CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE)) {
+ builder.append(" CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE");
+ }
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
}
@@ -339,6 +406,15 @@ public final class Call {
if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
}
+ if (can(capabilities, CAPABILITY_VOICE_PRIVACY)) {
+ builder.append(" CAPABILITY_VOICE_PRIVACY");
+ }
+ if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
+ builder.append(" CAPABILITY_ADD_PARTICIPANT");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_TRANSFER)) {
+ builder.append(" CAPABILITY_SUPPORTS_TRANSFER");
+ }
builder.append("]");
return builder.toString();
}
@@ -388,6 +464,22 @@ public final class Call {
if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
}
+ if (hasProperty(properties, PROPERTY_WAS_FORWARDED)) {
+ builder.append(" PROPERTY_WAS_FORWARDED");
+ }
+ if (hasProperty(properties, PROPERTY_HELD_REMOTELY)) {
+ builder.append(" PROPERTY_HELD_REMOTELY");
+ }
+ if (hasProperty(properties, PROPERTY_DIALING_IS_WAITING)) {
+ builder.append(" PROPERTY_DIALING_IS_WAITING");
+ }
+ if (hasProperty(properties, PROPERTY_ADDITIONAL_CALL_FORWARDED)) {
+ builder.append(" PROPERTY_ADDITIONAL_CALL_FORWARDED");
+ }
+ if (hasProperty(properties, PROPERTY_REMOTE_INCOMING_CALLS_BARRED)) {
+ builder.append(" PROPERTY_REMOTE_INCOMING_CALLS_BARRED");
+ }
+
builder.append("]");
return builder.toString();
}
@@ -465,6 +557,14 @@ public final class Call {
}
/**
+ * @return the time the Call object was created
+ * {@hide}
+ */
+ public long getCreateTimeMillis() {
+ return mCreateTimeMillis;
+ }
+
+ /**
* @return Information about any calling gateway the {@code Call} may be using.
*/
public GatewayInfo getGatewayInfo() {
@@ -514,6 +614,7 @@ public final class Call {
Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Objects.equals(mCallProperties, d.mCallProperties) &&
Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
+ Objects.equals(mCreateTimeMillis, d.mCreateTimeMillis) &&
Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Objects.equals(mVideoState, d.mVideoState) &&
@@ -535,6 +636,7 @@ public final class Call {
Objects.hashCode(mCallCapabilities) +
Objects.hashCode(mCallProperties) +
Objects.hashCode(mDisconnectCause) +
+ Objects.hashCode(mCreateTimeMillis) +
Objects.hashCode(mConnectTimeMillis) +
Objects.hashCode(mGatewayInfo) +
Objects.hashCode(mVideoState) +
@@ -553,6 +655,7 @@ public final class Call {
int capabilities,
int properties,
DisconnectCause disconnectCause,
+ long createTimeMillis,
long connectTimeMillis,
GatewayInfo gatewayInfo,
int videoState,
@@ -567,6 +670,7 @@ public final class Call {
mCallCapabilities = capabilities;
mCallProperties = properties;
mDisconnectCause = disconnectCause;
+ mCreateTimeMillis = createTimeMillis;
mConnectTimeMillis = connectTimeMillis;
mGatewayInfo = gatewayInfo;
mVideoState = videoState;
@@ -688,6 +792,28 @@ public final class Call {
private Details mDetails;
/**
+ * when mIsActiveSub True indicates this call belongs to active subscription
+ * Calls belonging to active subscription are shown to user.
+ */
+ private boolean mIsActiveSub = false;
+
+ /**
+ * Set this call object as active subscription.
+ * @hide
+ */
+ public void setActive() {
+ mIsActiveSub = true;
+ }
+
+ /**
+ * return if this call object belongs to active subscription.
+ * @hide
+ */
+ public boolean isActive() {
+ return mIsActiveSub;
+ }
+
+ /**
* Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
*
* @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
@@ -817,6 +943,15 @@ public final class Call {
}
/**
+ * Instructs this {@code Call} to connect the current active call and the call on hold.
+ * The current call will then disconnect. See {@link Details#CAPABILITY_SUPPORTS_TRANSFER}.
+ * @hide
+ */
+ public void transferCall() {
+ mInCallAdapter.transferCall(mTelecomCallId);
+ }
+
+ /**
* Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
*/
public void swapConference() {
@@ -977,11 +1112,22 @@ public final class Call {
}
/** {@hide} */
- Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter) {
+ Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, boolean isActiveSub) {
mPhone = phone;
mTelecomCallId = telecomCallId;
mInCallAdapter = inCallAdapter;
mState = STATE_NEW;
+ mIsActiveSub = isActiveSub;
+ }
+
+ /** {@hide} */
+ Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
+ boolean isActiveSub) {
+ mPhone = phone;
+ mTelecomCallId = telecomCallId;
+ mInCallAdapter = inCallAdapter;
+ mState = state;
+ mIsActiveSub = isActiveSub;
}
/** {@hide} */
@@ -1009,6 +1155,7 @@ public final class Call {
parcelableCall.getCapabilities(),
parcelableCall.getProperties(),
parcelableCall.getDisconnectCause(),
+ parcelableCall.getCreateTimeMillis(),
parcelableCall.getConnectTimeMillis(),
parcelableCall.getGatewayInfo(),
parcelableCall.getVideoState(),
@@ -1034,9 +1181,10 @@ public final class Call {
}
int state = parcelableCall.getState();
- boolean stateChanged = mState != state;
+ boolean stateChanged = (mState != state) || (mIsActiveSub != parcelableCall.isActive());
if (stateChanged) {
mState = state;
+ mIsActiveSub = parcelableCall.isActive();
}
String parentId = parcelableCall.getParentCallId();
@@ -1113,6 +1261,11 @@ public final class Call {
}
}
+ /** {@hide} */
+ final void onMergeFailed() {
+ fireStateChanged(mState);
+ }
+
private void fireStateChanged(final int newState) {
for (CallbackRecord<Callback> record : mCallbackRecords) {
final Call call = this;
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 77fdb65..046e615 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -51,6 +51,8 @@ public abstract class Conference extends Conferenceable {
public void onDestroyed(Conference conference) {}
public void onConnectionCapabilitiesChanged(
Conference conference, int connectionCapabilities) {}
+ public void onConnectionPropertiesChanged(
+ Conference conference, int connectionProperties) {}
public void onVideoStateChanged(Conference c, int videoState) { }
public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {}
public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {}
@@ -70,6 +72,7 @@ public abstract class Conference extends Conferenceable {
private int mState = Connection.STATE_NEW;
private DisconnectCause mDisconnectCause;
private int mConnectionCapabilities;
+ private int mConnectionProperties;
private String mDisconnectMessage;
private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED;
private StatusHints mStatusHints;
@@ -160,7 +163,10 @@ public abstract class Conference extends Conferenceable {
* @hide
*/
public void removeCapability(int capability) {
- mConnectionCapabilities &= ~capability;
+ int newCapabilities = mConnectionCapabilities;
+ newCapabilities &= ~capability;
+
+ setConnectionCapabilities(newCapabilities);
}
/**
@@ -170,7 +176,36 @@ public abstract class Conference extends Conferenceable {
* @hide
*/
public void addCapability(int capability) {
- mConnectionCapabilities |= capability;
+ int newCapabilities = mConnectionCapabilities;
+ newCapabilities |= capability;
+
+ setConnectionCapabilities(newCapabilities);
+ }
+
+ /**
+ * Returns a bit mask of this conference's properties. See the {@code PROPERTY_*} constants
+ * in the {@link Connection} class.
+ * @hide
+ */
+ public final int getConnectionProperties() {
+ return mConnectionProperties;
+ }
+
+
+ /**
+ * Sets this conference's properties as a bit mask of the {@code PROPERTY_*} constants
+ * in the {@link Connection} class.
+ *
+ * @param connectionProperties The new connection properties.
+ * @hide
+ */
+ public final void setConnectionProperties(int connectionProperties) {
+ if (mConnectionProperties != connectionProperties) {
+ mConnectionProperties = connectionProperties;
+ for (Listener l : mListeners) {
+ l.onConnectionPropertiesChanged(this, mConnectionProperties);
+ }
+ }
}
/**
@@ -222,6 +257,14 @@ public abstract class Conference extends Conferenceable {
public void onSeparate(Connection connection) {}
/**
+ * Invoked when the conference adds a participant to the conference call.
+ *
+ * @param participant The participant to be added with conference call.
+ * @hide
+ */
+ public void onAddParticipant(String participant) {}
+
+ /**
* Invoked when the specified {@link Connection} should merged with the conference call.
*
* @param connection The {@code Connection} to merge.
@@ -559,6 +602,7 @@ public abstract class Conference extends Conferenceable {
private void setState(int newState) {
if (newState != Connection.STATE_ACTIVE &&
+ newState != Connection.STATE_DIALING &&
newState != Connection.STATE_HOLDING &&
newState != Connection.STATE_DISCONNECTED) {
Log.w(this, "Unsupported state transition for Conference call.",
@@ -585,9 +629,11 @@ public abstract class Conference extends Conferenceable {
@Override
public String toString() {
return String.format(Locale.US,
- "[State: %s,Capabilites: %s, VideoState: %s, VideoProvider: %s, ThisObject %s]",
+ "[State: %s, Capabilites: %s, Properties: %s, " +
+ "VideoState: %s, VideoProvider: %s, ThisObject %s]",
Connection.stateToString(mState),
Call.Details.capabilitiesToString(mConnectionCapabilities),
+ Call.Details.propertiesToString(mConnectionProperties),
getVideoState(),
getVideoProvider(),
super.toString());
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 520a1d7..5e2ec3c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -227,6 +227,13 @@ public abstract class Connection extends Conferenceable {
public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
/**
+ * Add participant in an active or conference call option
+ *
+ * @hide
+ */
+ public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
+
+ /**
* For a conference, indicates the conference will not have child connections.
* <p>
* An example of a conference with child connections is a GSM conference call, where the radio
@@ -247,6 +254,29 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000;
+ /**
+ * Call has voice privacy capability.
+ * @hide
+ */
+ public static final int CAPABILITY_VOICE_PRIVACY = 0x00400000;
+
+ /**
+ * Local device supports voice telephony.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00800000;
+
+ /**
+ * Remote device supports voice telephony.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x01000000;
+
+ /**
+ * Remote device supports call transfers.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_TRANSFER = 0x04000000;
/**
* Indicates that the connection itself wants to handle any sort of reply response, rather than
@@ -260,6 +290,40 @@ public abstract class Connection extends Conferenceable {
//**********************************************************************************************
/**
+ * Whether the call was forwarded from another party (GSM only)
+ * @hide
+ */
+ public static final int PROPERTY_WAS_FORWARDED = 0x00000001;
+
+ /**
+ * Whether the call is held remotely
+ * @hide
+ */
+ public static final int PROPERTY_HELD_REMOTELY = 0x00000002;
+
+ /**
+ * Whether the dialing state is waiting for the busy remote side
+ * @hide
+ */
+ public static final int PROPERTY_DIALING_IS_WAITING = 0x00000004;
+
+ /**
+ * Whether an additional call came in and was forwarded while the call was active
+ * @hide
+ */
+ public static final int PROPERTY_ADDITIONAL_CALL_FORWARDED = 0x00000008;
+
+ /**
+ * Whether incoming calls are barred at the remote side
+ * @hide
+ */
+ public static final int PROPERTY_REMOTE_INCOMING_CALLS_BARRED = 0x00000010;
+
+ //******************************************************************************************
+ // Next PROPERTY value: 0x00000020
+ //******************************************************************************************
+
+ /**
* Connection extra key used to store the last forwarded number associated with the current
* connection. Used to communicate to the user interface that the connection was forwarded via
* the specified number.
@@ -282,6 +346,13 @@ public abstract class Connection extends Conferenceable {
*/
public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
+ /**
+ * Call extras key to pack/unpack call history info.
+ * The value for this key should be an ArrayList of Strings.
+ * @hide
+ */
+ public static final String EXTRA_CALL_HISTORY_INFO = "EXTRA_CALL_HISTORY_INFO";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -328,7 +399,6 @@ public abstract class Connection extends Conferenceable {
mConnectionCapabilities |= capability;
}
-
public static String capabilitiesToString(int capabilities) {
StringBuilder builder = new StringBuilder();
builder.append("[Capabilities:");
@@ -371,6 +441,12 @@ public abstract class Connection extends Conferenceable {
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
}
+ if (can(capabilities, CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL)) {
+ builder.append(" CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE)) {
+ builder.append(" CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE");
+ }
if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) {
builder.append(" CAPABILITY_HIGH_DEF_AUDIO");
}
@@ -403,6 +479,75 @@ public abstract class Connection extends Conferenceable {
return builder.toString();
}
+ /**
+ * Whether the given properties include the specified property.
+ *
+ * @param properties A property bit field.
+ * @param property The property to check properties for.
+ * @return Whether the specified property is present.
+ * @hide
+ */
+ public static boolean hasProperty(int properties, int property) {
+ return (properties & property) != 0;
+ }
+
+ /**
+ * Whether the properties of this {@code Connection} include the specified property.
+ *
+ * @param property The property to look for.
+ * @return Whether the specified property is present.
+ * @hide
+ */
+ public boolean hasProperty(int property) {
+ return hasProperty(mConnectionProperties, property);
+ }
+
+ /**
+ * Removes the specified property from the set of properties of this {@code Connection}.
+ *
+ * @param property The property to remove from the set.
+ * @hide
+ */
+ public void removeProperty(int property) {
+ mConnectionProperties &= ~property;
+ }
+
+ /**
+ * Adds the specified property to the set of propertes of this {@code Connection}.
+ *
+ * @param property The property to add to the set.
+ * @hide
+ */
+ public void addProperty(int property) {
+ mConnectionProperties |= property;
+ }
+
+ /**
+ * @hide
+ */
+ public static String propertiesToString(int properties) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[Properties:");
+
+ if (hasProperty(properties, PROPERTY_WAS_FORWARDED)) {
+ builder.append(" PROPERTY_WAS_FORWARDED");
+ }
+ if (hasProperty(properties, PROPERTY_HELD_REMOTELY)) {
+ builder.append(" PROPERTY_HELD_REMOTELY");
+ }
+ if (hasProperty(properties, PROPERTY_DIALING_IS_WAITING)) {
+ builder.append(" PROPERTY_DIALING_IS_WAITING");
+ }
+ if (hasProperty(properties, PROPERTY_ADDITIONAL_CALL_FORWARDED)) {
+ builder.append(" PROPERTY_ADDITIONAL_CALL_FORWARDED");
+ }
+ if (hasProperty(properties, PROPERTY_REMOTE_INCOMING_CALLS_BARRED)) {
+ builder.append(" PROPERTY_REMOTE_INCOMING_CALLS_BARRED");
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+
/** @hide */
public abstract static class Listener {
public void onStateChanged(Connection c, int state) {}
@@ -416,6 +561,7 @@ public abstract class Connection extends Conferenceable {
public void onRingbackRequested(Connection c, boolean ringback) {}
public void onDestroyed(Connection c) {}
public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {}
+ public void onConnectionPropertiesChanged(Connection c, int properties) {}
public void onVideoProviderChanged(
Connection c, VideoProvider videoProvider) {}
public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
@@ -429,6 +575,7 @@ public abstract class Connection extends Conferenceable {
public void onConferenceStarted() {}
public void onConferenceMergeFailed(Connection c) {}
public void onExtrasChanged(Connection c, Bundle extras) {}
+ public void onCdmaConnectionTimeReset(Connection c) {}
}
/**
@@ -1082,6 +1229,7 @@ public abstract class Connection extends Conferenceable {
private int mCallerDisplayNamePresentation;
private boolean mRingbackRequested = false;
private int mConnectionCapabilities;
+ private int mConnectionProperties;
private VideoProvider mVideoProvider;
private boolean mAudioModeIsVoip;
private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
@@ -1306,6 +1454,14 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Returns the connection's properties, as a bit mask of the {@code PROPERTY_*} constants.
+ * @hide
+ */
+ public final int getConnectionProperties() {
+ return mConnectionProperties;
+ }
+
+ /**
* Sets the value of the {@link #getAddress()} property.
*
* @param address The new address.
@@ -1502,6 +1658,22 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Sets the connection's properties as a bit mask of the {@code PROPERTY_*} constants.
+ *
+ * @param connectionProperties The new connection properties.
+ * @hide
+ */
+ public final void setConnectionProperties(int connectionProperties) {
+ checkImmutable();
+ if (mConnectionProperties != connectionProperties) {
+ mConnectionProperties = connectionProperties;
+ for (Listener l : mListeners) {
+ l.onConnectionPropertiesChanged(this, mConnectionProperties);
+ }
+ }
+ }
+
+ /**
* Tears down the Connection object.
*/
public final void destroy() {
@@ -1593,6 +1765,16 @@ public abstract class Connection extends Conferenceable {
}
/**
+ *@hide
+ * Resets the cdma connection time.
+ */
+ public final void resetCdmaConnectionTime() {
+ for (Listener l : mListeners) {
+ l.onCdmaConnectionTimeReset(this);
+ }
+ }
+
+ /**
* Returns the connections or conferences with which this connection can be conferenced.
*/
public final List<Conferenceable> getConferenceables() {
@@ -1718,6 +1900,12 @@ public abstract class Connection extends Conferenceable {
public void onStopDtmfTone() {}
/**
+ * Notifies this to set local call hold.
+ * {@hide}
+ */
+ public void setLocalCallHold(boolean lchState) {}
+
+ /**
* Notifies this Connection of a request to disconnect.
*/
public void onDisconnect() {}
@@ -1774,6 +1962,12 @@ public abstract class Connection extends Conferenceable {
public void onReject() {}
/**
+ * Transfers the current call.
+ * @hide
+ */
+ public void onTransfer() { }
+
+ /**
* Notifies ths Connection of a request reject with a message.
*
* @hide
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 6863214..2e8f8fd 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -28,7 +28,7 @@ import android.os.Parcelable;
public final class ConnectionRequest implements Parcelable {
// TODO: Token to limit recursive invocations
- private final PhoneAccountHandle mAccountHandle;
+ private PhoneAccountHandle mAccountHandle;
private final Uri mAddress;
private final Bundle mExtras;
private final int mVideoState;
@@ -74,6 +74,9 @@ public final class ConnectionRequest implements Parcelable {
*/
public PhoneAccountHandle getAccountHandle() { return mAccountHandle; }
+ /** {@hide} */
+ public void setAccountHandle(PhoneAccountHandle acc) { mAccountHandle = acc; }
+
/**
* The handle (e.g., phone number) to which the {@link Connection} is to connect.
*/
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index ceaa1bf..f64fc99 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -103,6 +103,10 @@ public abstract class ConnectionService extends Service {
private static final int MSG_SWAP_CONFERENCE = 19;
private static final int MSG_REJECT_WITH_MESSAGE = 20;
private static final int MSG_SILENCE = 21;
+ private static final int MSG_SET_LOCAL_HOLD = 22;
+ private static final int MSG_EXPLICIT_TRANSFER = 23;
+ //Proprietary values starts after this.
+ private static final int MSG_ADD_PARTICIPANT_WITH_CONFERENCE = 30;
private static Connection sNullConnection;
@@ -214,6 +218,14 @@ public abstract class ConnectionService extends Service {
}
@Override
+ public void setLocalCallHold(String callId, boolean lchState) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.argi1 = lchState ? 1 : 0;
+ mHandler.obtainMessage(MSG_SET_LOCAL_HOLD, args).sendToTarget();
+ }
+
+ @Override
public void conference(String callId1, String callId2) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId1;
@@ -227,6 +239,14 @@ public abstract class ConnectionService extends Service {
}
@Override
+ public void addParticipantWithConference(String callId, String participant) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = participant;
+ mHandler.obtainMessage(MSG_ADD_PARTICIPANT_WITH_CONFERENCE, args).sendToTarget();
+ }
+
+ @Override
public void mergeConference(String callId) {
mHandler.obtainMessage(MSG_MERGE_CONFERENCE, callId).sendToTarget();
}
@@ -243,6 +263,11 @@ public abstract class ConnectionService extends Service {
args.argi1 = proceed ? 1 : 0;
mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
}
+
+ @Override
+ public void explicitTransfer(String callId) {
+ mHandler.obtainMessage(MSG_EXPLICIT_TRANSFER, callId).sendToTarget();
+ }
};
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -349,6 +374,17 @@ public abstract class ConnectionService extends Service {
case MSG_STOP_DTMF_TONE:
stopDtmfTone((String) msg.obj);
break;
+ case MSG_SET_LOCAL_HOLD: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ String callId = (String) args.arg1;
+ boolean lchStatus = (args.argi1 == 1);
+ setLocalCallHold(callId, lchStatus);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
case MSG_CONFERENCE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
@@ -363,6 +399,17 @@ public abstract class ConnectionService extends Service {
case MSG_SPLIT_FROM_CONFERENCE:
splitFromConference((String) msg.obj);
break;
+ case MSG_ADD_PARTICIPANT_WITH_CONFERENCE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ String callId = (String) args.arg1;
+ String participant = (String) args.arg2;
+ addParticipantWithConference(callId, participant);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
case MSG_MERGE_CONFERENCE:
mergeConference((String) msg.obj);
break;
@@ -380,6 +427,9 @@ public abstract class ConnectionService extends Service {
}
break;
}
+ case MSG_EXPLICIT_TRANSFER:
+ transfer((String) msg.obj);
+ break;
default:
break;
}
@@ -441,6 +491,16 @@ public abstract class ConnectionService extends Service {
}
@Override
+ public void onConnectionPropertiesChanged(
+ Conference conference,
+ int connectionProperties) {
+ String id = mIdByConference.get(conference);
+ Log.d(this, "call properties: conference: %s",
+ Connection.propertiesToString(connectionProperties));
+ mAdapter.setConnectionProperties(id, connectionProperties);
+ }
+
+ @Override
public void onVideoStateChanged(Conference c, int videoState) {
String id = mIdByConference.get(c);
Log.d(this, "onVideoStateChanged set video state %d", videoState);
@@ -557,6 +617,14 @@ public abstract class ConnectionService extends Service {
}
@Override
+ public void onConnectionPropertiesChanged(Connection c, int properties) {
+ String id = mIdByConnection.get(c);
+ Log.d(this, "properties: parcelableconnection: %s",
+ Connection.propertiesToString(properties));
+ mAdapter.setConnectionProperties(id, properties);
+ }
+
+ @Override
public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) {
String id = mIdByConnection.get(c);
Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
@@ -611,6 +679,12 @@ public abstract class ConnectionService extends Service {
mAdapter.setExtras(id, extras);
}
}
+
+ @Override
+ public void onCdmaConnectionTimeReset(Connection c) {
+ String id = mIdByConnection.get(c);
+ mAdapter.resetCdmaConnectionTime(id);
+ }
};
/** {@inheritDoc} */
@@ -656,10 +730,11 @@ public abstract class ConnectionService extends Service {
Uri address = connection.getAddress();
String number = address == null ? "null" : address.getSchemeSpecificPart();
- Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s",
+ Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s, properties: %s",
Connection.toLogSafePhoneNumber(number),
Connection.stateToString(connection.getState()),
- Connection.capabilitiesToString(connection.getConnectionCapabilities()));
+ Connection.capabilitiesToString(connection.getConnectionCapabilities()),
+ Connection.propertiesToString(connection.getConnectionProperties()));
Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
mAdapter.handleCreateConnectionComplete(
@@ -669,6 +744,7 @@ public abstract class ConnectionService extends Service {
request.getAccountHandle(),
connection.getState(),
connection.getConnectionCapabilities(),
+ connection.getConnectionProperties(),
connection.getAddress(),
connection.getAddressPresentation(),
connection.getCallerDisplayName(),
@@ -736,6 +812,11 @@ public abstract class ConnectionService extends Service {
}
}
+ private void transfer(String callId) {
+ Log.d(this, "transfer %s", callId);
+ findConnectionForAction(callId, "transfer").onTransfer();
+ }
+
private void unhold(String callId) {
Log.d(this, "unhold %s", callId);
if (mConnectionById.containsKey(callId)) {
@@ -774,6 +855,11 @@ public abstract class ConnectionService extends Service {
}
}
+ private void setLocalCallHold(String callId, boolean lchStatus) {
+ Log.d(this, "setLocalCallHold %s", callId);
+ findConnectionForAction(callId, "setLocalCallHold").setLocalCallHold(lchStatus);
+ }
+
private void conference(String callId1, String callId2) {
Log.d(this, "conference %s, %s", callId1, callId2);
@@ -836,6 +922,17 @@ public abstract class ConnectionService extends Service {
}
}
+ private void addParticipantWithConference(String callId, String participant) {
+ Log.d(this, "ConnectionService addParticipantWithConference(%s, %s)", participant, callId);
+ Conference conference = findConferenceForAction(callId, "addParticipantWithConference");
+ Connection connection = findConnectionForAction(callId, "addParticipantWithConnection");
+ if (connection != getNullConnection()) {
+ onAddParticipant(connection, participant);
+ } else if (conference != getNullConference()) {
+ conference.onAddParticipant(participant);
+ }
+ }
+
private void mergeConference(String callId) {
Log.d(this, "mergeConference(%s)", callId);
Conference conference = findConferenceForAction(callId, "mergeConference");
@@ -971,6 +1068,7 @@ public abstract class ConnectionService extends Service {
conference.getPhoneAccountHandle(),
conference.getState(),
conference.getConnectionCapabilities(),
+ conference.getConnectionProperties(),
connectionIds,
conference.getVideoProvider() == null ?
null : conference.getVideoProvider().getInterface(),
@@ -1011,6 +1109,7 @@ public abstract class ConnectionService extends Service {
phoneAccountHandle,
connection.getState(),
connection.getConnectionCapabilities(),
+ connection.getConnectionProperties(),
connection.getAddress(),
connection.getAddressPresentation(),
connection.getCallerDisplayName(),
@@ -1122,6 +1221,19 @@ public abstract class ConnectionService extends Service {
public void onConference(Connection connection1, Connection connection2) {}
/**
+ * Add participant with connection. Invoked when user has made a request to add
+ * participant with specified connection. In response, the participant should add with
+ * the connection.
+ *
+ * @param connection A connection where participant need to add.
+ * @param participant Address of participant which will be added.
+ * @return
+ *
+ * @hide
+ */
+ public void onAddParticipant(Connection connection, String participant) {}
+
+ /**
* Indicates that a remote conference has been created for existing {@link RemoteConnection}s.
* When this method is invoked, this {@link ConnectionService} should create its own
* representation of the conference call and send it to telecom using {@link #addConference}.
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 4562514..f4bf835 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -196,6 +196,15 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
}
+ void setConnectionProperties(String callId, int properties) {
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.setConnectionProperties(callId, properties);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
/**
* Indicates whether or not the specified call is currently conferenced into the specified
* conference call.
@@ -230,6 +239,18 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
/**
+ * Resets the cdma connection time.
+ */
+ void resetCdmaConnectionTime(String callId) {
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.resetCdmaConnectionTime(callId);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ /**
* Indicates that the call no longer exists. Can be used with either a call or a conference
* call.
*
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 293dc11..f167fc1 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -62,6 +62,7 @@ final class ConnectionServiceAdapterServant {
private static final int MSG_ON_POST_DIAL_CHAR = 22;
private static final int MSG_SET_CONFERENCE_MERGE_FAILED = 23;
private static final int MSG_SET_EXTRAS = 24;
+ private static final int MSG_SET_CONNECTION_PROPERTIES = 25;
private final IConnectionServiceAdapter mDelegate;
@@ -116,6 +117,9 @@ final class ConnectionServiceAdapterServant {
case MSG_SET_CONNECTION_CAPABILITIES:
mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1);
break;
+ case MSG_SET_CONNECTION_PROPERTIES:
+ mDelegate.setConnectionProperties((String) msg.obj, msg.arg1);
+ break;
case MSG_SET_IS_CONFERENCED: {
SomeArgs args = (SomeArgs) msg.obj;
try {
@@ -300,6 +304,13 @@ final class ConnectionServiceAdapterServant {
}
@Override
+ public void setConnectionProperties(String connectionId, int connectionProperties) {
+ mHandler.obtainMessage(
+ MSG_SET_CONNECTION_PROPERTIES, connectionProperties, 0, connectionId)
+ .sendToTarget();
+ }
+
+ @Override
public void setConferenceMergeFailed(String callId) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
@@ -419,6 +430,10 @@ final class ConnectionServiceAdapterServant {
args.arg2 = extras;
mHandler.obtainMessage(MSG_SET_EXTRAS, args).sendToTarget();
}
+
+ @Override
+ public void resetCdmaConnectionTime(String callId) {
+ }
};
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 0cf7212..8eb62ec 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -240,6 +240,13 @@ public final class InCallAdapter {
}
}
+ public void transferCall(String callId) {
+ try {
+ mAdapter.transferCall(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+
/**
* Instructs Telecom to swap the child calls of the specified conference call.
*/
@@ -273,4 +280,17 @@ public final class InCallAdapter {
} catch (RemoteException ignored) {
}
}
+
+ /**
+ * Instructs Telecomm to switch to other active subscripion
+ *
+ * @param subid switch to subscription denoted by subId
+ * {@hide}
+ */
+ public void switchToOtherActiveSub(String subId) {
+ try {
+ mAdapter.switchToOtherActiveSub(subId);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 19c613d..1b6a98f 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -73,6 +73,7 @@ public abstract class InCallService extends Service {
private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5;
private static final int MSG_BRING_TO_FOREGROUND = 6;
private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
+ private static final int MSG_ON_MERGE_FAILED = 8;
/** Default Handler used to consolidate binder method calls onto a single thread. */
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -91,6 +92,9 @@ public abstract class InCallService extends Service {
case MSG_ADD_CALL:
mPhone.internalAddCall((ParcelableCall) msg.obj);
break;
+ case MSG_ON_MERGE_FAILED:
+ mPhone.onMergeFailed((ParcelableCall) msg.obj);
+ break;
case MSG_UPDATE_CALL:
mPhone.internalUpdateCall((ParcelableCall) msg.obj);
break;
@@ -156,6 +160,11 @@ public abstract class InCallService extends Service {
}
@Override
+ public void onMergeFailed(ParcelableCall call) {
+ mHandler.obtainMessage(MSG_ON_MERGE_FAILED, call).sendToTarget();
+ }
+
+ @Override
public void bringToForeground(boolean showDialpad) {
mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
}
@@ -301,6 +310,18 @@ public abstract class InCallService extends Service {
}
/**
+ * Instructs Telecomm to switch to other active subscripion
+ *
+ * @param subId switch to this subscription
+ * @hide
+ */
+ public void switchToOtherActiveSub(String subId) {
+ if (mPhone != null) {
+ mPhone.switchToOtherActiveSub(subId);
+ }
+ }
+
+ /**
* Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will
* be change to the {@link #getCallAudioState()}.
*
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 8cf4aeb..5b343e6 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -39,6 +39,7 @@ public final class ParcelableCall implements Parcelable {
private final List<String> mCannedSmsResponses;
private final int mCapabilities;
private final int mProperties;
+ private final long mCreateTimeMillis;
private final long mConnectTimeMillis;
private final Uri mHandle;
private final int mHandlePresentation;
@@ -56,6 +57,7 @@ public final class ParcelableCall implements Parcelable {
private final List<String> mConferenceableCallIds;
private final Bundle mIntentExtras;
private final Bundle mExtras;
+ private final boolean mIsActiveSub;
public ParcelableCall(
String id,
@@ -64,6 +66,7 @@ public final class ParcelableCall implements Parcelable {
List<String> cannedSmsResponses,
int capabilities,
int properties,
+ long createTimeMillis,
long connectTimeMillis,
Uri handle,
int handlePresentation,
@@ -79,13 +82,15 @@ public final class ParcelableCall implements Parcelable {
int videoState,
List<String> conferenceableCallIds,
Bundle intentExtras,
- Bundle extras) {
+ Bundle extras,
+ boolean isActiveSub) {
mId = id;
mState = state;
mDisconnectCause = disconnectCause;
mCannedSmsResponses = cannedSmsResponses;
mCapabilities = capabilities;
mProperties = properties;
+ mCreateTimeMillis = createTimeMillis;
mConnectTimeMillis = connectTimeMillis;
mHandle = handle;
mHandlePresentation = handlePresentation;
@@ -102,6 +107,7 @@ public final class ParcelableCall implements Parcelable {
mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds);
mIntentExtras = intentExtras;
mExtras = extras;
+ mIsActiveSub = isActiveSub;
}
/** The unique ID of the call. */
@@ -137,6 +143,11 @@ public final class ParcelableCall implements Parcelable {
/** Bitmask of properties of the call. */
public int getProperties() { return mProperties; }
+ /** The time that the call object was created */
+ public long getCreateTimeMillis() {
+ return mCreateTimeMillis;
+ }
+
/** The time that the call switched to the active state. */
public long getConnectTimeMillis() {
return mConnectTimeMillis;
@@ -259,6 +270,13 @@ public final class ParcelableCall implements Parcelable {
return mIsVideoCallProviderChanged;
}
+ /**
+ * return if this call object belongs to active subscription.
+ */
+ public boolean isActive() {
+ return mIsActiveSub;
+ }
+
/** Responsible for creating ParcelableCall objects for deserialized Parcels. */
public static final Parcelable.Creator<ParcelableCall> CREATOR =
new Parcelable.Creator<ParcelableCall> () {
@@ -272,6 +290,7 @@ public final class ParcelableCall implements Parcelable {
source.readList(cannedSmsResponses, classLoader);
int capabilities = source.readInt();
int properties = source.readInt();
+ long createTimeMillis = source.readLong();
long connectTimeMillis = source.readLong();
Uri handle = source.readParcelable(classLoader);
int handlePresentation = source.readInt();
@@ -291,6 +310,7 @@ public final class ParcelableCall implements Parcelable {
source.readList(conferenceableCallIds, classLoader);
Bundle intentExtras = source.readBundle(classLoader);
Bundle extras = source.readBundle(classLoader);
+ boolean isActiveSub = (source.readInt() == 1) ? true : false;
return new ParcelableCall(
id,
state,
@@ -298,6 +318,7 @@ public final class ParcelableCall implements Parcelable {
cannedSmsResponses,
capabilities,
properties,
+ createTimeMillis,
connectTimeMillis,
handle,
handlePresentation,
@@ -313,7 +334,8 @@ public final class ParcelableCall implements Parcelable {
videoState,
conferenceableCallIds,
intentExtras,
- extras);
+ extras,
+ isActiveSub);
}
@Override
@@ -337,6 +359,7 @@ public final class ParcelableCall implements Parcelable {
destination.writeList(mCannedSmsResponses);
destination.writeInt(mCapabilities);
destination.writeInt(mProperties);
+ destination.writeLong(mCreateTimeMillis);
destination.writeLong(mConnectTimeMillis);
destination.writeParcelable(mHandle, 0);
destination.writeInt(mHandlePresentation);
@@ -354,6 +377,7 @@ public final class ParcelableCall implements Parcelable {
destination.writeList(mConferenceableCallIds);
destination.writeBundle(mIntentExtras);
destination.writeBundle(mExtras);
+ destination.writeInt(mIsActiveSub ? 1 : 0);
}
@Override
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index 870f5ee..8da5734 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -34,6 +34,7 @@ public final class ParcelableConference implements Parcelable {
private PhoneAccountHandle mPhoneAccount;
private int mState;
private int mConnectionCapabilities;
+ private int mConnectionProperties;
private List<String> mConnectionIds;
private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
private final IVideoProvider mVideoProvider;
@@ -45,6 +46,7 @@ public final class ParcelableConference implements Parcelable {
PhoneAccountHandle phoneAccount,
int state,
int connectionCapabilities,
+ int connectionProperties,
List<String> connectionIds,
IVideoProvider videoProvider,
int videoState,
@@ -54,6 +56,7 @@ public final class ParcelableConference implements Parcelable {
mPhoneAccount = phoneAccount;
mState = state;
mConnectionCapabilities = connectionCapabilities;
+ mConnectionProperties = connectionProperties;
mConnectionIds = connectionIds;
mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
mVideoProvider = videoProvider;
@@ -72,6 +75,8 @@ public final class ParcelableConference implements Parcelable {
.append(Connection.stateToString(mState))
.append(", capabilities: ")
.append(Connection.capabilitiesToString(mConnectionCapabilities))
+ .append(", properties: ")
+ .append(Connection.propertiesToString(mConnectionProperties))
.append(", connectTime: ")
.append(mConnectTimeMillis)
.append(", children: ")
@@ -95,6 +100,10 @@ public final class ParcelableConference implements Parcelable {
return mConnectionCapabilities;
}
+ public int getConnectionProperties() {
+ return mConnectionProperties;
+ }
+
public List<String> getConnectionIds() {
return mConnectionIds;
}
@@ -126,6 +135,7 @@ public final class ParcelableConference implements Parcelable {
PhoneAccountHandle phoneAccount = source.readParcelable(classLoader);
int state = source.readInt();
int capabilities = source.readInt();
+ int properties = source.readInt();
List<String> connectionIds = new ArrayList<>(2);
source.readList(connectionIds, classLoader);
long connectTimeMillis = source.readLong();
@@ -135,8 +145,9 @@ public final class ParcelableConference implements Parcelable {
StatusHints statusHints = source.readParcelable(classLoader);
Bundle extras = source.readBundle(classLoader);
- return new ParcelableConference(phoneAccount, state, capabilities, connectionIds,
- videoCallProvider, videoState, connectTimeMillis, statusHints, extras);
+ return new ParcelableConference(phoneAccount, state, capabilities, properties,
+ connectionIds, videoCallProvider, videoState,
+ connectTimeMillis, statusHints, extras);
}
@Override
@@ -157,6 +168,7 @@ public final class ParcelableConference implements Parcelable {
destination.writeParcelable(mPhoneAccount, 0);
destination.writeInt(mState);
destination.writeInt(mConnectionCapabilities);
+ destination.writeInt(mConnectionProperties);
destination.writeList(mConnectionIds);
destination.writeLong(mConnectTimeMillis);
destination.writeStrongBinder(
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index fe0a4d8..eca06af 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -36,6 +36,7 @@ public final class ParcelableConnection implements Parcelable {
private final PhoneAccountHandle mPhoneAccount;
private final int mState;
private final int mConnectionCapabilities;
+ private final int mConnectionProperties;
private final Uri mAddress;
private final int mAddressPresentation;
private final String mCallerDisplayName;
@@ -55,6 +56,7 @@ public final class ParcelableConnection implements Parcelable {
PhoneAccountHandle phoneAccount,
int state,
int capabilities,
+ int properties,
Uri address,
int addressPresentation,
String callerDisplayName,
@@ -71,6 +73,7 @@ public final class ParcelableConnection implements Parcelable {
mPhoneAccount = phoneAccount;
mState = state;
mConnectionCapabilities = capabilities;
+ mConnectionProperties = properties;
mAddress = address;
mAddressPresentation = addressPresentation;
mCallerDisplayName = callerDisplayName;
@@ -99,6 +102,10 @@ public final class ParcelableConnection implements Parcelable {
return mConnectionCapabilities;
}
+ public int getConnectionProperties() {
+ return mConnectionProperties;
+ }
+
public Uri getHandle() {
return mAddress;
}
@@ -160,6 +167,8 @@ public final class ParcelableConnection implements Parcelable {
.append(mState)
.append(", capabilities:")
.append(Connection.capabilitiesToString(mConnectionCapabilities))
+ .append(", properties:")
+ .append(Connection.propertiesToString(mConnectionProperties))
.append(", extras:")
.append(mExtras)
.toString();
@@ -174,6 +183,7 @@ public final class ParcelableConnection implements Parcelable {
PhoneAccountHandle phoneAccount = source.readParcelable(classLoader);
int state = source.readInt();
int capabilities = source.readInt();
+ int properties = source.readInt();
Uri address = source.readParcelable(classLoader);
int addressPresentation = source.readInt();
String callerDisplayName = source.readString();
@@ -194,6 +204,7 @@ public final class ParcelableConnection implements Parcelable {
phoneAccount,
state,
capabilities,
+ properties,
address,
addressPresentation,
callerDisplayName,
@@ -227,6 +238,7 @@ public final class ParcelableConnection implements Parcelable {
destination.writeParcelable(mPhoneAccount, 0);
destination.writeInt(mState);
destination.writeInt(mConnectionCapabilities);
+ destination.writeInt(mConnectionProperties);
destination.writeParcelable(mAddress, 0);
destination.writeInt(mAddressPresentation);
destination.writeString(mCallerDisplayName);
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 47154da..0fd124d 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -123,7 +123,7 @@ public final class Phone {
final void internalAddCall(ParcelableCall parcelableCall) {
Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
- parcelableCall.getState());
+ parcelableCall.getState(), parcelableCall.isActive());
mCallByTelecomCallId.put(parcelableCall.getId(), call);
mCalls.add(call);
checkCallTree(parcelableCall);
@@ -179,6 +179,12 @@ public final class Phone {
}
}
+ final void onMergeFailed(ParcelableCall parcelableCall) {
+ Call call = mCallByTelecomCallId.get(parcelableCall.getId());
+ if (call != null) {
+ call.onMergeFailed();
+ }
+ }
/**
* Called to destroy the phone and cleanup any lingering calls.
*/
@@ -280,6 +286,16 @@ public final class Phone {
}
/**
+ * Instructs Telecomm to switch to other active subscripion
+ *
+ * @param subId switch to this subscription
+ * {@hide}
+ */
+ public void switchToOtherActiveSub(String subId) {
+ mInCallAdapter.switchToOtherActiveSub(subId);
+ }
+
+ /**
* Obtains the current phone call audio state of the {@code Phone}.
*
* @return An object encapsulating the audio state.
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index b64043c..635a48b 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -34,6 +34,7 @@ import android.text.TextUtils;
import java.lang.String;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.MissingResourceException;
@@ -374,6 +375,43 @@ public final class PhoneAccount implements Parcelable {
}
/**
+ * Contains information related to
+ * LCH and ACTIVE.
+ */
+ private BitSet callsStatus = new BitSet();
+
+ /**
+ * {@hide}
+ */
+ public static final int LCH = 1;
+
+ /**
+ * {@hide}
+ */
+ public static final int ACTIVE = 2;
+
+ /**
+ * {@hide}
+ */
+ public void setBit(int bit) {
+ callsStatus.set(bit);
+ }
+
+ /**
+ * {@hide}
+ */
+ public void unSetBit(int bit) {
+ callsStatus.set(bit, false);
+ }
+
+ /**
+ * {@hide}
+ */
+ public boolean isSet(int bit) {
+ return callsStatus.get(bit);
+ }
+
+ /**
* Returns a builder initialized with the current {@link PhoneAccount} instance.
*
* @return The builder.
diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java
index ae5cd46..8136c7d 100644
--- a/telecomm/java/android/telecom/RemoteConference.java
+++ b/telecomm/java/android/telecom/RemoteConference.java
@@ -92,6 +92,18 @@ public final class RemoteConference {
int connectionCapabilities) {}
/**
+ * Indicates that the call properties of this {@code RemoteConference} have changed.
+ * See {@link #getConnectionProperties()}.
+ *
+ * @param conference The {@code RemoteConference} invoking this method.
+ * @param connectionProperties The new properties of the {@code RemoteConference}.
+ * @hide
+ */
+ public void onConnectionPropertiesChanged(
+ RemoteConference conference,
+ int connectionProperties) {}
+
+ /**
* Invoked when the set of {@link RemoteConnection}s which can be added to this conference
* call have changed.
*
@@ -133,6 +145,7 @@ public final class RemoteConference {
private int mState = Connection.STATE_NEW;
private DisconnectCause mDisconnectCause;
private int mConnectionCapabilities;
+ private int mConnectionProperties;
private Bundle mExtras;
/** @hide */
@@ -243,6 +256,24 @@ public final class RemoteConference {
}
}
+ /** {@hide} */
+ void setConnectionProperties(final int connectionProperties) {
+ if (mConnectionProperties != connectionProperties) {
+ mConnectionProperties = connectionProperties;
+ for (CallbackRecord<Callback> record : mCallbackRecords) {
+ final RemoteConference conference = this;
+ final Callback callback = record.getCallback();
+ record.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onConnectionPropertiesChanged(
+ conference, mConnectionProperties);
+ }
+ });
+ }
+ }
+ }
+
/** @hide */
void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
mConferenceableConnections.clear();
@@ -322,6 +353,17 @@ public final class RemoteConference {
}
/**
+ * Returns the properties of the conference. See {@code PROPERTY_*} constants in class
+ * {@link Connection} for valid values.
+ *
+ * @return A bitmask of the properties of the conference call.
+ * @hide
+ */
+ public final int getConnectionProperties() {
+ return mConnectionProperties;
+ }
+
+ /**
* Obtain the extras associated with this {@code RemoteConnection}.
*
* @return The extras for this connection.
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index f960959..4371367 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -90,6 +90,18 @@ public final class RemoteConnection {
int connectionCapabilities) {}
/**
+ * Indicates that the call properties of this {@code RemoteConnection} have changed.
+ * See {@link #getConnectionProperties()}.
+ *
+ * @param connection The {@code RemoteConnection} invoking this method.
+ * @param connectionProperties The new properties of the {@code RemoteConnection}.
+ * @hide
+ */
+ public void onConnectionPropertiesChanged(
+ RemoteConnection connection,
+ int connectionProperties) {}
+
+ /**
* Invoked when the post-dial sequence in the outgoing {@code Connection} has reached a
* pause character. This causes the post-dial signals to stop pending user confirmation. An
* implementation should present this choice to the user and invoke
@@ -577,6 +589,7 @@ public final class RemoteConnection {
private boolean mRingbackRequested;
private boolean mConnected;
private int mConnectionCapabilities;
+ private int mConnectionProperties;
private int mVideoState;
private VideoProvider mVideoProvider;
private boolean mIsVoipAudioMode;
@@ -613,6 +626,7 @@ public final class RemoteConnection {
mDisconnectCause = connection.getDisconnectCause();
mRingbackRequested = connection.isRingbackRequested();
mConnectionCapabilities = connection.getConnectionCapabilities();
+ mConnectionProperties = connection.getConnectionProperties();
mVideoState = connection.getVideoState();
mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider());
mIsVoipAudioMode = connection.getIsVoipAudioMode();
@@ -708,6 +722,15 @@ public final class RemoteConnection {
}
/**
+ * @return A bitmask of the properties of the {@code RemoteConnection}, as defined in
+ * the {@code PROPERTY_*} constants in class {@link Connection}.
+ * @hide
+ */
+ public int getConnectionProperties() {
+ return mConnectionProperties;
+ }
+
+ /**
* Determines if the audio mode of this {@code RemoteConnection} is VOIP.
*
* @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP.
@@ -1089,6 +1112,23 @@ public final class RemoteConnection {
/**
* @hide
*/
+ void setConnectionProperties(final int connectionProperties) {
+ mConnectionProperties = connectionProperties;
+ for (CallbackRecord record : mCallbackRecords) {
+ final RemoteConnection connection = this;
+ final Callback callback = record.getCallback();
+ record.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onConnectionPropertiesChanged(connection, connectionProperties);
+ }
+ });
+ }
+ }
+
+ /**
+ * @hide
+ */
void setDestroyed() {
if (!mCallbackRecords.isEmpty()) {
// Make sure that the callbacks are notified that the call is destroyed first.
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index dc0de0c..0045915 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -61,6 +61,7 @@ final class RemoteConnectionService {
mPendingConnections.remove(connection);
// Unconditionally initialize the connection ...
connection.setConnectionCapabilities(parcel.getConnectionCapabilities());
+ connection.setConnectionProperties(parcel.getConnectionProperties());
if (parcel.getHandle() != null
|| parcel.getState() != Connection.STATE_DISCONNECTED) {
connection.setAddress(parcel.getHandle(), parcel.getHandlePresentation());
@@ -156,6 +157,17 @@ final class RemoteConnectionService {
}
@Override
+ public void setConnectionProperties(String callId, int connectionProperties) {
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "setConnectionProperties")
+ .setConnectionProperties(connectionProperties);
+ } else {
+ findConferenceForAction(callId, "setConnectionProperties")
+ .setConnectionProperties(connectionProperties);
+ }
+ }
+
+ @Override
public void setIsConferenced(String callId, String conferenceCallId) {
// Note: callId should not be null; conferenceCallId may be null
RemoteConnection connection =
@@ -206,6 +218,7 @@ final class RemoteConnectionService {
conference.setState(parcel.getState());
conference.setConnectionCapabilities(parcel.getConnectionCapabilities());
+ conference.setConnectionProperties(parcel.getConnectionProperties());
mConferenceById.put(callId, conference);
conference.registerCallback(new RemoteConference.Callback() {
@Override
@@ -330,6 +343,10 @@ final class RemoteConnectionService {
.setExtras(extras);
}
}
+
+ @Override
+ public void resetCdmaConnectionTime(String callId) {
+ }
};
private final ConnectionServiceAdapterServant mServant =
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index b07b018..ae7c18e 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -22,6 +22,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -1090,6 +1091,37 @@ public class TelecomManager {
}
/**
+ * Returns current active subscription.
+ * Active subscription is the one from which calls are displayed to user when there are actve
+ * calls on both subscriptions.
+ * @hide
+ */
+ public int getActiveSubscription() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecomService().getActiveSubscription();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException attempting to get the active subsription.", e);
+ }
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ /**
+ * switches to other active subscription.
+ * @hide
+ */
+ public void switchToOtherActiveSub(int subId) {
+ try {
+ if (isServiceConnected()) {
+ getTelecomService().switchToOtherActiveSub(subId);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException attempting to switchToOtherActiveSub.", e);
+ }
+ }
+
+ /**
* Registers a new incoming call. A {@link ConnectionService} should invoke this method when it
* has an incoming call. The specified {@link PhoneAccountHandle} must have been registered
* with {@link #registerPhoneAccount}. Once invoked, this method will cause the system to bind
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index c8072d1..93484cd 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -57,13 +57,20 @@ public class VideoCallImpl extends VideoCall {
private final class VideoCallListenerBinder extends IVideoCallback.Stub {
@Override
public void receiveSessionModifyRequest(VideoProfile videoProfile) {
+ if (mHandler == null) {
+ return;
+ }
mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
videoProfile).sendToTarget();
+
}
@Override
public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
VideoProfile responseProfile) {
+ if (mHandler == null) {
+ return;
+ }
SomeArgs args = SomeArgs.obtain();
args.arg1 = status;
args.arg2 = requestProfile;
@@ -74,12 +81,18 @@ public class VideoCallImpl extends VideoCall {
@Override
public void handleCallSessionEvent(int event) {
+ if (mHandler == null) {
+ return;
+ }
mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
.sendToTarget();
}
@Override
public void changePeerDimensions(int width, int height) {
+ if (mHandler == null) {
+ return;
+ }
SomeArgs args = SomeArgs.obtain();
args.arg1 = width;
args.arg2 = height;
@@ -88,18 +101,27 @@ public class VideoCallImpl extends VideoCall {
@Override
public void changeVideoQuality(int videoQuality) {
+ if (mHandler == null) {
+ return;
+ }
mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
.sendToTarget();
}
@Override
public void changeCallDataUsage(long dataUsage) {
+ if (mHandler == null) {
+ return;
+ }
mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
.sendToTarget();
}
@Override
public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
+ if (mHandler == null) {
+ return;
+ }
mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
cameraCapabilities).sendToTarget();
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 8a54add..398d2e1 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -75,4 +75,10 @@ oneway interface IConnectionService {
void swapConference(String conferenceCallId);
void onPostDialContinue(String callId, boolean proceed);
+
+ void setLocalCallHold(String callId, boolean lchState);
+
+ void addParticipantWithConference(String callId, String recipients);
+
+ void explicitTransfer(String callId);
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 7647444..1853f5a 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -55,6 +55,8 @@ oneway interface IConnectionServiceAdapter {
void setConnectionCapabilities(String callId, int connectionCapabilities);
+ void setConnectionProperties(String callId, int connectionProperties);
+
void setIsConferenced(String callId, String conferenceCallId);
void setConferenceMergeFailed(String callId);
@@ -86,4 +88,6 @@ oneway interface IConnectionServiceAdapter {
void addExistingConnection(String callId, in ParcelableConnection connection);
void setExtras(String callId, in Bundle extras);
+
+ void resetCdmaConnectionTime(String callId);
}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 863fff2..6ef8eda 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -60,4 +60,8 @@ oneway interface IInCallAdapter {
void turnOnProximitySensor();
void turnOffProximitySensor(boolean screenOnImmediately);
+
+ void switchToOtherActiveSub(String subId);
+
+ void transferCall(String callId);
}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index ded47d5..f4ba9a0 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -45,4 +45,6 @@ oneway interface IInCallService {
void bringToForeground(boolean showDialpad);
void onCanAddCallChanged(boolean canAddCall);
+
+ void onMergeFailed(in ParcelableCall call);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 2e07759..cad8c5d 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -232,4 +232,14 @@ interface ITelecomService {
* @see TelecomServiceImpl#setDefaultDialer
*/
boolean setDefaultDialer(in String packageName);
+
+ /**
+ * @see TelecommManager#getActiveSubscription
+ */
+ int getActiveSubscription();
+
+ /**
+ * @see TelecommManager#switchToOtherActiveSub
+ */
+ void switchToOtherActiveSub(int subId);
}
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 8443490..1821f30 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -187,6 +187,68 @@ public class DisconnectCause {
*/
public static final int CDMA_ALREADY_ACTIVATED = 49;
+ /** call failed due to LTE to 3G/2G handover not feasible */
+ public static final int HO_NOT_FEASIBLE = 50;
+
+ public static final int NO_CIRCUIT_AVAIL = 51;
+ public static final int NO_ROUTE_TO_DESTINAON = 52;
+ public static final int OPERATOR_DETERMINED_BARRING = 53;
+ public static final int CALL_FAIL_NO_USER_RESPONDING = 54;
+ public static final int CALL_FAIL_NO_ANSWER_FROM_USER = 55;
+ public static final int CALL_FAIL_DESTINATION_OUT_OF_ORDER = 56;
+ public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57;
+ public static final int CHANNEL_UNACCEPTABLE = 58;
+ public static final int CALL_REJECTED = 59;
+ public static final int NUMBER_CHANGED = 60;
+ public static final int PREEMPTION = 61;
+ public static final int FACILITY_REJECTED = 62;
+ public static final int RESP_TO_STATUS_ENQUIRY = 63;
+ public static final int NORMAL_UNSPECIFIED = 64;
+ public static final int NETWORK_OUT_OF_ORDER = 65;
+ public static final int TEMPORARY_FAILURE = 66;
+ public static final int SWITCHING_EQUIPMENT_CONGESTION = 67;
+ public static final int ACCESS_INFORMATION_DISCARDED = 68;
+ public static final int REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 69;
+ public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 70;
+ public static final int QOS_UNAVAILABLE = 71;
+ public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 72;
+ public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 73;
+ public static final int BEARER_CAPABILITY_UNAVAILABLE = 74;
+ public static final int SERVICE_OPTION_NOT_AVAILABLE = 75;
+ public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 76;
+ public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 77;
+ public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 78;
+ public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79;
+ public static final int INVALID_TRANSACTION_IDENTIFIER = 80;
+ public static final int USER_NOT_MEMBER_OF_CUG = 81;
+ public static final int INCOMPATIBLE_DESTINATION = 82;
+ public static final int INVALID_TRANSIT_NW_SELECTION = 83;
+ public static final int SEMANTICALLY_INCORRECT_MESSAGE = 84;
+ public static final int INVALID_MANDATORY_INFORMATION = 85;
+ public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 86;
+ public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 87;
+ public static final int INFORMATION_ELEMENT_NON_EXISTENT = 88;
+ public static final int CONDITIONAL_IE_ERROR = 89;
+ public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 90;
+ public static final int RECOVERY_ON_TIMER_EXPIRED = 91;
+ public static final int PROTOCOL_ERROR_UNSPECIFIED = 92;
+ public static final int INTERWORKING_UNSPECIFIED = 93;
+ public static final int LOCAL_LOW_BATTERY = 94;
+ public static final int LOW_BATTERY = 95;
+
+ /** EMERGENCY call failed with temporary fail cause */
+ public static final int EMERGENCY_TEMP_FAILURE = 96;
+ /** EMERGENCY call failed with permanent fail cause */
+ public static final int EMERGENCY_PERM_FAILURE = 97;
+
+ public static final int NON_SELECTED_USER_CLEARING = 98;
+
+ /**
+ * Call was rejected due to number being blacklisted by user.
+ * {@@hide}
+ */
+ public static final int CALL_BLACKLISTED = 400;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -195,14 +257,14 @@ public class DisconnectCause {
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 50
+ // NextId: 99
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = CDMA_ALREADY_ACTIVATED;
+ public static final int MAXIMUM_VALID_VALUE = CALL_BLACKLISTED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -310,6 +372,106 @@ public class DisconnectCause {
return "IMS_MERGED_SUCCESSFULLY";
case CDMA_ALREADY_ACTIVATED:
return "CDMA_ALREADY_ACTIVATED";
+ case NON_SELECTED_USER_CLEARING:
+ return "NON_SELECTED_USER_CLEARING";
+ case HO_NOT_FEASIBLE:
+ return "HO_NOT_FEASIBLE";
+ case NO_CIRCUIT_AVAIL:
+ return "NO_CIRCUIT_AVAIL";
+ case NO_ROUTE_TO_DESTINAON:
+ return "NO_ROUTE_TO_DESTINAON";
+ case OPERATOR_DETERMINED_BARRING:
+ return "OPERATOR_DETERMINED_BARRING";
+ case CALL_FAIL_NO_USER_RESPONDING:
+ return "CALL_FAIL_NO_USER_RESPONDING";
+ case CALL_FAIL_NO_ANSWER_FROM_USER:
+ return "CALL_FAIL_NO_ANSWER_FROM_USER";
+ case CALL_FAIL_DESTINATION_OUT_OF_ORDER:
+ return "CALL_FAIL_DESTINATION_OUT_OF_ORDER";
+ case BEARER_CAPABILITY_NOT_AUTHORIZED:
+ return "BEARER_CAPABILITY_NOT_AUTHORIZED";
+ case CHANNEL_UNACCEPTABLE:
+ return "CHANNEL_UNACCEPTABLE";
+ case CALL_REJECTED:
+ return "CALL_REJECTED";
+ case NUMBER_CHANGED:
+ return "NUMBER_CHANGED";
+ case PREEMPTION:
+ return "PREEMPTION";
+ case FACILITY_REJECTED:
+ return "FACILITY_REJECTED";
+ case RESP_TO_STATUS_ENQUIRY:
+ return "RESP_TO_STATUS_ENQUIRY";
+ case NORMAL_UNSPECIFIED:
+ return "NORMAL_UNSPECIFIED";
+ case NETWORK_OUT_OF_ORDER:
+ return "NETWORK_OUT_OF_ORDER";
+ case TEMPORARY_FAILURE:
+ return "TEMPORARY_FAILURE";
+ case SWITCHING_EQUIPMENT_CONGESTION:
+ return "SWITCHING_EQUIPMENT_CONGESTION";
+ case ACCESS_INFORMATION_DISCARDED:
+ return "ACCESS_INFORMATION_DISCARDED";
+ case REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE:
+ return "REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE";
+ case RESOURCES_UNAVAILABLE_OR_UNSPECIFIED:
+ return "RESOURCES_UNAVAILABLE_OR_UNSPECIFIED";
+ case QOS_UNAVAILABLE:
+ return "QOS_UNAVAILABLE";
+ case REQUESTED_FACILITY_NOT_SUBSCRIBED:
+ return "REQUESTED_FACILITY_NOT_SUBSCRIBED";
+ case INCOMING_CALLS_BARRED_WITHIN_CUG:
+ return "INCOMING_CALLS_BARRED_WITHIN_CUG";
+ case BEARER_CAPABILITY_UNAVAILABLE:
+ return "BEARER_CAPABILITY_UNAVAILABLE";
+ case SERVICE_OPTION_NOT_AVAILABLE:
+ return "SERVICE_OPTION_NOT_AVAILABLE";
+ case BEARER_SERVICE_NOT_IMPLEMENTED:
+ return "BEARER_SERVICE_NOT_IMPLEMENTED";
+ case REQUESTED_FACILITY_NOT_IMPLEMENTED:
+ return "REQUESTED_FACILITY_NOT_IMPLEMENTED";
+ case ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE:
+ return "ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE";
+ case SERVICE_OR_OPTION_NOT_IMPLEMENTED:
+ return "SERVICE_OR_OPTION_NOT_IMPLEMENTED";
+ case INVALID_TRANSACTION_IDENTIFIER:
+ return "INVALID_TRANSACTION_IDENTIFIER";
+ case USER_NOT_MEMBER_OF_CUG:
+ return "USER_NOT_MEMBER_OF_CUG";
+ case INCOMPATIBLE_DESTINATION:
+ return "INCOMPATIBLE_DESTINATION";
+ case INVALID_TRANSIT_NW_SELECTION:
+ return "INVALID_TRANSIT_NW_SELECTION";
+ case SEMANTICALLY_INCORRECT_MESSAGE:
+ return "SEMANTICALLY_INCORRECT_MESSAGE";
+ case INVALID_MANDATORY_INFORMATION:
+ return "INVALID_MANDATORY_INFORMATION";
+ case MESSAGE_TYPE_NON_IMPLEMENTED:
+ return "MESSAGE_TYPE_NON_IMPLEMENTED";
+ case MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE:
+ return "MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE";
+ case INFORMATION_ELEMENT_NON_EXISTENT:
+ return "INFORMATION_ELEMENT_NON_EXISTENT";
+ case CONDITIONAL_IE_ERROR:
+ return "CONDITIONAL_IE_ERROR";
+ case MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE:
+ return "MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE";
+ case RECOVERY_ON_TIMER_EXPIRED:
+ return "RECOVERY_ON_TIMER_EXPIRED";
+ case PROTOCOL_ERROR_UNSPECIFIED:
+ return "PROTOCOL_ERROR_UNSPECIFIED";
+ case INTERWORKING_UNSPECIFIED:
+ return "INTERWORKING_UNSPECIFIED";
+ case LOCAL_LOW_BATTERY:
+ return "LOCAL_LOW_BATTERY";
+ case LOW_BATTERY:
+ return "LOW_BATTERY";
+ case EMERGENCY_TEMP_FAILURE:
+ return "EMERGENCY_TEMP_FAILURE";
+ case EMERGENCY_PERM_FAILURE:
+ return "EMERGENCY_PERM_FAILURE";
+ case CALL_BLACKLISTED:
+ return "CALL_BLACKLISTED";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b430340..5ee1fb2 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.util.SparseArray;
import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
@@ -25,6 +26,7 @@ import com.android.i18n.phonenumbers.ShortNumberUtil;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
+import android.location.Country;
import android.location.CountryDetector;
import android.net.Uri;
import android.os.SystemProperties;
@@ -77,6 +79,7 @@ public class PhoneNumberUtils
static final String LOG_TAG = "PhoneNumberUtils";
private static final boolean DBG = false;
+ private static Country sCountryDetector = null;
/*
* global-phone-number = ["+"] 1*( DIGIT / written-sep )
* written-sep = ("-"/".")
@@ -139,6 +142,55 @@ public class PhoneNumberUtils
return !isDialable(ch) && !(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'));
}
+ /**
+ * On some CDMA networks +COUNTRYCODE must be rewritten to 0 when making a local
+ * call from within the user's home network. We maintain a white list of
+ * (country code prefix) -> (rewrite rule) to perform this substitution.
+ *
+ * Since country codes are variable length it is easiest to compile a regex
+ */
+ private static SparseArray<RewriteRule> sCdmaLocalRewriteWhitelist;
+ private static Pattern sCdmaLocalRewritePattern;
+ static {
+ sCdmaLocalRewriteWhitelist = new SparseArray<RewriteRule>();
+ addRewriteRule(62, "ID", "0"); // indonesia
+ addRewriteRule(380, "UA", "0"); // ukraine
+
+ StringBuffer regex = new StringBuffer();
+ regex.append("[+](");
+ for (int i=0; i < sCdmaLocalRewriteWhitelist.size(); ++i) {
+ int countryCode = sCdmaLocalRewriteWhitelist.keyAt(i);
+ if (i > 0) {
+ regex.append("|");
+ }
+ regex.append(countryCode);
+ }
+ regex.append(")");
+ sCdmaLocalRewritePattern = Pattern.compile(regex.toString());
+ }
+
+ private static class RewriteRule {
+ public int countryCodePrefix;
+ public String isoCountryCode;
+ public String replacement;
+
+ public RewriteRule(int countryCodePrefix, String isoCountryCode, String replacement) {
+ this.countryCodePrefix = countryCodePrefix;
+ this.isoCountryCode = isoCountryCode;
+ this.replacement = replacement;
+ }
+
+ public String apply(String dialStr) {
+ return dialStr.replaceFirst("[+]" + countryCodePrefix, replacement);
+ }
+ }
+
+ private static void addRewriteRule(int countryCodePrefix,
+ String isoCountryCode, String replacement) {
+ sCdmaLocalRewriteWhitelist.put(countryCodePrefix,
+ new RewriteRule(countryCodePrefix, isoCountryCode, replacement));
+ }
+
/** Extracts the phone number from an Intent.
*
* @param intent the intent to get the number of
@@ -2057,12 +2109,9 @@ public class PhoneNumberUtils
private static boolean isLocalEmergencyNumberInternal(int subId, String number,
Context context,
boolean useExactMatch) {
- String countryIso;
- CountryDetector detector = (CountryDetector) context.getSystemService(
- Context.COUNTRY_DETECTOR);
- if (detector != null && detector.detectCountry() != null) {
- countryIso = detector.detectCountry().getCountryIso();
- } else {
+ String countryIso = getCountryIso(context);
+ Rlog.w(LOG_TAG, "isLocalEmergencyNumberInternal" + countryIso);
+ if (countryIso == null) {
Locale locale = context.getResources().getConfiguration().locale;
countryIso = locale.getCountry();
Rlog.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: "
@@ -2071,6 +2120,28 @@ public class PhoneNumberUtils
return isEmergencyNumberInternal(subId, number, countryIso, useExactMatch);
}
+ private static String getCountryIso(Context context) {
+ Rlog.w(LOG_TAG, "getCountryIso " + sCountryDetector);
+ if (sCountryDetector == null) {
+ CountryDetector detector = (CountryDetector) context.getSystemService(
+ Context.COUNTRY_DETECTOR);
+ if (detector != null) {
+ sCountryDetector = detector.detectCountry();
+ }
+ }
+
+ if (sCountryDetector == null) {
+ return null;
+ } else {
+ return sCountryDetector.getCountryIso();
+ }
+ }
+
+ /** @hide */
+ public static void resetCountryDetectorInfo() {
+ sCountryDetector = null;
+ }
+
/**
* isVoiceMailNumber: checks a given number against the voicemail
* number provided by the RIL and SIM card. The caller must have
@@ -2560,6 +2631,29 @@ public class PhoneNumberUtils
}
/**
+ * Returns a rewrite rule for the country code prefix if the dial string matches the
+ * whitelist and the user is in their home network
+ *
+ * @param dialStr number being dialed
+ * @param currIso ISO code of currently attached network
+ * @param defaultIso ISO code of user's sim
+ * @return RewriteRule or null if conditions fail
+ */
+ private static RewriteRule getCdmaLocalRewriteRule(String dialStr,
+ String currIso, String defaultIso) {
+ Matcher m = sCdmaLocalRewritePattern.matcher(dialStr);
+ if (m.find()) {
+ String dialPrefix = m.group(1);
+ RewriteRule rule = sCdmaLocalRewriteWhitelist.get(Integer.valueOf(dialPrefix));
+ if (currIso.equalsIgnoreCase(defaultIso) &&
+ currIso.equalsIgnoreCase(rule.isoCountryCode)) {
+ return rule;
+ }
+ }
+ return null;
+ }
+
+ /**
* Determines if the specified number is actually a URI
* (i.e. a SIP address) rather than a regular PSTN phone number,
* based on whether or not the number contains an "@" character.
@@ -2622,8 +2716,16 @@ public class PhoneNumberUtils
// Remove the leading plus sign
retStr = newStr;
} else {
- // Replaces the plus sign with the default IDP
- retStr = networkDialStr.replaceFirst("[+]", getCurrentIdp(useNanp));
+ RewriteRule rewriteRule =
+ getCdmaLocalRewriteRule(networkDialStr,
+ TelephonyManager.getDefault().getNetworkCountryIso(),
+ TelephonyManager.getDefault().getSimCountryIso());
+ if (rewriteRule != null) {
+ retStr = rewriteRule.apply(networkDialStr);
+ } else {
+ // Replaces the plus sign with the default IDP
+ retStr = networkDialStr.replaceFirst("[+]", getCurrentIdp(useNanp));
+ }
}
}
if (DBG) log("processPlusCode, retStr=" + retStr);
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 2bfaf1b..2906a2d 100644..100755
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -47,6 +47,7 @@ public class RadioAccessFamily implements Parcelable {
public static final int RAF_HSPAP = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP);
public static final int RAF_GSM = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
public static final int RAF_TD_SCDMA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA);
+ public static final int RAF_LTE_CA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA);
// Grouping of RAFs
private static final int GSM = RAF_GSM | RAF_GPRS | RAF_EDGE;
@@ -54,6 +55,7 @@ public class RadioAccessFamily implements Parcelable {
private static final int CDMA = RAF_IS95A | RAF_IS95B | RAF_1xRTT;
private static final int EVDO = RAF_EVDO_0 | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD;
private static final int WCDMA = HS | RAF_UMTS;
+ private static final int LTE = RAF_LTE | RAF_LTE_CA;
/* Phone ID of phone */
private int mPhoneId;
@@ -162,19 +164,19 @@ public class RadioAccessFamily implements Parcelable {
raf = CDMA | EVDO;
break;
case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:
- raf = RAF_LTE | CDMA | EVDO;
+ raf = LTE | CDMA | EVDO;
break;
case RILConstants.NETWORK_MODE_LTE_GSM_WCDMA:
- raf = RAF_LTE | GSM | WCDMA;
+ raf = LTE | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
- raf = RAF_LTE | CDMA | EVDO | GSM | WCDMA;
+ raf = LTE | CDMA | EVDO | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_ONLY:
- raf = RAF_LTE;
+ raf = LTE;
break;
case RILConstants.NETWORK_MODE_LTE_WCDMA:
- raf = RAF_LTE | WCDMA;
+ raf = LTE | WCDMA;
break;
case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
raf = CDMA;
@@ -232,6 +234,7 @@ public class RadioAccessFamily implements Parcelable {
raf = ((WCDMA & raf) > 0) ? (WCDMA | raf) : raf;
raf = ((CDMA & raf) > 0) ? (CDMA | raf) : raf;
raf = ((EVDO & raf) > 0) ? (EVDO | raf) : raf;
+ raf = ((LTE & raf) > 0) ? (LTE | raf) : raf;
return raf;
}
@@ -254,19 +257,19 @@ public class RadioAccessFamily implements Parcelable {
case (CDMA | EVDO):
type = RILConstants.NETWORK_MODE_CDMA;
break;
- case (RAF_LTE | CDMA | EVDO):
+ case (LTE | CDMA | EVDO):
type = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
break;
- case (RAF_LTE | GSM | WCDMA):
+ case (LTE | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
break;
- case (RAF_LTE | CDMA | EVDO | GSM | WCDMA):
+ case (LTE | CDMA | EVDO | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
break;
- case RAF_LTE:
+ case LTE:
type = RILConstants.NETWORK_MODE_LTE_ONLY;
break;
- case (RAF_LTE | WCDMA):
+ case (LTE | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_WCDMA;
break;
case CDMA:
@@ -339,6 +342,7 @@ public class RadioAccessFamily implements Parcelable {
case "CDMA": return CDMA;
case "EVDO": return EVDO;
case "WCDMA": return WCDMA;
+ case "LTE_CA": return RAF_LTE_CA;
default: return RAF_UNKNOWN;
}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1337487..d411376 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -154,6 +154,12 @@ public class ServiceState implements Parcelable {
*/
public static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18;
/**
+ * LTE_CA
+ * @hide
+ */
+ public static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
+
+ /**
* Available registration states for GSM, UMTS and CDMA.
*/
/** @hide */
@@ -728,11 +734,14 @@ public class ServiceState implements Parcelable {
case RIL_RADIO_TECHNOLOGY_GSM:
rtString = "GSM";
break;
+ case RIL_RADIO_TECHNOLOGY_TD_SCDMA:
+ rtString = "TD-SCDMA";
+ break;
case RIL_RADIO_TECHNOLOGY_IWLAN:
rtString = "IWLAN";
break;
- case RIL_RADIO_TECHNOLOGY_TD_SCDMA:
- rtString = "TD-SCDMA";
+ case RIL_RADIO_TECHNOLOGY_LTE_CA:
+ rtString = "LTE_CA";
break;
default:
rtString = "Unexpected";
@@ -1075,6 +1084,8 @@ public class ServiceState implements Parcelable {
return TelephonyManager.NETWORK_TYPE_TD_SCDMA;
case ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN:
return TelephonyManager.NETWORK_TYPE_IWLAN;
+ case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA:
+ return TelephonyManager.NETWORK_TYPE_LTE_CA;
default:
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -1126,7 +1137,9 @@ public class ServiceState implements Parcelable {
|| radioTechnology == RIL_RADIO_TECHNOLOGY_HSPAP
|| radioTechnology == RIL_RADIO_TECHNOLOGY_GSM
|| radioTechnology == RIL_RADIO_TECHNOLOGY_TD_SCDMA
- || radioTechnology == RIL_RADIO_TECHNOLOGY_IWLAN;
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_IWLAN
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA;
+
}
/** @hide */
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index fced667..997b6ff 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -19,6 +19,7 @@ package android.telephony;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemProperties;
import android.telephony.Rlog;
import android.content.res.Resources;
@@ -52,6 +53,7 @@ public class SignalStrength implements Parcelable {
public static final int INVALID = 0x7FFFFFFF;
private static final int RSRP_THRESH_TYPE_STRICT = 0;
+ private static final int RSRP_THRESH_TYPE_CUSTOM = 2;
private static final int[] RSRP_THRESH_STRICT = new int[] {-140, -115, -105, -95, -85, -44};
private static final int[] RSRP_THRESH_LENIENT = new int[] {-140, -128, -118, -108, -98, -44};
@@ -146,11 +148,10 @@ public class SignalStrength implements Parcelable {
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
- int tdScdmaRscp, boolean gsmFlag) {
+ boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
lteRsrq, lteRssnr, lteCqi, gsmFlag);
- mTdScdmaRscp = tdScdmaRscp;
}
/**
@@ -162,10 +163,11 @@ public class SignalStrength implements Parcelable {
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
- boolean gsmFlag) {
+ int tdScdmaRscp, boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
lteRsrq, lteRssnr, lteCqi, gsmFlag);
+ mTdScdmaRscp = tdScdmaRscp;
}
/**
@@ -398,11 +400,12 @@ public class SignalStrength implements Parcelable {
mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
mLteRsrp = ((mLteRsrp >= 44) && (mLteRsrp <= 140)) ? -mLteRsrp : SignalStrength.INVALID;
mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
- mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
+ mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300) && !(mLteRsrq == SignalStrength.INVALID && mLteRssnr == -1)) ? mLteRssnr
: SignalStrength.INVALID;
mTdScdmaRscp = ((mTdScdmaRscp >= 25) && (mTdScdmaRscp <= 120))
? -mTdScdmaRscp : SignalStrength.INVALID;
+
// Cqi no change
if (DBG) log("Signal after validate=" + this);
}
@@ -494,6 +497,16 @@ public class SignalStrength implements Parcelable {
return mLteCqi;
}
+ /** @hide */
+ public boolean needsOldRilFeature(String feature) {
+ String[] features = SystemProperties.get("ro.telephony.ril.config", "").split(",");
+ for (String found: features) {
+ if (found.equals(feature))
+ return true;
+ }
+ return false;
+ }
+
/**
* Retrieve an abstract level value for the overall signal strength.
*
@@ -506,8 +519,9 @@ public class SignalStrength implements Parcelable {
int level = 0;
if (isGsm) {
+ boolean oldRil = needsOldRilFeature("signalstrength");
level = getLteLevel();
- if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+ if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN || oldRil) {
level = getTdScdmaLevel();
if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
level = getGsmLevel();
@@ -539,7 +553,8 @@ public class SignalStrength implements Parcelable {
public int getAsuLevel() {
int asuLevel = 0;
if (isGsm) {
- if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+ boolean oldRil = needsOldRilFeature("signalstrength");
+ if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN || oldRil) {
if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
asuLevel = getGsmAsuLevel();
} else {
@@ -575,8 +590,9 @@ public class SignalStrength implements Parcelable {
int dBm = INVALID;
if(isGsm()) {
+ boolean oldRil = needsOldRilFeature("signalstrength");
dBm = getLteDbm();
- if (dBm == INVALID) {
+ if (dBm == INVALID || oldRil) {
if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
dBm = getGsmDbm();
} else {
@@ -796,6 +812,9 @@ public class SignalStrength implements Parcelable {
int[] threshRsrp;
if (rsrpThreshType == RSRP_THRESH_TYPE_STRICT) {
threshRsrp = RSRP_THRESH_STRICT;
+ } else if (rsrpThreshType == RSRP_THRESH_TYPE_CUSTOM) {
+ threshRsrp = Resources.getSystem().getIntArray(com.android.internal.R.array.
+ config_LTE_RSRP_custom_levels);
} else {
threshRsrp = RSRP_THRESH_LENIENT;
}
@@ -933,7 +952,7 @@ public class SignalStrength implements Parcelable {
return tdScdmaAsuLevel;
}
- /**
+ /**
* @return hash code
*/
@Override
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index d1d6e0d..5e5b70d 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -111,9 +111,14 @@ public class SubscriptionInfo implements Parcelable {
/**
* @hide
*/
+ public int mUserNwMode;
+
+ /**
+ * @hide
+ */
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
- Bitmap icon, int mcc, int mnc, String countryIso) {
+ Bitmap icon, int mcc, int mnc, String countryIso, int userNwMode) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -126,6 +131,7 @@ public class SubscriptionInfo implements Parcelable {
this.mIconBitmap = icon;
this.mMcc = mcc;
this.mMnc = mnc;
+ this.mUserNwMode = userNwMode;
this.mCountryIso = countryIso;
}
@@ -277,6 +283,14 @@ public class SubscriptionInfo implements Parcelable {
}
/**
+ * Returns the User set Network mode.
+ * @hide
+ */
+ public int getUserNwMode() {
+ return this.mUserNwMode;
+ }
+
+ /**
* @return the ISO country code
*/
public String getCountryIso() {
@@ -297,11 +311,12 @@ public class SubscriptionInfo implements Parcelable {
int dataRoaming = source.readInt();
int mcc = source.readInt();
int mnc = source.readInt();
+ int userNwMode = source.readInt();
String countryIso = source.readString();
Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
- nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso);
+ nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, userNwMode);
}
@Override
@@ -323,6 +338,7 @@ public class SubscriptionInfo implements Parcelable {
dest.writeInt(mDataRoaming);
dest.writeInt(mMcc);
dest.writeInt(mMnc);
+ dest.writeInt(mUserNwMode);
dest.writeString(mCountryIso);
mIconBitmap.writeToParcel(dest, flags);
}
@@ -354,6 +370,6 @@ public class SubscriptionInfo implements Parcelable {
+ " displayName=" + mDisplayName + " carrierName=" + mCarrierName
+ " nameSource=" + mNameSource + " iconTint=" + mIconTint
+ " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
- + " mnc " + mMnc + "}";
+ + " mnc " + mMnc + " mUserNwMode=" + mUserNwMode + "}";
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 32b7383..86021e0 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -121,6 +121,39 @@ public class SubscriptionManager {
public static final int SIM_NOT_INSERTED = -1;
/**
+ * The Network mode of SIM/sub.
+ * <P>Type: INTEGER (int)</P>
+ */
+ /** @hide */
+ public static final String NETWORK_MODE = "network_mode";
+
+ /**
+ * The user configured Network mode of SIM/sub.
+ * <P>Type: INTEGER (int)</P>
+ * {@hide}
+ */
+ public static final String USER_NETWORK_MODE = "user_network_mode";
+
+ /** @hide */
+ public static final int DEFAULT_NW_MODE = -1;
+
+ /**
+ * The activation state of SIM/sub.
+ * <P>Type: INTEGER (int)</P>
+ */
+ /** @hide */
+ public static final String SUB_STATE = "sub_state";
+
+ /** @hide */
+ public static final int INACTIVE = 0;
+
+ /** @hide */
+ public static final int ACTIVE = 1;
+
+ /** @hide */
+ public static final int SUB_CONFIGURATION_IN_PROGRESS = 2;
+
+ /**
* TelephonyProvider column name for user displayed name.
* <P>Type: TEXT (String)</P>
*/
@@ -310,6 +343,14 @@ public class SubscriptionManager {
*/
public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts";
+
+
+ /**
+ * TelephonyProvider column name for enable channel60 alert in CB settings
+ *@hide
+ */
+ public static final String CB_CHANNEL_60_ALERT = "enable_channel_60_alerts";
+
/**
* TelephonyProvider column name for CMAS test alert in CB settings
*@hide
@@ -1118,6 +1159,53 @@ public class SubscriptionManager {
}
/** @hide */
+ public static void activateSubId(int subId) {
+ logd("activateSubId sub id = " + subId);
+ try {
+ getISubInfo().activateSubId(subId);
+ } catch (RemoteException ex) {
+ return;
+ }
+ }
+
+ /** @hide */
+ public static void deactivateSubId(int subId) {
+ logd("deactivateSubId sub id = " + subId);
+ try {
+ getISubInfo().deactivateSubId(subId);
+ } catch (RemoteException ex) {
+ return;
+ }
+ }
+
+ /** @hide */
+ public static int getSubState(int subId) {
+ logd("getSubState sub id = " + subId);
+ try {
+ return getISubInfo().getSubState(subId);
+ } catch (RemoteException ex) {
+ return INACTIVE;
+ }
+ }
+
+ /** @hide */
+ public static int setSubState(int subId, int subState) {
+ logd("setSubState sub id = " + subId + " state = " + subState);
+ try {
+ return getISubInfo().setSubState(subId, subState);
+ } catch (RemoteException ex) {
+ return INACTIVE;
+ }
+ }
+
+ /**
+ @hide
+ */
+ private static ISub getISubInfo() {
+ return ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ }
+
+ /** @hide */
public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
int[] subIds = SubscriptionManager.getSubId(phoneId);
if (subIds != null && subIds.length > 0) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 7276980..7afaf7e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,10 +21,12 @@ package android.telephony;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.Manifest;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.ActivityThread;
import android.content.ContentResolver;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
@@ -31,6 +36,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.telecom.PhoneAccount;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.telecom.ITelecomService;
@@ -45,6 +51,7 @@ import com.android.internal.telephony.TelephonyProperties;
import java.io.FileInputStream;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -684,6 +691,11 @@ public class TelephonyManager {
*/
public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_IS_FORWARDED = "is_forwarded";
+
//
//
// Device Info
@@ -761,6 +773,7 @@ public class TelephonyManager {
* @param slotId of which deviceID is returned
*/
public String getDeviceId(int slotId) {
+ android.util.SeempLog.record_str(8, ""+slotId);
// FIXME this assumes phoneId == slotId
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -857,6 +870,7 @@ public class TelephonyManager {
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.
*/
public CellLocation getCellLocation() {
+ android.util.SeempLog.record(49);
try {
ITelephony telephony = getITelephony();
if (telephony == null) {
@@ -954,6 +968,7 @@ public class TelephonyManager {
*/
@Deprecated
public List<NeighboringCellInfo> getNeighboringCellInfo() {
+ android.util.SeempLog.record(50);
try {
ITelephony telephony = getITelephony();
if (telephony == null)
@@ -1204,6 +1219,15 @@ public class TelephonyManager {
return retVal;
}
+ /**
+ * Return if the current radio is LTE on GSM
+ * @hide
+ */
+ public static int getLteOnGsmModeStatic() {
+ return SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_GSM_DEVICE,
+ 0);
+ }
+
//
//
// Current Network
@@ -1380,11 +1404,12 @@ public class TelephonyManager {
public static final int NETWORK_TYPE_HSPAP = 15;
/** Current network is GSM {@hide} */
public static final int NETWORK_TYPE_GSM = 16;
- /** Current network is TD_SCDMA {@hide} */
+ /** Current network is TD_SCDMA {@hide} */
public static final int NETWORK_TYPE_TD_SCDMA = 17;
/** Current network is IWLAN {@hide} */
public static final int NETWORK_TYPE_IWLAN = 18;
-
+ /** Current network is LTE_CA {@hide} */
+ public static final int NETWORK_TYPE_LTE_CA = 19;
/**
* @return the NETWORK_TYPE_xxxx for current data connection.
*/
@@ -1429,10 +1454,12 @@ public class TelephonyManager {
* @see #NETWORK_TYPE_LTE
* @see #NETWORK_TYPE_EHRPD
* @see #NETWORK_TYPE_HSPAP
+ * @see #NETWORK_TYPE_TD_SCDMA
*
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
*/
/** {@hide} */
public int getNetworkType(int subId) {
@@ -1552,6 +1579,21 @@ public class TelephonyManager {
}
}
+ /**
+ * Returns the icc operator numeric for a given subId
+ *
+ */
+ /** {@hide} */
+ public String getIccOperatorNumericForData(int subId) {
+ try{
+ return getITelephony().getIccOperatorNumericForData(subId);
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
/** Unknown network class. {@hide} */
public static final int NETWORK_CLASS_UNKNOWN = 0;
/** Class of broadly defined "2G" networks. {@hide} */
@@ -1589,6 +1631,7 @@ public class TelephonyManager {
return NETWORK_CLASS_3_G;
case NETWORK_TYPE_LTE:
case NETWORK_TYPE_IWLAN:
+ case NETWORK_TYPE_LTE_CA:
return NETWORK_CLASS_4_G;
default:
return NETWORK_CLASS_UNKNOWN;
@@ -1652,6 +1695,8 @@ public class TelephonyManager {
return "TD_SCDMA";
case NETWORK_TYPE_IWLAN:
return "IWLAN";
+ case NETWORK_TYPE_LTE_CA:
+ return "LTE_CA";
default:
return "UNKNOWN";
}
@@ -1957,6 +2002,7 @@ public class TelephonyManager {
*/
/** {@hide} */
public String getSimSerialNumber(int subId) {
+ android.util.SeempLog.record_str(388, ""+subId);
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
@@ -2017,6 +2063,21 @@ public class TelephonyManager {
}
}
+ /**
+ * Return if the current radio is LTE on GSM
+ * @hide
+ */
+ public int getLteOnGsmMode() {
+ try {
+ return getITelephony().getLteOnGsmMode();
+ } catch (RemoteException ex) {
+ return 0;
+ } catch (NullPointerException ex) {
+ // This could happen before phone restarts due to crashing
+ return 0;
+ }
+ }
+
//
//
// Subscriber Info
@@ -2046,6 +2107,7 @@ public class TelephonyManager {
*/
/** {@hide} */
public String getSubscriberId(int subId) {
+ android.util.SeempLog.record_str(389, ""+subId);
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
@@ -2134,6 +2196,7 @@ public class TelephonyManager {
*/
/** {@hide} */
public String getLine1NumberForSubscriber(int subId) {
+ android.util.SeempLog.record_str(9, ""+subId);
String number = null;
try {
ITelephony telephony = getITelephony();
@@ -2931,6 +2994,40 @@ public class TelephonyManager {
}
/**
+ * Allows an application to add a protected sms address if the application has
+ * been granted the permission MODIFY_PROTECTED_SMS_LIST.
+ * @param address
+ * @hide
+ */
+ public void addProtectedSmsAddress(String address) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MODIFY_PROTECTED_SMS_LIST, null);
+ try {
+ getITelephony().addProtectedSmsAddress(address);
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ /**
+ * Allows an application to revoke/remove a protected sms address if the application has been
+ * granted the permission MODIFY_PROTECTED_SMS_LIST.
+ * @param address
+ * @return true if address is successfully removed
+ * @hide
+ */
+ public boolean revokeProtectedSmsAddress(String address) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MODIFY_PROTECTED_SMS_LIST, null);
+ try {
+ return getITelephony().revokeProtectedSmsAddress(address);
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ }
+ return false;
+ }
+
+ /**
* Returns the MMS user agent.
*/
public String getMmsUserAgent() {
@@ -3396,13 +3493,7 @@ public class TelephonyManager {
/** @hide */
public int getSimCount() {
- // FIXME Need to get it from Telephony Dev Controller when that gets implemented!
- // and then this method shouldn't be used at all!
- if(isMultiSimEnabled()) {
- return 2;
- } else {
- return 1;
- }
+ return getPhoneCount();
}
/**
@@ -4198,11 +4289,18 @@ public class TelephonyManager {
public void setDataEnabled(int subId, boolean enable) {
try {
Log.d(TAG, "setDataEnabled: enabled=" + enable);
+ AppOpsManager appOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
+ if (enable) {
+ if (appOps.noteOp(AppOpsManager.OP_DATA_CONNECT_CHANGE) != AppOpsManager.MODE_ALLOWED) {
+ Log.w(TAG, "Permission denied by user.");
+ return;
+ }
+ }
ITelephony telephony = getITelephony();
if (telephony != null)
telephony.setDataEnabled(subId, enable);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setDataEnabled", e);
+ Log.e(TAG, "Error calling setDataEnabled", e);
}
}
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.java b/telephony/java/com/android/ims/ImsCallForwardInfo.java
index 3f8fd19..97dcbd5 100644
--- a/telephony/java/com/android/ims/ImsCallForwardInfo.java
+++ b/telephony/java/com/android/ims/ImsCallForwardInfo.java
@@ -31,6 +31,8 @@ public class ImsCallForwardInfo implements Parcelable {
public int mStatus;
// 0x91: International, 0x81: Unknown
public int mToA;
+ // Service class
+ public int mServiceClass;
// Number (it will not include the "sip" or "tel" URI scheme)
public String mNumber;
// No reply timer for CF
@@ -53,6 +55,7 @@ public class ImsCallForwardInfo implements Parcelable {
out.writeInt(mCondition);
out.writeInt(mStatus);
out.writeInt(mToA);
+ out.writeInt(mServiceClass);
out.writeString(mNumber);
out.writeInt(mTimeSeconds);
}
@@ -62,6 +65,7 @@ public class ImsCallForwardInfo implements Parcelable {
return super.toString() + ", Condition: " + mCondition
+ ", Status: " + ((mStatus == 0) ? "disabled" : "enabled")
+ ", ToA: " + mToA + ", Number=" + mNumber
+ + ", Service Class: " + mServiceClass
+ ", Time (seconds): " + mTimeSeconds;
}
@@ -69,6 +73,7 @@ public class ImsCallForwardInfo implements Parcelable {
mCondition = in.readInt();
mStatus = in.readInt();
mToA = in.readInt();
+ mServiceClass = in.readInt();
mNumber = in.readString();
mTimeSeconds = in.readInt();
}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 5f84e0c..50ee543 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -188,6 +188,7 @@ public class ImsCallProfile implements Parcelable {
public static final String EXTRA_CODEC = "Codec";
public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+ public static final String EXTRA_IS_CALL_PULL = "CallPull";
/**
* Extra key which the RIL can use to indicate the radio technology used for a call.
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 2769a2b..85ec162 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -84,6 +84,8 @@ public class ImsReasonInfo implements Parcelable {
public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147;
// IMS call is already terminated (in TERMINATED state)
public static final int CODE_LOCAL_CALL_TERMINATED = 148;
+ // Handover not feasible
+ public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149;
/**
* TIMEOUT (IMS -> Telephony)
@@ -153,6 +155,9 @@ public class ImsReasonInfo implements Parcelable {
public static final int CODE_SIP_USER_REJECTED = 361;
// Others
public static final int CODE_SIP_GLOBAL_ERROR = 362;
+ // Emergency failure
+ public static final int CODE_EMERGENCY_TEMP_FAILURE = 363;
+ public static final int CODE_EMERGENCY_PERM_FAILURE = 364;
/**
* MEDIA (IMS -> Telephony)
@@ -236,6 +241,24 @@ public class ImsReasonInfo implements Parcelable {
public static final int CODE_ANSWERED_ELSEWHERE = 1014;
/**
+ * For VICE - Call Pull request has failed
+ */
+ public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015;
+
+ /**
+ * For VICE - Call has been pulled from primary to secondary
+ */
+ public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016;
+
+ /**
+ * Supplementary services (HOLD/RESUME) failure error codes.
+ * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+ */
+ public static final int CODE_SUPP_SVC_FAILED = 1201;
+ public static final int CODE_SUPP_SVC_CANCELLED = 1202;
+ public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203;
+
+ /**
* Network string error messages.
* mExtraMessage may have these values.
*/
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.java b/telephony/java/com/android/ims/ImsStreamMediaProfile.java
index 359b270..216cef5 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/com/android/ims/ImsStreamMediaProfile.java
@@ -51,6 +51,16 @@ public class ImsStreamMediaProfile implements Parcelable {
public static final int AUDIO_QUALITY_GSM_EFR = 8;
public static final int AUDIO_QUALITY_GSM_FR = 9;
public static final int AUDIO_QUALITY_GSM_HR = 10;
+ public static final int AUDIO_QUALITY_G711U = 11;
+ public static final int AUDIO_QUALITY_G723 = 12;
+ public static final int AUDIO_QUALITY_G711A = 13;
+ public static final int AUDIO_QUALITY_G722 = 14;
+ public static final int AUDIO_QUALITY_G711AB = 15;
+ public static final int AUDIO_QUALITY_G729 = 16;
+ public static final int AUDIO_QUALITY_EVS_NB = 17;
+ public static final int AUDIO_QUALITY_EVS_WB = 18;
+ public static final int AUDIO_QUALITY_EVS_SWB = 19;
+ public static final int AUDIO_QUALITY_EVS_FB = 20;
/**
* Video information
@@ -76,7 +86,7 @@ public class ImsStreamMediaProfile implements Parcelable {
}
public ImsStreamMediaProfile() {
- mAudioQuality = AUDIO_QUALITY_AMR_WB;
+ mAudioQuality = AUDIO_QUALITY_NONE;
mAudioDirection = DIRECTION_SEND_RECEIVE;
mVideoQuality = VIDEO_QUALITY_NONE;
mVideoDirection = DIRECTION_INVALID;
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 23a69d1..507a293 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -17,6 +17,7 @@
package com.android.ims.internal;
import com.android.ims.ImsReasonInfo;
+
/**
* A listener type for receiving notifications about the changes to
* the IMS connection(registration).
@@ -26,30 +27,36 @@ import com.android.ims.ImsReasonInfo;
interface IImsRegistrationListener {
/**
* Notifies the application when the device is connected to the IMS network.
+ *
+ * @param imsRadioTech the radio access technology. Valid values are {@code
+ * RIL_RADIO_TECHNOLOGY_*} defined in {@link ServiceState}.
*/
- void registrationConnected();
+ void registrationConnected(int imsRadioTech) = 0;
/**
* Notifies the application when the device is trying to connect the IMS network.
+ *
+ * @param imsRadioTech the radio access technology. Valid values are {@code
+ * RIL_RADIO_TECHNOLOGY_*} defined in {@link ServiceState}.
*/
- void registrationProgressing();
+ void registrationProgressing(int imsRadioTech) = 1;
/**
* Notifies the application when the device is disconnected from the IMS network.
*/
- void registrationDisconnected(in ImsReasonInfo imsReasonInfo);
+ void registrationDisconnected(in ImsReasonInfo imsReasonInfo) = 2;
/**
* Notifies the application when its suspended IMS connection is resumed,
* meaning the connection now allows throughput.
*/
- void registrationResumed();
+ void registrationResumed() = 3;
/**
* Notifies the application when its current IMS connection is suspended,
* meaning there is no data throughput.
*/
- void registrationSuspended();
+ void registrationSuspended() = 4;
/**
* Notifies the application when its current IMS connection is updated
@@ -60,7 +67,7 @@ interface IImsRegistrationListener {
* If {@code event} is 0, meaning the specified service is removed from the IMS connection.
* Else ({@code event} is 1), meaning the specified service is added to the IMS connection.
*/
- void registrationServiceCapabilityChanged(int serviceClass, int event);
+ void registrationServiceCapabilityChanged(int serviceClass, int event) = 5;
/**
* Notifies the application when features on a particular service enabled or
@@ -71,11 +78,17 @@ interface IImsRegistrationListener {
* @param disabledFeatures features disabled as defined in com.android.ims.ImsConfig#FeatureConstants.
*/
void registrationFeatureCapabilityChanged(int serviceClass,
- in int[] enabledFeatures, in int[] disabledFeatures);
+ in int[] enabledFeatures, in int[] disabledFeatures) = 6;
/**
* Updates the application with the waiting voice message count.
* @param count The number of waiting voice messages.
*/
- void voiceMessageCountUpdate(int count);
+ void voiceMessageCountUpdate(int count) = 7;
+
+ /**
+ * Compatibility with AOSP
+ */
+ void registrationConnected() = 8;
+ void registrationProgressing() = 9;
}
diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl
index 4ab5ee3..2784653 100644
--- a/telephony/java/com/android/ims/internal/IImsUt.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUt.aidl
@@ -111,4 +111,9 @@ interface IImsUt {
* Sets the listener.
*/
void setListener(in IImsUtListener listener);
+
+ /**
+ * Retrieves the configuration of the call forward for specified service class.
+ */
+ int queryCFForServiceClass(int condition, String number, int serviceClass);
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index be7e702..6e1a004 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -165,6 +165,7 @@ public class CallerInfo {
* number. The returned CallerInfo is null if no number is supplied.
*/
public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) {
+ android.util.SeempLog.record_uri(12, contactRef);
CallerInfo info = new CallerInfo();
info.photoResource = 0;
info.phoneLabel = null;
@@ -325,6 +326,7 @@ public class CallerInfo {
* with all relevant fields empty or null.
*/
public static CallerInfo getCallerInfo(Context context, String number, int subId) {
+ android.util.SeempLog.record_str(12, "number="+number+",subId="+subId);
if (TextUtils.isEmpty(number)) {
return null;
diff --git a/telephony/java/com/android/internal/telephony/IExtTelephony.aidl b/telephony/java/com/android/internal/telephony/IExtTelephony.aidl
new file mode 100644
index 0000000..f98a0d8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IExtTelephony.aidl
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package com.android.internal.telephony;
+
+
+/**
+ * Interface used to interact with the telephony framework for
+ * Telephony value adds.
+ * {@hide}
+ */
+interface IExtTelephony {
+
+ /**
+ * Returns the current SIM Manual provision status.
+ * @param slotId user preferred slotId.
+ * @return Card provision status as integer, below are
+ * possible return values.
+ * '0' - returned if Uicc Card is not provisioned.
+ * '1' - returned if Uicc Card provisioned.
+ * '-1'- returned if there is an error @ below layers OR
+ * if framework does not received info from Modem yet.
+ * '-2' returned when SIM card is not present in slot.
+ * Requires Permission: android.Manifest.permission.READ_PHONE_STATE
+ */
+ int getCurrentUiccCardProvisioningStatus(int slotId);
+
+ /**
+ * Returns the user preferred Uicc card provision status.
+ * @param slotId user preferred slotId.
+ * @return User preference value as integer, below are
+ * possible return values.
+ * '0' - returned if Uicc Card is not provisioned.
+ * '1' - returned if Uicc Card provisioned.
+ * '-1'- returned if there is an error @ below layers OR
+ * if framework does not received info from Modem yet.
+ * '-2' returned when SIM card is not present in slot.
+ * Requires Permission: android.Manifest.permission.READ_PHONE_STATE
+ */
+ int getUiccCardProvisioningUserPreference(int slotId);
+
+ /**
+ * Activates the Uicc card.
+ * @param slotId user preferred slotId.
+ * @return Uicc card activation result as Integer, below are
+ * supported return values:
+ * '0' - Success
+ * '-1' -Generic Failure
+ * '-2' -Invalid input
+ * '-3 -Another request in progress
+ * Requires Permission: android.Manifest.permission.MODIFY_PHONE_STATE
+ */
+ int activateUiccCard(int slotId);
+
+ /**
+ * Deactivates UICC card.
+ * @param slotId user preferred slotId.
+ * @return Uicc card deactivation result as Integer, below are
+ * supported return values:
+ * '0' - Success
+ * '-1' -Generic Failure
+ * '-2' -Invalid input
+ * '-3 -Another request in progress
+ * Requires Permission: android.Manifest.permission.MODIFY_PHONE_STATE
+ */
+ int deactivateUiccCard(int slotId);
+
+ /**
+ * Check for Sms Prompt is Enabled or Not.
+ * @return
+ * true - Sms Prompt is Enabled
+ * false - Sms prompt is Disabled
+ * Requires Permission: android.Manifest.permission.READ_PHONE_STATE
+ */
+ boolean isSMSPromptEnabled();
+
+ /**
+ * Enable/Disable Sms prompt option.
+ * @param - enabled
+ * true - to enable Sms prompt
+ * false - to disable Sms prompt
+ * Requires Permission: android.Manifest.permission.MODIFY_PHONE_STATE
+ */
+ void setSMSPromptEnabled(boolean enabled);
+
+ /**
+ * Get logical phone id for Emergency call.
+ * @param - void
+ * @return phone id
+ */
+ int getPhoneIdForECall();
+
+ /**
+ * Check is FDN is enabled or not.
+ * @param - void
+ * @return true or false
+ */
+ boolean isFdnEnabled();
+}
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 70a8653..c7e13aa 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -187,6 +187,53 @@ interface ISms {
in PendingIntent deliveryIntent);
/**
+ * Send an SMS with options using Subscription Id.
+ *
+ * @param subId the subId on which the SMS has to be sent.
+ * @param destAddr the address to send the message to
+ * @param scAddr the SMSC to send the message through, or NULL for the
+ * default SMSC
+ * @param text the body of the message to send
+ * @param sentIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is sucessfully sent, or failed.
+ * The result code will be <code>Activity.RESULT_OK<code> for success,
+ * or one of these errors:<br>
+ * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+ * <code>RESULT_ERROR_RADIO_OFF</code><br>
+ * <code>RESULT_ERROR_NULL_PDU</code><br>
+ * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+ * the extra "errorCode" containing a radio technology specific value,
+ * generally only useful for troubleshooting.<br>
+ * The per-application based SMS control checks sentIntent. If sentIntent
+ * is NULL the caller will be checked against all unknown applications,
+ * which cause smaller number of SMS to be sent in checking period.
+ * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is delivered to the recipient. The
+ * raw pdu of the status report is in the extended data ("pdu").
+ * @param priority Priority level of the message
+ * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
+ * ---------------------------------
+ * PRIORITY | Level of Priority
+ * ---------------------------------
+ * '00' | Normal
+ * '01' | Interactive
+ * '10' | Urgent
+ * '11' | Emergency
+ * ----------------------------------
+ * Any Other values included Negative considered as Invalid Priority Indicator of the message.
+ * @param isExpectMore is a boolean to indicate the sending message is multi segmented or not.
+ * @param validityPeriod Validity Period of the message in mins.
+ * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
+ * Validity Period(Minimum) -> 5 mins
+ * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
+ * Any Other values included Negative considered as Invalid Validity Period of the message.
+ */
+ void sendTextForSubscriberWithOptions(in int subId, String callingPkg, in String destAddr,
+ in String scAddr, in String text, in PendingIntent sentIntent,
+ in PendingIntent deliveryIntent, in int priority, in boolean isExpectMore,
+ in int validityPeriod);
+
+ /**
* Inject an SMS PDU into the android platform.
*
* @param subId the subId on which the SMS has to be injected.
@@ -234,6 +281,51 @@ interface ISms {
in List<PendingIntent> deliveryIntents, in boolean persistMessageForNonDefaultSmsApp);
/**
+ * Send a multi-part text based SMS with options using Subscription Id.
+ *
+ * @param subId the subId on which the SMS has to be sent.
+ * @param destinationAddress the address to send the message to
+ * @param scAddress is the service center address or null to use
+ * the current default SMSC
+ * @param parts an <code>ArrayList</code> of strings that, in order,
+ * comprise the original message
+ * @param sentIntents if not null, an <code>ArrayList</code> of
+ * <code>PendingIntent</code>s (one for each message part) that is
+ * broadcast when the corresponding message part has been sent.
+ * The result code will be <code>Activity.RESULT_OK<code> for success,
+ * or one of these errors:
+ * <code>RESULT_ERROR_GENERIC_FAILURE</code>
+ * <code>RESULT_ERROR_RADIO_OFF</code>
+ * <code>RESULT_ERROR_NULL_PDU</code>.
+ * @param deliveryIntents if not null, an <code>ArrayList</code> of
+ * <code>PendingIntent</code>s (one for each message part) that is
+ * broadcast when the corresponding message part has been delivered
+ * to the recipient. The raw pdu of the status report is in the
+ * extended data ("pdu").
+ * @param priority Priority level of the message
+ * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
+ * ---------------------------------
+ * PRIORITY | Level of Priority
+ * ---------------------------------
+ * '00' | Normal
+ * '01' | Interactive
+ * '10' | Urgent
+ * '11' | Emergency
+ * ----------------------------------
+ * Any Other values included Negative considered as Invalid Priority Indicator of the message.
+ * @param isExpectMore is a boolean to indicate the sending message is multi segmented or not.
+ * @param validityPeriod Validity Period of the message in mins.
+ * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
+ * Validity Period(Minimum) -> 5 mins
+ * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
+ * Any Other values included Negative considered as Invalid Validity Period of the message.
+ */
+ void sendMultipartTextForSubscriberWithOptions(in int subId, String callingPkg,
+ in String destinationAddress, in String scAddress, in List<String> parts,
+ in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents,
+ in int priority, in boolean isExpectMore, in int validityPeriod);
+
+ /**
* Enable reception of cell broadcast (SMS-CB) messages with the given
* message identifier and RAN type. The RAN type specify this message ID
* belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients
@@ -375,13 +467,18 @@ interface ISms {
*/
String getImsSmsFormatForSubscriber(int subId);
- /*
+ /**
* Get SMS prompt property, enabled or not
* @return true if enabled, false otherwise
*/
boolean isSMSPromptEnabled();
/**
+ * Set SMS prompt property, enabled or not
+ */
+ void setSMSPromptEnabled(boolean bool);
+
+ /**
* Send a system stored text message.
*
* This is used for sending a previously sent, but failed-to-send, message or
@@ -447,4 +544,12 @@ interface ISms {
void sendStoredMultipartText(int subId, String callingPkg, in Uri messageUri,
String scAddress, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents);
+
+ /**
+ * Get the capacity count of sms on Icc card.
+ *
+ * @param subId for subId which getSmsCapacityOnIcc is queried.
+ * @return capacity of ICC
+ */
+ int getSmsCapacityOnIccForSubscriber(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index f6aef08..1323258 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -183,4 +183,12 @@ interface ISub {
int getSimStateForSlotIdx(int slotIdx);
boolean isActiveSubId(int subId);
+
+ void activateSubId(int subId);
+
+ void deactivateSubId(int subId);
+
+ int setSubState(int subId, int subStatus);
+
+ int getSubState(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index dcece26..c3db8c2 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -488,6 +488,13 @@ interface ITelephony {
int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage);
/**
+ * Return icc operator numeric for given subId
+ * @param subId user preferred subId.
+ * Returns icc operator numeric
+ */
+ String getIccOperatorNumericForData(int subId);
+
+ /**
* Return true if an ICC card is present
*/
boolean hasIccCard();
@@ -531,6 +538,22 @@ interface ITelephony {
*/
void setCellInfoListRate(int rateInMillis);
+
+ /**
+ * Return if the current radio is LTE on GSM
+ */
+ int getLteOnGsmMode();
+
+ /**
+ * Adds a protected sms address to the {@link Settings.Secure.PROTECTED_SMS_ADDRESSES}
+ */
+ void addProtectedSmsAddress(String address);
+
+ /**
+ * Revokes a protected sms address from {@link Settings.Secure.PROTECTED_SMS_ADDRESSES}
+ */
+ boolean revokeProtectedSmsAddress(String address);
+
/**
* get default sim
* @return sim id
@@ -547,6 +570,18 @@ interface ITelephony {
*/
IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID);
+
+ /**
+ * Opens a logical channel to the ICC card for a particular subId.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHO command.
+ *
+ * @param subId user preferred subId.
+ * @param AID Application id. See ETSI 102.221 and 101.220.
+ * @return an IccOpenLogicalChannelResponse object.
+ */
+ IccOpenLogicalChannelResponse iccOpenLogicalChannelUsingSubId(int subId, String AID);
+
/**
* Closes a previously opened logical channel to the ICC card.
*
@@ -559,6 +594,19 @@ interface ITelephony {
boolean iccCloseLogicalChannel(int channel);
/**
+ * Closes a previously opened logical channel to the ICC card for a
+ * particular subId.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHC command.
+ *
+ * @param subId user preferred subId.
+ * @param channel is the channel id to be closed as retruned by a
+ * successful iccOpenLogicalChannel.
+ * @return true if the channel was closed successfully.
+ */
+ boolean iccCloseLogicalChannelUsingSubId(int subId, int channel);
+
+ /**
* Transmit an APDU to the ICC card over a logical channel.
*
* Input parameters equivalent to TS 27.007 AT+CGLA command.
@@ -579,6 +627,28 @@ interface ITelephony {
int p1, int p2, int p3, String data);
/**
+ * Transmit an APDU to the ICC card over a logical channel for a
+ * particular subId.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CGLA command.
+ *
+ * @param subId user preferred subId.
+ * @param channel is the channel id to be closed as retruned by a
+ * successful iccOpenLogicalChannel.
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end.
+ */
+ String iccTransmitApduLogicalChannelUsingSubId(int subId, int channel, int cla,
+ int instruction, int p1, int p2, int p3, String data);
+
+ /**
* Transmit an APDU to the ICC card over the basic channel.
*
* Input parameters equivalent to TS 27.007 AT+CSIM command.
@@ -597,6 +667,26 @@ interface ITelephony {
int p1, int p2, int p3, String data);
/**
+ * Transmit an APDU to the ICC card over the basic channel for a particular
+ * subId.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CSIM command.
+ *
+ * @param subId user preferred subId.
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end.
+ */
+ String iccTransmitApduBasicChannelUsingSubId(int subId, int cla, int instruction,
+ int p1, int p2, int p3, String data);
+
+ /**
* Returns the response APDU for a command APDU sent through SIM_IO.
*
* @param fileID
@@ -611,6 +701,22 @@ interface ITelephony {
String filePath);
/**
+ * Returns the response APDU for a command APDU sent through SIM_IO
+ * for a particular subId.
+ *
+ * @param subId user preferred subId.
+ * @param fileID
+ * @param command
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command.
+ * @param filePath
+ * @return The APDU response.
+ */
+ byte[] iccExchangeSimIOUsingSubId(int subId, int fileID, int command, int p1, int p2,
+ int p3, String filePath);
+
+ /**
* Send ENVELOPE to the SIM and returns the response.
*
* @param contents String containing SAT/USAT response in hexadecimal
@@ -1005,4 +1111,15 @@ interface ITelephony {
* Return the modem activity info.
*/
ModemActivityInfo getModemActivityInfo();
+
+ /**
+ * Get ATR (Answer To Reset; as per ISO/IEC 7816-4) from SIM card
+ */
+ byte[] getAtr();
+
+ /**
+ * Get ATR (Answer To Reset; as per ISO/IEC 7816-4) from SIM card
+ * for a particular subId.
+ */
+ byte[] getAtrUsingSubId(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
index a29d7c1..7db6600 100644
--- a/telephony/java/com/android/internal/telephony/OperatorInfo.java
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -33,6 +33,7 @@ public class OperatorInfo implements Parcelable {
private String mOperatorAlphaLong;
private String mOperatorAlphaShort;
private String mOperatorNumeric;
+ private String mRadioTech;
private State mState = State.UNKNOWN;
@@ -57,6 +58,11 @@ public class OperatorInfo implements Parcelable {
return mState;
}
+ public String
+ getRadioTech() {
+ return mRadioTech;
+ }
+
OperatorInfo(String operatorAlphaLong,
String operatorAlphaShort,
String operatorNumeric,
@@ -65,6 +71,14 @@ public class OperatorInfo implements Parcelable {
mOperatorAlphaLong = operatorAlphaLong;
mOperatorAlphaShort = operatorAlphaShort;
mOperatorNumeric = operatorNumeric;
+ mRadioTech = "";
+ /* operatorNumeric format: PLMN+RAT or PLMN */
+ if (null != operatorNumeric) {
+ String values[] = operatorNumeric.split("\\+");
+ mOperatorNumeric = values[0];
+ if (values.length > 1)
+ mRadioTech = values[1];
+ }
mState = state;
}
@@ -108,6 +122,7 @@ public class OperatorInfo implements Parcelable {
return "OperatorInfo " + mOperatorAlphaLong
+ "/" + mOperatorAlphaShort
+ "/" + mOperatorNumeric
+ + "/" + mRadioTech
+ "/" + mState;
}
@@ -132,7 +147,7 @@ public class OperatorInfo implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mOperatorAlphaLong);
dest.writeString(mOperatorAlphaShort);
- dest.writeString(mOperatorNumeric);
+ dest.writeString(mOperatorNumeric + "+" + mRadioTech);
dest.writeSerializable(mState);
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 8bc1402..e612be3 100644..100755
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -184,7 +184,8 @@ public class PhoneConstants {
public enum CardUnavailableReason {
REASON_CARD_REMOVED,
REASON_RADIO_UNAVAILABLE,
- REASON_SIM_REFRESH_RESET
+ REASON_SIM_REFRESH_RESET,
+ REASON_APM_SIM_POWER_DOWN
};
// Initial MTU value.
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 7088be8..af79ff8 100644..100755
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -77,7 +77,7 @@ public interface RILConstants {
int SIM_SAP_MSG_SIZE_TOO_SMALL = 34;
int SIM_SAP_CONNECT_OK_CALL_ONGOING = 35;
int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not supported */
-
+ int INVALID_PARAMETER = 37;
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
@@ -334,6 +334,7 @@ cat include/telephony/ril.h | \
int RIL_REQUEST_STOP_LCE = 133;
int RIL_REQUEST_PULL_LCEDATA = 134;
int RIL_REQUEST_GET_ACTIVITY_INFO = 135;
+ int RIL_REQUEST_SIM_GET_ATR = 136;
int RIL_UNSOL_RESPONSE_BASE = 1000;
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
@@ -382,4 +383,6 @@ cat include/telephony/ril.h | \
int RIL_UNSOL_ON_SS = 1043;
int RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1044;
int RIL_UNSOL_LCEDATA_RECV = 1045;
+
+ int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; /* Samsung STK */
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 645c3a1..73e778c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -88,6 +88,11 @@ public interface TelephonyProperties
*/
static final String PROPERTY_LTE_ON_CDMA_DEVICE = "telephony.lteOnCdmaDevice";
+ /**
+ * {@see BaseCommands#getLteOnGsmMode()}
+ */
+ static final String PROPERTY_LTE_ON_GSM_DEVICE = "telephony.lteOnGsmDevice";
+
static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type";
//****** SIM Card
@@ -217,4 +222,44 @@ public interface TelephonyProperties
* or Earpiece, based on the default audio routing strategy.
*/
static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output";
+
+ /**
+ * Used when Presence app sends Dial intent with specific schema
+ * If true: skip schema parsing and use Tel schema
+ * If false: parse schema
+ */
+ static final String EXTRA_SKIP_SCHEMA_PARSING =
+ "org.codeaurora.extra.SKIP_SCHEMA_PARSING";
+
+ /**
+ * For Group Conference Calling
+ * If true: isConferenceUri in Dial is set to true,
+ * which indicates that Dial is for Conference Calling
+ * If false: above is set to false
+ */
+ static final String EXTRAS_IS_CONFERENCE_URI = "isConferenceUri";
+
+ /**
+ * For Group Conference Dialing Feature
+ * If true: Dial intent triggered from Group Conference Calling screen
+ * if false: normal dial
+ */
+ static final String EXTRA_DIAL_CONFERENCE_URI =
+ "org.codeaurora.extra.DIAL_CONFERENCE_URI";
+
+ /**
+ * For Add Participant Feature
+ * If true: Dial intent triggered from Dialpad is for AddParticipant
+ * if false: normal dial
+ */
+ static final String ADD_PARTICIPANT_KEY = "add_participant";
+
+ /**
+ * For VICE Feature
+ * If true: Dial intent is for call pull functionality
+ * if false: normal dial
+ */
+ static final String EXTRA_IS_CALL_PULL =
+ "org.codeaurora.extra.IS_CALL_PULL";
+
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index e09d124..d530491 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -98,6 +98,12 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public void recreateTheme() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public ClassLoader getClassLoader() {
throw new UnsupportedOperationException();
@@ -645,6 +651,19 @@ public class MockContext extends Context {
/** {@hide} */
@Override
+ public Context createPackageContextAsUser(String packageName, String themePackageName,
+ int flags, UserHandle user) throws PackageManager.NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@hide} */
+ public Context createApplicationContext(ApplicationInfo application,
+ String themePackageName, int flags) throws PackageManager.NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@hide} */
+ @Override
public int getUserId() {
throw new UnsupportedOperationException();
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 1ff621a..d3e2bfd 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -510,6 +510,27 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public Resources getThemedResourcesForApplication(ApplicationInfo app, String themePkgName)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ /** @hide */
+ @Override
+ public Resources getThemedResourcesForApplication(String appPackageName, String themePkgName)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ /** @hide */
+ @Override
+ public Resources getThemedResourcesForApplicationAsUser(String appPackageName,
+ String themePkgName, int userId) throws NameNotFoundException {
+ return null;
+ }
+
@Override
public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
throw new UnsupportedOperationException();
@@ -875,6 +896,22 @@ public class MockPackageManager extends PackageManager {
* @hide
*/
@Override
+ public void setComponentProtectedSetting(ComponentName componentName, boolean newState) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean isComponentProtected(String callingPackage, ComponentName componentName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public void installPackage(Uri packageURI, PackageInstallObserver observer,
int flags, String installerPackageName) {
throw new UnsupportedOperationException();
@@ -942,4 +979,20 @@ public class MockPackageManager extends PackageManager {
public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public void updateIconMaps(String pkgName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public int processThemeResources(String themePkgName) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/ThemeTests/cm11_to_cm12/downgrade_to_cm11.sh b/tests/ThemeTests/cm11_to_cm12/downgrade_to_cm11.sh
new file mode 100755
index 0000000..9f8a2c6
--- /dev/null
+++ b/tests/ThemeTests/cm11_to_cm12/downgrade_to_cm11.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+#****************************************************************************************
+# Run this script to move your CM12 device move back to a CM11 state. This is
+# useful when you want to manually test CM11 to CM12 upgrade without reflashing the device
+#***************************************************************************************
+
+#Delete all themes related data
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "DELETE FROM secure WHERE name='themeConfig'";
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "DELETE FROM secure WHERE name='theme_prev_boot_api_level'";
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "pragma user_version=115"
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "DELETE FROM secure WHERE name='default_theme_package'"
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "DELETE FROM secure WHERE name='default_theme_components'"
+
+#HEXO Config (Comment HOLO if you use this)
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO secure (name,value) VALUES('themeConfig','{\"default\":{\"mOverlayPkgName\":\"com.cyngn.hexo\",\"mIconPkgName\":\"com.tung91.mianogen\",\"mFontPkgName\":\"bigwave.thyrus.darkuinte\"}}')";
+
+#HOLO Config (Comment HEXO if you use this)
+#adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO secure (name,value) VALUES('themeConfig','{\"default\":{\"mOverlayPkgName\":\"holo\",\"mIconPkgName\":\"com.tung91.mianogen\",\"mFontPkgName\":\"bigwave.thyrus.darkuinte\"}}')";
+
+
+#Default Theme Package
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO secure (name,value) VALUES('default_theme_package', 'com.cyngn.hexo')"
+adb shell 'sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO secure (name,value) VALUES(\"default_theme_components\", \"mods_overlays\")"'
+
+#Print out the db
+adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "SELECT * from secure"
+
+
+#ThemesProvider's default theme is called "Holo"
+adb shell sqlite3 /data/data/org.cyanogenmod.themes.provider/databases/themes.db "UPDATE themes SET pkg_name='holo', title='Holo' WHERE pkg_name='system'"
+adb shell sqlite3 /data/data/org.cyanogenmod.themes.provider/databases/themes.db "pragma user_version=10"
+
+adb shell sqlite3 /data/data/org.cyanogenmod.themes.provider/databases/themes.db "SELECT * FROM themes"
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index d346731..1a5d512 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1048,8 +1048,23 @@ ssize_t AaptAssets::slurpFromArgs(Bundle* bundle)
goto bail;
}
totalCount += count;
- }
- else {
+ } else if (type == kFileTypeRegular) {
+ ZipFile* zip = new ZipFile;
+ status_t err = zip->open(String8(res), ZipFile::kOpenReadOnly);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "error opening zip file %s\n", res);
+ delete zip;
+ totalCount = -1;
+ goto bail;
+ }
+
+ count = current->slurpResourceZip(bundle, zip, res);
+ delete zip;
+ if (count < 0) {
+ totalCount = count;
+ goto bail;
+ }
+ } else {
fprintf(stderr, "ERROR: '%s' is not a directory\n", res);
return UNKNOWN_ERROR;
}
@@ -1214,96 +1229,90 @@ bail:
}
ssize_t
-AaptAssets::slurpResourceZip(Bundle* /* bundle */, const char* filename)
+AaptAssets::slurpResourceZip(Bundle* bundle, ZipFile* zip, const char* fullZipPath)
{
+ status_t err = NO_ERROR;
int count = 0;
SortedVector<AaptGroupEntry> entries;
- ZipFile* zip = new ZipFile;
- status_t err = zip->open(filename, ZipFile::kOpenReadOnly);
- if (err != NO_ERROR) {
- fprintf(stderr, "error opening zip file %s\n", filename);
- count = err;
- delete zip;
- return -1;
- }
-
const int N = zip->getNumEntries();
for (int i=0; i<N; i++) {
ZipEntry* entry = zip->getEntryByIndex(i);
- if (entry->getDeleted()) {
+
+ if (!isEntryValid(bundle, entry)) {
continue;
}
- String8 entryName(entry->getFileName());
+ String8 entryName(entry->getFileName()); //ex: /res/drawable/foo.png
+ String8 entryLeaf = entryName.getPathLeaf(); //ex: foo.png
+ String8 entryDirFull = entryName.getPathDir(); //ex: res/drawable
+ String8 entryDir = entryDirFull.getPathLeaf(); //ex: drawable
- String8 dirName = entryName.getPathDir();
- sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName);
+ err = addEntry(entryName, entryLeaf, entryDirFull, entryDir, String8(fullZipPath), 0);
+ if (err) continue;
- String8 resType;
- AaptGroupEntry kind;
+ count++;
+ }
- String8 remain;
- if (entryName.walkPath(&remain) == kResourceDir) {
- // these are the resources, pull their type out of the directory name
- kind.initFromDirName(remain.walkPath().string(), &resType);
- } else {
- // these are untyped and don't have an AaptGroupEntry
- }
- if (entries.indexOf(kind) < 0) {
- entries.add(kind);
- mGroupEntries.add(kind);
- }
+ return count;
+}
- // use the one from the zip file if they both exist.
- dir->removeFile(entryName.getPathLeaf());
+status_t
+AaptAssets::addEntry(const String8& entryName, const String8& entryLeaf,
+ const String8& /* entryDirFull */, const String8& entryDir,
+ const String8& zipFile, int compressionMethod)
+{
+ AaptGroupEntry group;
+ String8 resType;
+ bool b = group.initFromDirName(entryDir, &resType);
+ if (!b) {
+ fprintf(stderr, "invalid resource directory name: %s\n", entryDir.string());
+ return -1;
+ }
- sp<AaptFile> file = new AaptFile(entryName, kind, resType);
- status_t err = dir->addLeafFile(entryName.getPathLeaf(), file);
- if (err != NO_ERROR) {
- fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.string());
- count = err;
- goto bail;
- }
- file->setCompressionMethod(entry->getCompressionMethod());
+ //This will do a cached lookup as well
+ sp<AaptDir> dir = makeDir(resType); //Does lookup as well on mdirs
+ sp<AaptFile> file = new AaptFile(entryName, group, resType, zipFile);
+ file->setCompressionMethod(compressionMethod);
-#if 0
- if (entryName == "AndroidManifest.xml") {
- printf("AndroidManifest.xml\n");
- }
- printf("\n\nfile: %s\n", entryName.string());
-#endif
-
- size_t len = entry->getUncompressedLen();
- void* data = zip->uncompress(entry);
- void* buf = file->editData(len);
- memcpy(buf, data, len);
-
-#if 0
- const int OFF = 0;
- const unsigned char* p = (unsigned char*)data;
- const unsigned char* end = p+len;
- p += OFF;
- for (int i=0; i<32 && p < end; i++) {
- printf("0x%03x ", i*0x10 + OFF);
- for (int j=0; j<0x10 && p < end; j++) {
- printf(" %02x", *p);
- p++;
- }
- printf("\n");
- }
-#endif
+ dir->addLeafFile(entryLeaf, file);
- free(data);
+ sp<AaptDir> rdir = resDir(resType);
+ if (rdir == NULL) {
+ mResDirs.add(dir);
+ }
- count++;
+ return NO_ERROR;
+}
+
+bool AaptAssets::isEntryValid(Bundle* bundle, ZipEntry* entry) {
+ if (entry == NULL) {
+ return false;
}
-bail:
- delete zip;
- return count;
+ if (entry->getDeleted()) {
+ return false;
+ }
+
+ // Entries that are not inside the internal zip path can be ignored
+ if (bundle->getInternalZipPath()) {
+ bool prefixed = (strncmp(entry->getFileName(),
+ bundle->getInternalZipPath(),
+ strlen(bundle->getInternalZipPath())) == 0);
+ if (!prefixed) {
+ return false;
+ }
+ }
+
+ //Do not process directories
+ if (String8(entry->getFileName()).size() == 0) {
+ return false;
+ }
+
+ return true;
}
+
status_t AaptAssets::filter(Bundle* bundle)
{
WeakResourceFilter reqFilter;
@@ -1530,7 +1539,7 @@ status_t AaptAssets::buildIncludedResources(Bundle* bundle)
printf("Including resources from package: %s\n", includes[i].string());
}
- if (!mIncludedAssets.addAssetPath(includes[i], NULL)) {
+ if (!mIncludedAssets.addAssetPath(includes[i], 0)) {
fprintf(stderr, "ERROR: Asset package include '%s' not found.\n",
includes[i].string());
return UNKNOWN_ERROR;
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 4fdc964..5b66e4e 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -27,6 +27,8 @@ using namespace android;
extern const char * const gDefaultIgnoreAssets;
extern const char * gUserIgnoreAssets;
+extern bool endsWith(const char* haystack, const char* needle);
+
bool valid_symbol_name(const String8& str);
class AaptAssets;
@@ -146,7 +148,7 @@ class AaptFile : public RefBase
{
public:
AaptFile(const String8& sourceFile, const AaptGroupEntry& groupEntry,
- const String8& resType)
+ const String8& resType, const String8& zipFile=String8(""))
: mGroupEntry(groupEntry)
, mResourceType(resType)
, mSourceFile(sourceFile)
@@ -154,9 +156,11 @@ public:
, mDataSize(0)
, mBufferSize(0)
, mCompression(ZipEntry::kCompressStored)
+ , mZipFile(zipFile)
{
//printf("new AaptFile created %s\n", (const char*)sourceFile);
}
+
virtual ~AaptFile() {
free(mData);
}
@@ -188,6 +192,12 @@ public:
// no compression is ZipEntry::kCompressStored.
int getCompressionMethod() const { return mCompression; }
void setCompressionMethod(int c) { mCompression = c; }
+
+ // ZIP support. In this case the sourceFile is the zip entry name
+ // and zipFile is the path to the zip File.
+ // example: sourceFile = drawable-hdpi/foo.png, zipFile = res.zip
+ const String8& getZipFile() const { return mZipFile; }
+
private:
friend class AaptGroup;
@@ -199,6 +209,7 @@ private:
size_t mDataSize;
size_t mBufferSize;
int mCompression;
+ String8 mZipFile;
};
/**
@@ -540,6 +551,8 @@ public:
void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
ssize_t slurpFromArgs(Bundle* bundle);
+ ssize_t slurpResourceZip(Bundle* bundle, ZipFile* zip, const char* fullZipPath);
+ bool isEntryValid(Bundle* bundle, ZipEntry* entry);
sp<AaptSymbols> getSymbolsFor(const String8& name);
@@ -593,7 +606,11 @@ private:
const bool overwrite=false);
ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
- ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
+
+
+ status_t addEntry(const String8& entryName, const String8& entryLeaf,
+ const String8& entryDirFull, const String8& entryDir,
+ const String8& zipFile, int compressionMethod);
status_t filter(Bundle* bundle);
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index b12867a..fc42b8c 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -224,9 +224,20 @@ bool parse(const String8& str, ConfigDescription* out) {
success:
if (out != NULL) {
+#ifndef HAVE_ANDROID_OS
applyVersionForCompatibility(&config);
+#else
+ // Calling applyVersionForCompatibility when compiling a theme can cause
+ // the path to be changed by AAPT which results in the themed assets not being
+ // loaded. The only time (as of right now) that aapt is run on an android device
+ // is when it is being used for themes, so this should be the correct behavior
+ // in this case. If AAPT is ever used on an android device for some other reason,
+ // we will need to change this.
+ printf("AAPT is running on Android, skipping applyVersionForCompatibility");
+#endif
*out = config;
}
+
return true;
}
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index b991d55..68c2fe8f 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -133,5 +133,30 @@ LOCAL_STATIC_LIBRARIES += libaapt $(aaptHostStaticLibs)
include $(BUILD_HOST_NATIVE_TEST)
+# ==========================================================
+# Build the device executable: aapt
+# ==========================================================
+ifneq ($(SDK_ONLY),true)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := aapt
+LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_SRC_FILES := $(aaptSources) $(aaptMain)
+LOCAL_C_INCLUDES += \
+ $(aaptCIncludes) \
+ bionic
+LOCAL_SHARED_LIBRARIES := \
+ libandroidfw \
+ libutils \
+ libcutils \
+ libpng \
+ liblog \
+ libz
+LOCAL_STATIC_LIBRARIES := \
+ libexpat_static
+
+include $(BUILD_EXECUTABLE)
+
+endif # Not SDK_ONLY
endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index cbe7c5d..145eb64 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -1,5 +1,6 @@
//
// Copyright 2006 The Android Open Source Project
+// This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
//
// State bundle. Used to pass around stuff like command-line args.
//
@@ -49,7 +50,7 @@ public:
Bundle(void)
: mCmd(kCommandUnknown), mVerbose(false), mAndroidList(false),
mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false),
- mUpdate(false), mExtending(false),
+ mUpdate(false), mExtending(false), mExtendedPackageId(0),
mRequireLocalization(false), mPseudolocalize(NO_PSEUDOLOCALIZATION),
mWantUTF16(false), mValues(false), mIncludeMetaData(false),
mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
@@ -65,6 +66,8 @@ public:
mProduct(NULL), mUseCrunchCache(false), mErrorOnFailedInsert(false),
mErrorOnMissingConfigEntry(false), mOutputTextSymbols(NULL),
mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL),
+ mOutputResourcesApkFile(NULL),
+ mInternalZipPath(NULL), mInputAPKFile(NULL),
mBuildSharedLibrary(false),
mArgc(0), mArgv(NULL)
{}
@@ -94,6 +97,8 @@ public:
void setUpdate(bool val) { mUpdate = val; }
bool getExtending(void) const { return mExtending; }
void setExtending(bool val) { mExtending = val; }
+ int getExtendedPackageId(void) const { return mExtendedPackageId; }
+ void setExtendedPackageId(int val) { mExtendedPackageId = val; }
bool getRequireLocalization(void) const { return mRequireLocalization; }
void setRequireLocalization(bool val) { mRequireLocalization = val; }
short getPseudolocalize(void) const { return mPseudolocalize; }
@@ -109,6 +114,10 @@ public:
void setJunkPath(bool val) { mJunkPath = val; }
const char* getOutputAPKFile() const { return mOutputAPKFile; }
void setOutputAPKFile(const char* val) { mOutputAPKFile = val; }
+ const char* getOutputResApk() { return mOutputResourcesApkFile; }
+ const char* getInputAPKFile() { return mInputAPKFile; }
+ void setInputAPKFile(const char* val) { mInputAPKFile = val; }
+ void setOutputResApk(const char* val) { mOutputResourcesApkFile = val; }
const char* getManifestPackageNameOverride() const { return mManifestPackageNameOverride; }
void setManifestPackageNameOverride(const char * val) { mManifestPackageNameOverride = val; }
const char* getInstrumentationPackageNameOverride() const { return mInstrumentationPackageNameOverride; }
@@ -204,6 +213,8 @@ public:
void setSingleCrunchInputFile(const char* val) { mSingleCrunchInputFile = val; }
const char* getSingleCrunchOutputFile() const { return mSingleCrunchOutputFile; }
void setSingleCrunchOutputFile(const char* val) { mSingleCrunchOutputFile = val; }
+ void setInternalZipPath(const char* val) { mInternalZipPath = val; }
+ const char* getInternalZipPath() const { return mInternalZipPath; }
bool getBuildSharedLibrary() const { return mBuildSharedLibrary; }
void setBuildSharedLibrary(bool val) { mBuildSharedLibrary = val; }
void setNoVersionVectors(bool val) { mNoVersionVectors = val; }
@@ -275,6 +286,7 @@ private:
bool mMakePackageDirs;
bool mUpdate;
bool mExtending;
+ int mExtendedPackageId;
bool mRequireLocalization;
short mPseudolocalize;
bool mWantUTF16;
@@ -326,6 +338,9 @@ private:
const char* mOutputTextSymbols;
const char* mSingleCrunchInputFile;
const char* mSingleCrunchOutputFile;
+ const char* mOutputResourcesApkFile;
+ const char* mInternalZipPath;
+ const char* mInputAPKFile;
bool mBuildSharedLibrary;
android::String8 mPlatformVersionCode;
android::String8 mPlatformVersionName;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index d63fe31..58c65db 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -2573,21 +2573,48 @@ int doPackage(Bundle* bundle)
goto bail;
}
- // Write the apk
- if (outputAPKFile) {
+ if (outputAPKFile || bundle->getOutputResApk()) {
// Gather all resources and add them to the APK Builder. The builder will then
// figure out which Split they belong in.
err = addResourcesToBuilder(assets, builder);
if (err != NO_ERROR) {
goto bail;
}
+ }
+
+ //Write the res apk
+ if (bundle->getOutputResApk()) {
+ const char* resPath = bundle->getOutputResApk();
+ char *endptr;
+ int resApk_fd = strtol(resPath, &endptr, 10);
+
+ if (*endptr == '\0') {
+ //OutputResDir was a file descriptor
+ //Assume there is only one set of assets, when we deal with actual split apks this may have to change
+ err = writeAPK(bundle, resApk_fd, builder->getBaseSplit(), true);
+ } else {
+ //Assume there is only one set of assets, when we deal with actual split apks this may have to change
+ err = writeAPK(bundle, String8(bundle->getOutputResApk()), builder->getBaseSplit(), true);
+ }
+
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ERROR: writing '%s' failed\n", resPath);
+ goto bail;
+ }
+ }
+
+ // Write the apk
+ if (outputAPKFile) {
+ if (err != NO_ERROR) {
+ goto bail;
+ }
const Vector<sp<ApkSplit> >& splits = builder->getSplits();
const size_t numSplits = splits.size();
for (size_t i = 0; i < numSplits; i++) {
const sp<ApkSplit>& split = splits[i];
String8 outputPath = buildApkName(String8(outputAPKFile), split);
- err = writeAPK(bundle, outputPath, split);
+ err = writeAPK(bundle, outputPath, split, false);
if (err != NO_ERROR) {
fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string());
goto bail;
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index e4738f5..6c29ad9 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -27,6 +27,15 @@ png_write_aapt_file(png_structp png_ptr, png_bytep data, png_size_t length)
}
}
+static void
+png_read_mem_file(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ PngMemoryFile* pngFile = (PngMemoryFile*) png_get_io_ptr(png_ptr);
+ status_t err = pngFile->read(data, length);
+ if (err != NO_ERROR) {
+ png_error(png_ptr, "Read Error");
+ }
+}
static void
png_flush_aapt_file(png_structp /* png_ptr */)
@@ -1269,43 +1278,51 @@ static bool write_png_protected(png_structp write_ptr, String8& printableName, p
return true;
}
-status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets */,
+status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets */, //non-theme path
const sp<AaptFile>& file, String8* /* outNewLeafName */)
{
String8 ext(file->getPath().getPathExtension());
+ bool isImageInZip = !file->getZipFile().isEmpty();
// We currently only process PNG images.
if (strcmp(ext.string(), ".png") != 0) {
return NO_ERROR;
}
+ String8 printableName(file->getPrintableSource());
+
+ // We currently only process nine patch PNG images when building a theme apk.
+ Bundle* b = const_cast<Bundle*>(bundle);
+ if (!endsWith(printableName.string(), ".9.png") && b->getOutputResApk() != NULL) {
+ if (bundle->getVerbose()) {
+ printf("Skipping image: %s\n", file->getPrintableSource().string());
+ }
+ return NO_ERROR;
+ }
+
// Example of renaming a file:
//*outNewLeafName = file->getPath().getBasePath().getFileName();
//outNewLeafName->append(".nupng");
- String8 printableName(file->getPrintableSource());
-
if (bundle->getVerbose()) {
printf("Processing image: %s\n", printableName.string());
}
png_structp read_ptr = NULL;
png_infop read_info = NULL;
- FILE* fp;
+ FILE* fp = NULL;
image_info imageInfo;
png_structp write_ptr = NULL;
png_infop write_info = NULL;
- status_t error = UNKNOWN_ERROR;
+ PngMemoryFile* pmf = NULL;
+ ZipFile* zip = NULL;
- fp = fopen(file->getSourceFile().string(), "rb");
- if (fp == NULL) {
- fprintf(stderr, "%s: ERROR: Unable to open PNG file\n", printableName.string());
- goto bail;
- }
+ status_t error = UNKNOWN_ERROR;
+ const size_t nameLen = file->getPath().length();
read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, (png_error_ptr)NULL,
(png_error_ptr)NULL);
if (!read_ptr) {
@@ -1317,8 +1334,46 @@ status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets *
goto bail;
}
- if (!read_png_protected(read_ptr, printableName, read_info, file, fp, &imageInfo)) {
- goto bail;
+ if (isImageInZip) {
+ pmf = new PngMemoryFile();
+ zip = new ZipFile;
+ status_t err = zip->open(file->getZipFile(), ZipFile::kOpenReadOnly);
+ if (NO_ERROR != err) {
+ fprintf(stderr, "ERROR: Unable to open %s\n", file->getZipFile().string());
+ goto bail;
+ }
+
+ ZipEntry* entry = zip->getEntryByName(file->getSourceFile().string());
+ size_t len = entry->getUncompressedLen();
+ void* data = zip->uncompress(entry);
+ void* buf = file->editData(len);
+ memcpy(buf, data, len);
+ free(data);
+
+ pmf->setDataSource((const char*)file->getData(), file->getSize());
+ png_set_read_fn(read_ptr, pmf, png_read_mem_file);
+ read_png(printableName.string(), read_ptr, read_info, &imageInfo);
+ if (nameLen > 6) {
+ const char* name = file->getPath().string();
+ if (name[nameLen-5] == '9' && name[nameLen-6] == '.') {
+ if (do_9patch(printableName.string(), &imageInfo) != NO_ERROR) {
+ goto bail;
+ }
+ }
+ }
+ } else {
+ fp = fopen(file->getSourceFile().string(), "rb");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: ERROR: Unable to open PNG file\n", printableName.string());
+ goto bail;
+ }
+ if (!read_png_protected(read_ptr, printableName, read_info, file, fp, &imageInfo)) {
+ goto bail;
+ }
+ }
+
+ if (isImageInZip) {
+ file->clearData();
}
write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, (png_error_ptr)NULL,
@@ -1343,13 +1398,15 @@ status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets *
error = NO_ERROR;
- if (bundle->getVerbose()) {
+ if (bundle->getVerbose() && !isImageInZip) {
fseek(fp, 0, SEEK_END);
size_t oldSize = (size_t)ftell(fp);
size_t newSize = file->getSize();
float factor = ((float)newSize)/oldSize;
int percent = (int)(factor*100);
printf(" (processed image %s: %d%% size of source)\n", printableName.string(), percent);
+ } else if (bundle->getVerbose() && isImageInZip) {
+ printf(" (processed image %s)\n", printableName.string());
}
bail:
@@ -1362,6 +1419,12 @@ bail:
if (write_ptr) {
png_destroy_write_struct(&write_ptr, &write_info);
}
+ if (zip) {
+ delete zip;
+ }
+ if (pmf) {
+ delete pmf;
+ }
if (error != NO_ERROR) {
fprintf(stderr, "ERROR: Failure processing PNG image %s\n",
@@ -1375,7 +1438,7 @@ status_t preProcessImageToCache(const Bundle* bundle, const String8& source, con
png_structp read_ptr = NULL;
png_infop read_info = NULL;
- FILE* fp;
+ FILE*volatile fp;
image_info imageInfo;
@@ -1511,3 +1574,17 @@ status_t postProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets,
return NO_ERROR;
}
+
+status_t PngMemoryFile::read(png_bytep data, png_size_t length) {
+ if (data == NULL)
+ return -1;
+
+ if ((mIndex + length) >= mDataSize) {
+ length = mDataSize - mIndex;
+ }
+
+ memcpy(data, mData + mIndex, length);
+ mIndex += length;
+
+ return NO_ERROR;
+}
diff --git a/tools/aapt/Images.h b/tools/aapt/Images.h
index a0a94f8..3230ddc 100644
--- a/tools/aapt/Images.h
+++ b/tools/aapt/Images.h
@@ -10,6 +10,8 @@
#include "ResourceTable.h"
#include "Bundle.h"
+#include <png.h>
+
#include <utils/String8.h>
#include <utils/RefBase.h>
@@ -23,4 +25,18 @@ status_t preProcessImageToCache(const Bundle* bundle, const String8& source, con
status_t postProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets,
ResourceTable* table, const sp<AaptFile>& file);
+class PngMemoryFile {
+public:
+ PngMemoryFile(void)
+ : mData(NULL), mDataSize(0), mIndex(0)
+ {}
+ void setDataSource(const char* data, uint32_t size) { mData = data; mDataSize = size; mIndex = 0; }
+ status_t read(png_bytep data, png_size_t length);
+
+private:
+ const char* mData;
+ uint32_t mDataSize;
+ uint32_t mIndex;
+};
+
#endif
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index f832c60..aa67480 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -1,5 +1,6 @@
//
// Copyright 2006 The Android Open Source Project
+// This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
//
// Android Asset Packaging Tool main entry point.
//
@@ -14,6 +15,7 @@
#include <cstdlib>
#include <getopt.h>
#include <cassert>
+#include <ctype.h>
using namespace android;
@@ -56,7 +58,7 @@ void usage(void)
" xmltree Print the compiled xmls in the given assets.\n"
" xmlstrings Print the strings of the given compiled xml assets.\n\n", gProgName);
fprintf(stderr,
- " %s p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \\\n"
+ " %s p[ackage] [-d][-f][-m][-u][-v][-x[ extending-resource-id]][-z][-M AndroidManifest.xml] \\\n"
" [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \\\n"
" [--debug-mode] [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n"
" [--app-version VAL] [--app-version-name TEXT] [--custom-package VAL] \\\n"
@@ -114,7 +116,7 @@ void usage(void)
" -m make package directories under location specified by -J\n"
" -u update existing packages (add new, replace older, remove deleted files)\n"
" -v verbose output\n"
- " -x create extending (non-application) resource IDs\n"
+ " -x either create or assign (if specified) extending (non-application) resource IDs\n"
" -z require localization of resource attributes marked with\n"
" localization=\"suggested\"\n"
" -A additional directory in which to find raw asset files\n"
@@ -347,6 +349,14 @@ int main(int argc, char* const argv[])
break;
case 'x':
bundle.setExtending(true);
+ argc--;
+ argv++;
+ if (!argc || !isdigit(argv[0][0])) {
+ argc++;
+ argv--;
+ } else {
+ bundle.setExtendedPackageId(atoi(argv[0]));
+ }
break;
case 'z':
bundle.setRequireLocalization(true);
@@ -428,6 +438,17 @@ int main(int argc, char* const argv[])
convertPath(argv[0]);
bundle.setAndroidManifestFile(argv[0]);
break;
+ case 'X':
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '-X' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ convertPath(argv[0]);
+ bundle.setInternalZipPath(argv[0]);
+ break;
case 'P':
argc--;
argv++;
@@ -497,6 +518,28 @@ int main(int argc, char* const argv[])
bundle.setCompressionMethod(ZipEntry::kCompressStored);
}
break;
+ case 'Z':
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '-Z' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ convertPath(argv[0]);
+ bundle.setInputAPKFile(argv[0]);
+ break;
+ case 'r':
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '-r' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ convertPath(argv[0]);
+ bundle.setOutputResApk(argv[0]);
+ break;
case '-':
if (strcmp(cp, "-debug-mode") == 0) {
bundle.setDebugMode(true);
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index e84c4c5..0b8adbe 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -42,7 +42,14 @@ extern int calcPercent(long uncompressedLen, long compressedLen);
extern android::status_t writeAPK(Bundle* bundle,
const android::String8& outputFile,
- const android::sp<OutputSet>& outputSet);
+ const android::sp<OutputSet>& outputSet,
+ bool isOverlay);
+extern android::status_t writeAPK(Bundle* bundle,
+ int fd,
+ const android::sp<OutputSet>& outputSet,
+ bool isOverlay);
+extern android::status_t writeResFile(FILE* fp, const sp<AaptAssets>& assets, sp<ApkBuilder>& builder);
+extern sp<AaptFile> getResourceFile(const sp<AaptAssets>& assets, bool makeIfNecessary=true);
extern android::status_t updatePreProcessedCache(Bundle* bundle);
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index cb244ec..3daf644 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -37,8 +37,10 @@ static const char* kNoCompressExt[] = {
};
/* fwd decls, so I can write this downward */
-ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<const OutputSet>& outputSet);
bool processFile(Bundle* bundle, ZipFile* zip, String8 storageName, const sp<const AaptFile>& file);
+ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<const OutputSet>& outputSet, bool isOverlay);
+bool processOverlayFile(Bundle* bundle, ZipFile* zip,
+ String8 storageName, const sp<const AaptFile>& file);
bool okayToCompress(Bundle* bundle, const String8& pathName);
ssize_t processJarFiles(Bundle* bundle, ZipFile* zip);
@@ -49,7 +51,81 @@ ssize_t processJarFiles(Bundle* bundle, ZipFile* zip);
* On success, "bundle->numPackages" will be the number of Zip packages
* we created.
*/
-status_t writeAPK(Bundle* bundle, const String8& outputFile, const sp<OutputSet>& outputSet)
+status_t writeAPK(Bundle* bundle, ZipFile* zip, const char* outputFileName,
+ const sp<OutputSet>& outputSet, bool isOverlay)
+{
+ status_t result = NO_ERROR;
+ int count;
+
+ if (bundle->getVerbose()) {
+ printf("Writing all files...\n");
+ }
+
+ count = processAssets(bundle, zip, outputSet, isOverlay);
+ if (count < 0) {
+ fprintf(stderr, "ERROR: unable to process assets while packaging '%s'\n",
+ outputFileName);
+ result = count;
+ goto bail;
+ }
+
+ if (bundle->getVerbose()) {
+ printf("Generated %d file%s\n", count, (count==1) ? "" : "s");
+ }
+
+ if (!isOverlay) {
+ count = processJarFiles(bundle, zip);
+ if (count < 0) {
+ fprintf(stderr, "ERROR: unable to process jar files while packaging '%s'\n",
+ outputFileName);
+ result = count;
+ goto bail;
+ }
+
+ if (bundle->getVerbose())
+ printf("Included %d file%s from jar/zip files.\n", count, (count==1) ? "" : "s");
+ }
+
+ result = NO_ERROR;
+
+ /*
+ * Check for cruft. We set the "marked" flag on all entries we created
+ * or decided not to update. If the entry isn't already slated for
+ * deletion, remove it now.
+ */
+ {
+ if (bundle->getVerbose())
+ printf("Checking for deleted files\n");
+ int i, removed = 0;
+ for (i = 0; i < zip->getNumEntries(); i++) {
+ ZipEntry* entry = zip->getEntryByIndex(i);
+
+ if (!entry->getMarked() && entry->getDeleted()) {
+ if (bundle->getVerbose()) {
+ printf(" (removing crufty '%s')\n",
+ entry->getFileName());
+ }
+ zip->remove(entry);
+ removed++;
+ }
+ }
+ if (bundle->getVerbose() && removed > 0)
+ printf("Removed %d file%s\n", removed, (removed==1) ? "" : "s");
+ }
+
+ /* tell Zip lib to process deletions and other pending changes */
+ result = zip->flush();
+ if (result != NO_ERROR) {
+ fprintf(stderr, "ERROR: Zip flush failed, archive may be hosed\n");
+ goto bail;
+ }
+
+bail:
+ return result;
+}
+
+status_t writeAPK(Bundle* bundle, const String8& outputFile,
+ const sp<OutputSet>& outputSet, bool isOverlay)
{
#if BENCHMARK
fprintf(stdout, "BENCHMARK: Starting APK Bundling \n");
@@ -58,7 +134,6 @@ status_t writeAPK(Bundle* bundle, const String8& outputFile, const sp<OutputSet>
status_t result = NO_ERROR;
ZipFile* zip = NULL;
- int count;
//bundle->setPackageCount(0);
@@ -105,64 +180,10 @@ status_t writeAPK(Bundle* bundle, const String8& outputFile, const sp<OutputSet>
goto bail;
}
- if (bundle->getVerbose()) {
- printf("Writing all files...\n");
- }
-
- count = processAssets(bundle, zip, outputSet);
- if (count < 0) {
- fprintf(stderr, "ERROR: unable to process assets while packaging '%s'\n",
- outputFile.string());
- result = count;
- goto bail;
- }
-
- if (bundle->getVerbose()) {
- printf("Generated %d file%s\n", count, (count==1) ? "" : "s");
- }
-
- count = processJarFiles(bundle, zip);
- if (count < 0) {
- fprintf(stderr, "ERROR: unable to process jar files while packaging '%s'\n",
- outputFile.string());
- result = count;
- goto bail;
- }
-
- if (bundle->getVerbose())
- printf("Included %d file%s from jar/zip files.\n", count, (count==1) ? "" : "s");
-
- result = NO_ERROR;
+ result = writeAPK(bundle, zip, outputFile.string(), outputSet, isOverlay);
- /*
- * Check for cruft. We set the "marked" flag on all entries we created
- * or decided not to update. If the entry isn't already slated for
- * deletion, remove it now.
- */
- {
- if (bundle->getVerbose())
- printf("Checking for deleted files\n");
- int i, removed = 0;
- for (i = 0; i < zip->getNumEntries(); i++) {
- ZipEntry* entry = zip->getEntryByIndex(i);
-
- if (!entry->getMarked() && entry->getDeleted()) {
- if (bundle->getVerbose()) {
- printf(" (removing crufty '%s')\n",
- entry->getFileName());
- }
- zip->remove(entry);
- removed++;
- }
- }
- if (bundle->getVerbose() && removed > 0)
- printf("Removed %d file%s\n", removed, (removed==1) ? "" : "s");
- }
-
- /* tell Zip lib to process deletions and other pending changes */
- result = zip->flush();
if (result != NO_ERROR) {
- fprintf(stderr, "ERROR: Zip flush failed, archive may be hosed\n");
+ fprintf(stderr, "ERROR: Writing apk failed\n");
goto bail;
}
@@ -215,7 +236,98 @@ bail:
return result;
}
-ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<const OutputSet>& outputSet)
+/*
+ * The directory hierarchy looks like this:
+ * "outputDir" and "assetRoot" are existing directories.
+ *
+ * On success, "bundle->numPackages" will be the number of Zip packages
+ * we created.
+ */
+status_t writeAPK(Bundle* bundle, int fd, const sp<OutputSet>& outputSet, bool isOverlay)
+{
+ #if BENCHMARK
+ fprintf(stdout, "BENCHMARK: Starting APK Bundling \n");
+ long startAPKTime = clock();
+ #endif /* BENCHMARK */
+
+ status_t result = NO_ERROR;
+ ZipFile* zip = NULL;
+
+ status_t status;
+ zip = new ZipFile;
+ status = zip->openfd(fd, ZipFile::kOpenReadWrite);
+ if (status != NO_ERROR) {
+ fprintf(stderr, "ERROR: unable to open file as Zip file for writing\n");
+ result = PERMISSION_DENIED;
+ goto bail;
+ }
+
+ result = writeAPK(bundle, zip, "file_descriptor", outputSet, isOverlay);
+
+ if (result != NO_ERROR) {
+ fprintf(stderr, "ERROR: Writing apk failed\n");
+ goto bail;
+ }
+
+ /* anything here? */
+ if (zip->getNumEntries() == 0) {
+ if (bundle->getVerbose()) {
+ printf("Archive is empty -- removing\n");
+ }
+ delete zip; // close the file so we can remove it in Win32
+ zip = NULL;
+ close(fd);
+ }
+
+ assert(result == NO_ERROR);
+
+bail:
+ delete zip; // must close before remove in Win32
+ close(fd);
+ if (result != NO_ERROR) {
+ if (bundle->getVerbose()) {
+ printf("Removing archive due to earlier failures\n");
+ }
+ }
+
+ if (result == NO_ERROR && bundle->getVerbose())
+ printf("Done!\n");
+
+ #if BENCHMARK
+ fprintf(stdout, "BENCHMARK: End APK Bundling. Time Elapsed: %f ms \n",(clock() - startAPKTime)/1000.0);
+ #endif /* BENCHMARK */
+ return result;
+}
+
+status_t writeResFile(FILE* fp, const sp<AaptAssets>& /* assets */, sp<ApkBuilder>& builder) {
+ if (fp == NULL) {
+ fprintf(stderr, "Unable to open resFile for writing resTable\n");
+ return PERMISSION_DENIED;
+ }
+
+ sp<ApkSplit> split = builder->getBaseSplit();
+ const std::set<OutputEntry>& entries = split->getEntries();
+ std::set<OutputEntry>::const_iterator iter = entries.begin();
+ for (; iter != entries.end(); iter++) {
+ const OutputEntry& entry = *iter;
+
+ if (entry.getPath() == String8("resources.arsc")) {
+ sp<const AaptFile> resFile = entry.getFile();
+
+ int count = 0;
+ count = fwrite(resFile->getData(), 1, resFile->getSize(), fp);
+
+ if (count == 0) {
+ fprintf(stderr, "Nothing written to resFile\n");
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+
+ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<const OutputSet>& outputSet,
+ bool isOverlay)
{
ssize_t count = 0;
const std::set<OutputEntry>& entries = outputSet->getEntries();
@@ -227,7 +339,9 @@ ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<const OutputSet>& o
} else {
String8 storagePath(entry.getPath());
storagePath.convertToResPath();
- if (!processFile(bundle, zip, storagePath, entry.getFile())) {
+ bool ret = isOverlay ? processOverlayFile(bundle, zip, storagePath, entry.getFile())
+ : processFile(bundle, zip, storagePath, entry.getFile());
+ if (!ret) {
return UNKNOWN_ERROR;
}
count++;
@@ -360,6 +474,76 @@ bool processFile(Bundle* bundle, ZipFile* zip,
}
/*
+ * Process a regular file, adding it to the archive if appropriate.
+ *
+ * This function is intended for use when creating a cached overlay package.
+ * Only xml and .9.png files are processed and added to the package.
+ *
+ * If we're in "update" mode, and the file already exists in the archive,
+ * delete the existing entry before adding the new one.
+ */
+bool processOverlayFile(Bundle* bundle, ZipFile* zip,
+ String8 storageName, const sp<const AaptFile>& file)
+{
+ const bool hasData = file->hasData();
+
+ storageName.convertToResPath();
+ ZipEntry* entry;
+ bool fromGzip = false;
+ status_t result;
+
+ if (strcasecmp(storageName.getPathExtension().string(), ".gz") == 0) {
+ fromGzip = true;
+ storageName = storageName.getBasePath();
+ }
+
+ if (bundle->getUpdate()) {
+ entry = zip->getEntryByName(storageName.string());
+ if (entry != NULL) {
+ /* file already exists in archive; there can be only one */
+ if (entry->getMarked()) {
+ fprintf(stderr,
+ "ERROR: '%s' exists twice (check for with & w/o '.gz'?)\n",
+ file->getPrintableSource().string());
+ return false;
+ }
+ zip->remove(entry);
+ }
+ }
+
+ if (hasData) {
+ const char* name = storageName.string();
+ if (endsWith(name, ".9.png") || endsWith(name, ".xml") || endsWith(name, ".arsc")) {
+ result = zip->add(file->getData(), file->getSize(), storageName.string(),
+ file->getCompressionMethod(), &entry);
+ if (result == NO_ERROR) {
+ if (bundle->getVerbose()) {
+ printf(" '%s'%s", storageName.string(), fromGzip ? " (from .gz)" : "");
+ if (entry->getCompressionMethod() == ZipEntry::kCompressStored) {
+ printf(" (not compressed)\n");
+ } else {
+ printf(" (compressed %d%%)\n", calcPercent(entry->getUncompressedLen(),
+ entry->getCompressedLen()));
+ }
+ }
+ entry->setMarked(true);
+ } else {
+ if (result == ALREADY_EXISTS) {
+ fprintf(stderr, " Unable to add '%s': file already in archive (try '-u'?)\n",
+ file->getPrintableSource().string());
+ } else {
+ fprintf(stderr, " Unable to add '%s': Zip add failed\n",
+ file->getPrintableSource().string());
+ }
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/*
* Determine whether or not we want to try to compress this file based
* on the file extension.
*/
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 5d20815..b796b27 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -221,6 +221,24 @@ bool isValidResourceType(const String8& type)
|| type == "color" || type == "menu" || type == "mipmap";
}
+sp<AaptFile> getResourceFile(const sp<AaptAssets>& assets, bool makeIfNecessary)
+{
+ sp<AaptGroup> group = assets->getFiles().valueFor(String8("resources.arsc"));
+ sp<AaptFile> file;
+ if (group != NULL) {
+ file = group->getFiles().valueFor(AaptGroupEntry());
+ if (file != NULL) {
+ return file;
+ }
+ }
+
+ if (!makeIfNecessary) {
+ return NULL;
+ }
+ return assets->addFile(String8("resources.arsc"), AaptGroupEntry(), String8(),
+ NULL, String8());
+}
+
static status_t parsePackage(Bundle* bundle, const sp<AaptAssets>& assets,
const sp<AaptGroup>& grp)
{
@@ -1170,7 +1188,9 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
packageType = ResourceTable::AppFeature;
}
- ResourceTable table(bundle, String16(assets->getPackage()), packageType);
+ int extendedPackageId = bundle->getExtendedPackageId();
+
+ ResourceTable table(bundle, String16(assets->getPackage()), packageType, extendedPackageId);
err = table.addIncludedResources(bundle, assets);
if (err != NO_ERROR) {
return err;
@@ -1252,7 +1272,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
bool hasErrors = false;
if (drawables != NULL) {
- if (bundle->getOutputAPKFile() != NULL) {
+ if (bundle->getOutputAPKFile() != NULL || bundle->getOutputResApk()) {
err = preProcessImages(bundle, assets, drawables, "drawable");
}
if (err == NO_ERROR) {
@@ -2523,7 +2543,7 @@ static status_t writeSymbolClass(
fprintf(fp,
"%s/** %s\n",
getIndentSpace(indent), cmt.string());
- } else if (sym.isPublic && !includePrivate) {
+ } else if (sym.isPublic && !includePrivate && kIsDebug) {
sym.sourcePos.warning("No comment for public symbol %s:%s/%s",
assets->getPackage().string(), className.string(),
String8(sym.name).string());
@@ -2569,7 +2589,7 @@ static status_t writeSymbolClass(
"%s */\n",
getIndentSpace(indent), cmt.string(),
getIndentSpace(indent));
- } else if (sym.isPublic && !includePrivate) {
+ } else if (sym.isPublic && !includePrivate && kIsDebug) {
sym.sourcePos.warning("No comment for public symbol %s:%s/%s",
assets->getPackage().string(), className.string(),
String8(sym.name).string());
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index d5a09d8..fb0299e 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1467,6 +1467,11 @@ status_t compileResourceFile(Bundle* bundle,
}
}
} else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
+ // Note the existence and locale of every string array we process
+ char rawLocale[RESTABLE_MAX_LOCALE_LEN];
+ curParams.getBcp47Locale(rawLocale);
+ String8 locale(rawLocale);
+ String16 name;
// Check whether these strings need valid formats.
// (simplified form of what string16 does above)
bool isTranslatable = false;
@@ -1477,7 +1482,9 @@ status_t compileResourceFile(Bundle* bundle,
for (size_t i = 0; i < n; i++) {
size_t length;
const char16_t* attr = block.getAttributeName(i, &length);
- if (strcmp16(attr, formatted16.string()) == 0) {
+ if (strcmp16(attr, name16.string()) == 0) {
+ name.setTo(block.getAttributeStringValue(i, &length));
+ } else if (strcmp16(attr, formatted16.string()) == 0) {
const char16_t* value = block.getAttributeStringValue(i, &length);
if (strcmp16(value, false16.string()) == 0) {
curIsFormatted = false;
@@ -1486,6 +1493,15 @@ status_t compileResourceFile(Bundle* bundle,
const char16_t* value = block.getAttributeStringValue(i, &length);
if (strcmp16(value, false16.string()) == 0) {
isTranslatable = false;
+ // Untranslatable string arrays must only exist
+ // in the default [empty] locale
+ if (locale.size() > 0) {
+ SourcePos(in->getPrintableSource(), block.getLineNumber()).warning(
+ "string-array '%s' marked untranslatable but exists"
+ " in locale '%s'\n", String8(name).string(),
+ locale.string());
+ // hasErrors = localHasErrors = true;
+ }
}
}
}
@@ -1753,7 +1769,7 @@ status_t compileResourceFile(Bundle* bundle,
return hasErrors ? STATUST(UNKNOWN_ERROR) : NO_ERROR;
}
-ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type)
+ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type, ssize_t pkgIdOverride)
: mAssetsPackage(assetsPackage)
, mPackageType(type)
, mTypeIdOffset(0)
@@ -1779,6 +1795,11 @@ ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, Reso
assert(0);
break;
}
+
+ if (pkgIdOverride != 0) {
+ packageId = pkgIdOverride;
+ }
+
sp<Package> package = new Package(mAssetsPackage, packageId);
mPackages.add(assetsPackage, package);
mOrderedPackages.add(package);
@@ -2825,8 +2846,9 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
for (size_t i = 0; i < basePackageCount; i++) {
size_t packageId = table.getBasePackageId(i);
String16 packageName(table.getBasePackageName(i));
- if (packageId > 0x01 && packageId != 0x7f &&
- packageName != String16("android")) {
+ if (packageId > 0x01 && packageId != 0x7f && packageId != 0x3f &&
+ packageName != String16("android")
+ && packageName != String16("cyanogenmod.platform")) {
libraryPackages.add(sp<Package>(new Package(packageName, packageId)));
}
}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index c4bdf09..2c2df19 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -109,7 +109,8 @@ public:
const ConfigDescription& sourceConfig,
const int sdkVersionToGenerate);
- ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type);
+ ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type,
+ ssize_t pkgIdOverride);
const String16& getAssetsPackage() const {
return mAssetsPackage;
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 9908c44..0d59fae 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -127,7 +127,7 @@ int StringPool::entry::compare(const entry& o) const {
}
StringPool::StringPool(bool utf8) :
- mUTF8(utf8), mValues(-1)
+ mUTF8(utf8)
{
}
@@ -144,8 +144,8 @@ ssize_t StringPool::add(const String16& value, const Vector<entry_style_span>& s
ssize_t StringPool::add(const String16& value,
bool mergeDuplicates, const String8* configTypeName, const ResTable_config* config)
{
- ssize_t vidx = mValues.indexOfKey(value);
- ssize_t pos = vidx >= 0 ? mValues.valueAt(vidx) : -1;
+ auto it = mValues.find(value);
+ ssize_t pos = it != mValues.end() ? it->second : -1;
ssize_t eidx = pos >= 0 ? mEntryArray.itemAt(pos) : -1;
if (eidx < 0) {
eidx = mEntries.add(entry(value));
@@ -192,21 +192,21 @@ ssize_t StringPool::add(const String16& value,
}
}
- const bool first = vidx < 0;
+ const bool first = (it == mValues.end());
const bool styled = (pos >= 0 && (size_t)pos < mEntryStyleArray.size()) ?
mEntryStyleArray[pos].spans.size() : 0;
if (first || styled || !mergeDuplicates) {
pos = mEntryArray.add(eidx);
if (first) {
- vidx = mValues.add(value, pos);
+ mValues[value] = pos;
}
entry& ent = mEntries.editItemAt(eidx);
ent.indices.add(pos);
}
if (kIsDebug) {
- printf("Adding string %s to pool: pos=%zd eidx=%zd vidx=%zd\n",
- String8(value).string(), SSIZE(pos), SSIZE(eidx), SSIZE(vidx));
+ printf("Adding string %s to pool: pos=%zd eidx=%zd\n",
+ String8(value).string(), SSIZE(pos), SSIZE(eidx));
}
return pos;
@@ -349,14 +349,18 @@ void StringPool::sortByConfig()
// Now trim any entries at the end of the new style array that are
// not needed.
- for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) {
+ ssize_t i;
+ for (i=newEntryStyleArray.size()-1; i>=0; i--) {
const entry_style& style = newEntryStyleArray[i];
if (style.spans.size() > 0) {
// That's it.
break;
}
- // This one is not needed; remove.
- newEntryStyleArray.removeAt(i);
+ }
+
+ ssize_t nToRemove=newEntryStyleArray.size()-(i+1);
+ if (nToRemove) {
+ newEntryStyleArray.removeItemsAt(i+1, nToRemove);
}
// All done, install the new data structures and upate mValues with
@@ -367,7 +371,7 @@ void StringPool::sortByConfig()
mValues.clear();
for (size_t i=0; i<mEntries.size(); i++) {
const entry& ent = mEntries[i];
- mValues.add(ent.value, ent.indices[0]);
+ mValues[ent.value] = ent.indices[0];
}
#if 0
@@ -610,9 +614,10 @@ ssize_t StringPool::offsetForString(const String16& val) const
const Vector<size_t>* StringPool::offsetsForString(const String16& val) const
{
- ssize_t pos = mValues.valueFor(val);
- if (pos < 0) {
+ auto it = mValues.find(val);
+ if (it == mValues.end()) {
return NULL;
}
+ ssize_t pos = it->second;
return &mEntries[mEntryArray[pos]].indices;
}
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index dbe8c85..3014a3b 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -19,6 +19,7 @@
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
+#include <map>
#include <libexpat/expat.h>
@@ -175,7 +176,7 @@ private:
// Unique set of all the strings added to the pool, mapped to
// the first index of mEntryArray where the value was added.
- DefaultKeyedVector<String16, ssize_t> mValues;
+ std::map<String16, ssize_t> mValues;
// This array maps from the original position a string was placed at
// in mEntryArray to its new position after being sorted with sortByConfig().
Vector<size_t> mOriginalPosToNewPos;
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index ca3f687..6ab55d5 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -11,6 +11,7 @@
#include <utils/ByteOrder.h>
#include <errno.h>
#include <string.h>
+#include <androidfw/AssetManager.h>
#ifndef HAVE_MS_C_RUNTIME
#define O_BINARY 0
@@ -583,9 +584,51 @@ status_t parseXMLResource(const sp<AaptFile>& file, ResXMLTree* outTree,
return NO_ERROR;
}
+sp<XMLNode> XMLNode::parseFromZip(const sp<AaptFile>& file) {
+ AssetManager assets;
+ int32_t cookie;
+
+ if (!assets.addAssetPath(file->getZipFile(), &cookie)) {
+ fprintf(stderr, "Error: Could not open path %s\n", file->getZipFile().string());
+ return NULL;
+ }
+
+ Asset* asset = assets.openNonAsset(cookie, file->getSourceFile(), Asset::ACCESS_BUFFER);
+ ssize_t len = asset->getLength();
+ const void* buf = asset->getBuffer(false);
+
+ XML_Parser parser = XML_ParserCreateNS(NULL, 1);
+ ParseState state;
+ state.filename = file->getPrintableSource();
+ state.parser = parser;
+ XML_SetUserData(parser, &state);
+ XML_SetElementHandler(parser, startElement, endElement);
+ XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace);
+ XML_SetCharacterDataHandler(parser, characterData);
+ XML_SetCommentHandler(parser, commentData);
+
+ bool done = true;
+ if (XML_Parse(parser, (char*) buf, len, done) == XML_STATUS_ERROR) {
+ SourcePos(file->getSourceFile(), (int)XML_GetCurrentLineNumber(parser)).error(
+ "Error parsing XML: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
+ return NULL;
+ }
+ XML_ParserFree(parser);
+ if (state.root == NULL) {
+ SourcePos(file->getSourceFile(), -1).error("No XML data generated when parsing");
+ }
+ return state.root;
+}
+
sp<XMLNode> XMLNode::parse(const sp<AaptFile>& file)
{
char buf[16384];
+
+ //Check for zip first
+ if (file->getZipFile().length() > 0) {
+ return parseFromZip(file);
+ }
+
int fd = open(file->getSourceFile().string(), O_RDONLY | O_BINARY);
if (fd < 0) {
SourcePos(file->getSourceFile(), -1).error("Unable to open file for read: %s",
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 3161f65..905c6fd 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -188,6 +188,9 @@ private:
status_t flatten_node(const StringPool& strings, const sp<AaptFile>& dest,
bool stripComments, bool stripRawValues) const;
+ static sp<XMLNode> parseFromZip(const sp<AaptFile>& file);
+ static sp<XMLNode> parseFromAsset(const Asset& asset);
+
String16 mNamespacePrefix;
String16 mNamespaceUri;
String16 mElementName;
diff --git a/tools/aapt/ZipFile.cpp b/tools/aapt/ZipFile.cpp
index 36f4e73..8a4eef5 100644
--- a/tools/aapt/ZipFile.cpp
+++ b/tools/aapt/ZipFile.cpp
@@ -130,6 +130,71 @@ status_t ZipFile::open(const char* zipFileName, int flags)
}
/*
+ * Open a file and parse its guts.
+ */
+status_t ZipFile::openfd(int fd, int flags)
+{
+ bool newArchive = true;
+
+ assert(mZipFp == NULL); // no reopen
+
+ if ((flags & kOpenTruncate))
+ flags |= kOpenCreate; // trunc implies create
+
+ if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite))
+ return INVALID_OPERATION; // not both
+ if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite)))
+ return INVALID_OPERATION; // not neither
+ if ((flags & kOpenCreate) && !(flags & kOpenReadWrite))
+ return INVALID_OPERATION; // create requires write
+
+ /* open the file */
+ const char* openflags;
+ if (flags & kOpenReadWrite) {
+ if (newArchive)
+ openflags = FILE_OPEN_RW_CREATE;
+ else
+ openflags = FILE_OPEN_RW;
+ } else {
+ openflags = FILE_OPEN_RO;
+ }
+ mZipFp = fdopen(fd, openflags);
+ if (mZipFp == NULL) {
+ int err = errno;
+ ALOGD("fdopen failed: %s\n", strerror(err));
+ return errnoToStatus(err);
+ }
+
+ status_t result;
+ if (!newArchive) {
+ /*
+ * Load the central directory. If that fails, then this probably
+ * isn't a Zip archive.
+ */
+ result = readCentralDir();
+ } else {
+ /*
+ * Newly-created. The EndOfCentralDir constructor actually
+ * sets everything to be the way we want it (all zeroes). We
+ * set mNeedCDRewrite so that we create *something* if the
+ * caller doesn't add any files. (We could also just unlink
+ * the file if it's brand new and nothing was added, but that's
+ * probably doing more than we really should -- the user might
+ * have a need for empty zip files.)
+ */
+ mNeedCDRewrite = true;
+ result = NO_ERROR;
+ }
+
+ if (flags & kOpenReadOnly)
+ mReadOnly = true;
+ else
+ assert(!mReadOnly);
+
+ return result;
+}
+
+/*
* Return the Nth entry in the archive.
*/
ZipEntry* ZipFile::getEntryByIndex(int idx) const
diff --git a/tools/aapt/ZipFile.h b/tools/aapt/ZipFile.h
index 7877550..d5abbf1 100644
--- a/tools/aapt/ZipFile.h
+++ b/tools/aapt/ZipFile.h
@@ -64,6 +64,7 @@ public:
kOpenTruncate = 0x08, // if it exists, empty it
};
status_t open(const char* zipFileName, int flags);
+ status_t openfd(int fd, int flags);
/*
* Add a file to the end of the archive. Specify whether you want the
diff --git a/tools/aapt/tests/ZipReading_test.cpp b/tools/aapt/tests/ZipReading_test.cpp
new file mode 100644
index 0000000..4b4f2da
--- /dev/null
+++ b/tools/aapt/tests/ZipReading_test.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <utils/String8.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <utils/KeyedVector.h>
+
+#include "mocks/MockZipFile.h"
+#include "mocks/MockZipEntry.h"
+
+#include "AaptConfig.h"
+#include "ConfigDescription.h"
+#include "TestHelper.h"
+
+#include "AaptAssets.h"
+
+using android::String8;
+using namespace testing;
+
+// A path to an apk that would be considered valid
+#define VALID_APK_FILE "/valid/valid.apk"
+
+// Internal zip path to a dir that aapt is being asked to compile
+#define COMPILING_OVERLAY_DIR "/assets/overlays/com.interesting.app"
+
+// Internal zip path to a valid resource. aapt is expected to compile this resource.
+#define COMPILING_OVERLAY_FILE COMPILING_OVERLAY_DIR "/res/drawable-xxhdpi/foo.png";
+
+// Internal zip path to another overlay dir that is NOT being compiled
+#define NOT_COMPILING_OVERLAY_DIR "/assets/overlays/com.boring.app"
+
+// Internal zip path to a resource for an overlay that is NOT compiling. aapt is expected to ignore
+#define NOT_COMPILING_OVERLAY_FILE COMPILING_OVERLAY_DIR "/assets/overlays/com.boring.app"
+
+static ::testing::AssertionResult TestParse(const String8& input, ConfigDescription* config=NULL) {
+ if (AaptConfig::parse(String8(input), config)) {
+ return ::testing::AssertionSuccess() << input << " was successfully parsed";
+ }
+ return ::testing::AssertionFailure() << input << " could not be parsed";
+}
+
+static ::testing::AssertionResult TestParse(const char* input, ConfigDescription* config=NULL) {
+ return TestParse(String8(input), config);
+}
+
+TEST(ZipReadingTest, TestValidZipEntryIsAdded) {
+ MockZipFile zip;
+ MockZipEntry entry1;
+ const char* zipFile = VALID_APK_FILE;
+ const char* validFilename = COMPILING_OVERLAY_FILE;
+
+ EXPECT_CALL(entry1, getFileName())
+ .WillRepeatedly(Return(validFilename));
+
+ EXPECT_CALL(zip, getNumEntries())
+ .Times(1)
+ .WillRepeatedly(Return(1));
+
+ EXPECT_CALL(zip, getEntryByIndex(_))
+ .Times(1)
+ .WillOnce(Return(&entry1));
+
+ sp<AaptAssets> assets = new AaptAssets();
+ Bundle bundle;
+ bundle.setInternalZipPath(COMPILING_OVERLAY_DIR);
+ ssize_t count = assets->slurpResourceZip(&bundle, &zip, zipFile);
+
+ Vector<sp<AaptDir> > dirs = assets->resDirs();
+ EXPECT_EQ(1, dirs.size());
+ EXPECT_EQ(1, count);
+}
+
+TEST(ZipReadingTest, TestDifferentThemeEntryNotAdded) {
+ MockZipFile zip;
+ MockZipEntry entry1;
+ const char* zipFile = VALID_APK_FILE;
+ const char* invalidFile = NOT_COMPILING_OVERLAY_FILE;
+
+ EXPECT_CALL(entry1, getFileName())
+ .WillRepeatedly(Return(invalidFile));
+
+ EXPECT_CALL(zip, getNumEntries())
+ .WillRepeatedly(Return(1));
+
+ EXPECT_CALL(zip, getEntryByIndex(_))
+ .Times(1)
+ .WillOnce(Return(&entry1));
+
+ sp<AaptAssets> assets = new AaptAssets();
+ Bundle bundle;
+ bundle.setInternalZipPath(COMPILING_OVERLAY_DIR);
+ ssize_t count = assets->slurpResourceZip(&bundle, &zip, zipFile);
+
+ Vector<sp<AaptDir> > dirs = assets->resDirs();
+ EXPECT_EQ(0, dirs.size());
+ EXPECT_EQ(0, count);
+}
+
+TEST(ZipReadingTest, TestOutsideEntryMarkedInvalid) {
+ Bundle bundle;
+ bundle.setInternalZipPath("VALID_OVERLAY_DIR");
+ MockZipEntry invalidEntry;
+ const char* invalidFile = NOT_COMPILING_OVERLAY_FILE;
+
+ EXPECT_CALL(invalidEntry, getFileName())
+ .WillRepeatedly(Return(invalidFile));
+
+ sp<AaptAssets> assets = new AaptAssets();
+ bool result = assets->isEntryValid(&bundle, &invalidEntry);
+
+ EXPECT_FALSE(result);
+}
+
+TEST(ZipReadingTest, TestNullEntryIsInvalid) {
+ Bundle bundle;
+ bundle.setInternalZipPath(COMPILING_OVERLAY_DIR);
+ MockZipEntry invalidEntry;
+ const char* invalidFile = NOT_COMPILING_OVERLAY_FILE;
+
+ EXPECT_CALL(invalidEntry, getFileName())
+ .WillRepeatedly(Return(invalidFile));
+
+ sp<AaptAssets> assets = new AaptAssets();
+ bool result = assets->isEntryValid(&bundle, NULL);
+
+ EXPECT_FALSE(result);
+}
+
+TEST(ZipReadingTest, TestDirectoryEntryMarkedInvalid) {
+ Bundle bundle;
+ bundle.setInternalZipPath(COMPILING_OVERLAY_DIR);
+ MockZipEntry invalidEntry2;
+ // Add a "/" signifying this is a dir entry not a file entry.
+ const char* dir2 = COMPILING_OVERLAY_DIR"/";
+ EXPECT_CALL(invalidEntry2, getFileName())
+ .WillRepeatedly(Return(dir2));
+
+ sp<AaptAssets> assets = new AaptAssets();
+ bool result2 = assets->isEntryValid(&bundle, &invalidEntry2);
+
+ EXPECT_FALSE(result2);
+}
diff --git a/tools/aapt/tests/mocks/MockZipEntry.h b/tools/aapt/tests/mocks/MockZipEntry.h
new file mode 100644
index 0000000..eef07f9
--- /dev/null
+++ b/tools/aapt/tests/mocks/MockZipEntry.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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_MOCK_ZIP_ENTRY
+#define ANDROID_MOCK_ZIP_ENTRY
+
+#include "ZipFile.h"
+#include "gmock/gmock.h"
+
+class MockZipEntry : public android::ZipEntry {
+public:
+ MOCK_CONST_METHOD0(getCompressionMethod, int());
+ MOCK_CONST_METHOD0(getFileName, const char* ());
+};
+
+#endif // ANDROID_MOCK_ZIP_ENTRY
diff --git a/tools/aapt/tests/mocks/MockZipFile.h b/tools/aapt/tests/mocks/MockZipFile.h
new file mode 100644
index 0000000..0394ce7
--- /dev/null
+++ b/tools/aapt/tests/mocks/MockZipFile.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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_MOCK_ZIP_FILE
+#define ANDROID_MOCK_ZIP_FILE
+
+#include "ZipFile.h"
+#include "gmock/gmock.h"
+
+class MockZipFile : public android::ZipFile {
+public:
+ MOCK_CONST_METHOD0(getNumEntries, int());
+ MOCK_CONST_METHOD1(getEntryByIndex, android::ZipEntry* (int idx));
+};
+
+#endif // ANDROID_MOCK_ZIP_FILE
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index 14c9f95..cd4fbe5 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -569,12 +569,19 @@ check_types(const char* filename, document_item_type* items)
if (methodNames.find(m->name.data) == methodNames.end()) {
methodNames[m->name.data] = m;
} else {
- fprintf(stderr,"%s:%d attempt to redefine method %s,\n",
+ if (m->hasId) {
+ fprintf(stderr, "%s:%d redefining method %s\n",
filename, m->name.lineno, m->name.data);
- method_type* old = methodNames[m->name.data];
- fprintf(stderr, "%s:%d previously defined here.\n",
- filename, old->name.lineno);
- err = 1;
+ m->deduplicate = true;
+ methodNames[m->name.data] = m;
+ } else {
+ fprintf(stderr,"%s:%d attempt to redefine method %s,\n",
+ filename, m->name.lineno, m->name.data);
+ method_type* old = methodNames[m->name.data];
+ fprintf(stderr, "%s:%d previously defined here.\n",
+ filename, old->name.lineno);
+ err = 1;
+ }
}
}
member = member->next;
@@ -1014,9 +1021,6 @@ compile_aidl(Options& options)
NAMES.Dump();
#endif
- // check the referenced types in mainDoc to make sure we've imported them
- err |= check_types(options.inputFileName.c_str(), mainDoc);
-
// finally, there really only needs to be one thing in mainDoc, and it
// needs to be an interface.
bool onlyParcelable = false;
@@ -1028,6 +1032,9 @@ compile_aidl(Options& options)
((interface_type*)mainDoc)->interface_items);
}
+ // check the referenced types in mainDoc to make sure we've imported them
+ err |= check_types(options.inputFileName.c_str(), mainDoc);
+
// after this, there shouldn't be any more errors because of the
// input.
if (err != 0 || mainDoc == NULL) {
diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h
index de1370c..f3c850e 100644
--- a/tools/aidl/aidl_language.h
+++ b/tools/aidl/aidl_language.h
@@ -64,6 +64,7 @@ typedef struct method_type {
buffer_type semicolon_token;
buffer_type* comments_token; // points into this structure, DO NOT DELETE
int assigned_id;
+ bool deduplicate;
} method_type;
enum {
diff --git a/tools/aidl/generate_java_binder.cpp b/tools/aidl/generate_java_binder.cpp
index f291ceb..1b538ca 100644
--- a/tools/aidl/generate_java_binder.cpp
+++ b/tools/aidl/generate_java_binder.cpp
@@ -260,6 +260,12 @@ generate_method(const method_type* method, Class* interface,
string transactCodeName = "TRANSACTION_";
transactCodeName += method->name.data;
+ if (method->deduplicate) {
+ char tmp[16];
+ sprintf(tmp, "_%d", index);
+ transactCodeName += tmp;
+ }
+
char transactCodeValue[60];
sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index f2d214c..2b83675 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -497,6 +497,11 @@ public final class BridgeContext extends Context {
}
@Override
+ public void recreateTheme() {
+ throw new UnsupportedOperationException("recreateTheme is unsupported");
+ }
+
+ @Override
public ClassLoader getClassLoader() {
// The documentation for this method states that it should return a class loader one can
// use to retrieve classes in this package. However, when called by LayoutInflater, we do
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 895f9c9..947f99c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -155,4 +155,20 @@ public class BridgePowerManager implements IPowerManager {
public boolean isScreenBrightnessBoosted() throws RemoteException {
return false;
}
+
+ @Override
+ public void setKeyboardVisibility(boolean visible) {
+ // pass for now.
+ }
+
+ @Override
+ public void cpuBoost(int duration) throws RemoteException {
+ // pass for now
+ }
+
+ @Override
+ public void setKeyboardLight(boolean on, int key) {
+ // pass for now
+ }
+
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
index 7e5ae8d..b23d87d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
@@ -45,6 +45,7 @@ public class WindowManagerImpl implements WindowManager {
@Override
public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) {
+ android.util.SeempLog.record_vg(383, arg1);
// pass
}
@@ -55,6 +56,7 @@ public class WindowManagerImpl implements WindowManager {
@Override
public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) {
+ android.util.SeempLog.record_vg(384, arg1);
// pass
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0d95b38..160fd76 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -90,6 +90,8 @@ interface IWifiManager
boolean isDualBandSupported();
+ boolean isIbssSupported();
+
boolean saveConfiguration();
DhcpInfo getDhcpInfo();
diff --git a/wifi/java/android/net/wifi/WifiChannel.java b/wifi/java/android/net/wifi/WifiChannel.java
index 640481e..a526062 100644
--- a/wifi/java/android/net/wifi/WifiChannel.java
+++ b/wifi/java/android/net/wifi/WifiChannel.java
@@ -43,6 +43,9 @@ public class WifiChannel implements Parcelable {
/** is it a DFS channel? */
public boolean isDFS;
+ /** is IBSS allowed? */
+ public boolean ibssAllowed;
+
/** public constructor */
public WifiChannel() { }
@@ -65,6 +68,7 @@ public class WifiChannel implements Parcelable {
out.writeInt(freqMHz);
out.writeInt(channelNum);
out.writeInt(isDFS ? 1 : 0);
+ out.writeInt(ibssAllowed ? 1 : 0);
}
/** implement Parcelable interface */
@@ -76,6 +80,7 @@ public class WifiChannel implements Parcelable {
channel.freqMHz = in.readInt();
channel.channelNum = in.readInt();
channel.isDFS = in.readInt() != 0;
+ channel.ibssAllowed = in.readInt() != 0;
return channel;
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index dc329e2..35d6d9e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -58,8 +58,15 @@ public class WifiConfiguration implements Parcelable {
public static final String pmfVarName = "ieee80211w";
/** {@hide} */
public static final String updateIdentiferVarName = "update_identifier";
+ /** {@hide} */
+ public static final String modeVarName = "mode";
+ /** {@hide} */
+ public static final String frequencyVarName = "frequency";
/** {@hide} */
public static final int INVALID_NETWORK_ID = -1;
+ /** {@hide} */
+ public static final String SIMNumVarName = "sim_num";
+
/**
* Recognized key management schemes.
@@ -302,6 +309,18 @@ public class WifiConfiguration implements Parcelable {
*/
public String updateIdentifier;
+ /**
+ * This is an Ad-Hoc (IBSS) network
+ * {@hide}
+ */
+ public boolean isIBSS;
+
+ /**
+ * Frequency of the Ad-Hoc (IBSS) network, if newly created
+ * {@hide}
+ */
+ public int frequency;
+
/**
* The set of key management protocols supported by this configuration.
* See {@link KeyMgmt} for descriptions of the values.
@@ -426,11 +445,24 @@ public class WifiConfiguration implements Parcelable {
public String autoJoinBSSID;
/**
+ * @hide
+ * sim number selected
+ */
+ public int SIMNum;
+
+ /**
* @hide
* Status of user approval for connection
*/
public int userApproved = USER_UNSPECIFIED;
+ /**
+ * @hide
+ * Inactivity time before wifi tethering is disabled. Here inactivity means no clients
+ * connected. A value of 0 means the AP will not be disabled when there is no activity
+ */
+ public long wifiApInactivityTimeout;
+
/** The Below RSSI thresholds are used to configure AutoJoin
* - GOOD/LOW/BAD thresholds are used so as to calculate link score
* - UNWANTED_SOFT are used by the blacklisting logic so as to handle
@@ -910,6 +942,8 @@ public class WifiConfiguration implements Parcelable {
roamingConsortiumIds = new long[0];
priority = 0;
hiddenSSID = false;
+ isIBSS = false;
+ frequency = 0;
disableReason = DISABLED_UNKNOWN_REASON;
allowedKeyManagement = new BitSet();
allowedProtocols = new BitSet();
@@ -929,6 +963,7 @@ public class WifiConfiguration implements Parcelable {
mIpConfiguration = new IpConfiguration();
lastUpdateUid = -1;
creatorUid = -1;
+ SIMNum = 0;
}
/**
@@ -1088,6 +1123,10 @@ public class WifiConfiguration implements Parcelable {
if (this.preSharedKey != null) {
sbuf.append('*');
}
+ sbuf.append('\n').append(" sim_num ");
+ if (this.SIMNum > 0 ) {
+ sbuf.append('*');
+ }
sbuf.append("\nEnterprise config:\n");
sbuf.append(enterpriseConfig);
@@ -1325,14 +1364,14 @@ public class WifiConfiguration implements Parcelable {
key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP];
} else {
if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
- key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
+ key = SSID + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK];
} else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
- key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
+ key = SSID + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP];
} else if (wepKeys[0] != null) {
- key = SSID + "WEP";
+ key = SSID + "-WEP";
} else {
- key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
+ key = SSID + "-" + KeyMgmt.strings[KeyMgmt.NONE];
}
mCachedConfigKey = key;
}
@@ -1354,17 +1393,16 @@ public class WifiConfiguration implements Parcelable {
if (result.capabilities.contains("WEP")) {
key = key + "-WEP";
- }
-
- if (result.capabilities.contains("PSK")) {
+ } else if (result.capabilities.contains("PSK")) {
key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK];
- }
-
- if (result.capabilities.contains("EAP")) {
+ } else if (result.capabilities.contains("EAP")||
+ result.capabilities.contains("IEEE8021X")) {
key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP];
+ } else {
+ key = key +"-" + KeyMgmt.strings[KeyMgmt.NONE];
}
- return key;
+ return key;
}
/** @hide */
@@ -1453,6 +1491,8 @@ public class WifiConfiguration implements Parcelable {
wepTxKeyIndex = source.wepTxKeyIndex;
priority = source.priority;
hiddenSSID = source.hiddenSSID;
+ isIBSS = source.isIBSS;
+ frequency = source.frequency;
allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone();
allowedProtocols = (BitSet) source.allowedProtocols.clone();
allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone();
@@ -1522,6 +1562,8 @@ public class WifiConfiguration implements Parcelable {
noInternetAccessExpected = source.noInternetAccessExpected;
creationTime = source.creationTime;
updateTime = source.updateTime;
+ SIMNum = source.SIMNum;
+ wifiApInactivityTimeout = source.wifiApInactivityTimeout;
}
}
@@ -1554,6 +1596,8 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(wepTxKeyIndex);
dest.writeInt(priority);
dest.writeInt(hiddenSSID ? 1 : 0);
+ dest.writeInt(isIBSS ? 1 : 0);
+ dest.writeInt(frequency);
dest.writeInt(requirePMF ? 1 : 0);
dest.writeString(updateIdentifier);
@@ -1601,6 +1645,8 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(userApproved);
dest.writeInt(numNoInternetAccessReports);
dest.writeInt(noInternetAccessExpected ? 1 : 0);
+ dest.writeInt(SIMNum);
+ dest.writeLong(wifiApInactivityTimeout);
}
/** Implement the Parcelable interface {@hide} */
@@ -1630,6 +1676,8 @@ public class WifiConfiguration implements Parcelable {
config.wepTxKeyIndex = in.readInt();
config.priority = in.readInt();
config.hiddenSSID = in.readInt() != 0;
+ config.isIBSS = in.readInt() != 0;
+ config.frequency = in.readInt();
config.requirePMF = in.readInt() != 0;
config.updateIdentifier = in.readString();
@@ -1677,6 +1725,8 @@ public class WifiConfiguration implements Parcelable {
config.userApproved = in.readInt();
config.numNoInternetAccessReports = in.readInt();
config.noInternetAccessExpected = in.readInt() != 0;
+ config.SIMNum = in.readInt();
+ config.wifiApInactivityTimeout = in.readLong();
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiDevice.aidl b/wifi/java/android/net/wifi/WifiDevice.aidl
new file mode 100755
index 0000000..c1b186c
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiDevice.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package android.net.wifi;
+
+parcelable WifiDevice;
diff --git a/wifi/java/android/net/wifi/WifiDevice.java b/wifi/java/android/net/wifi/WifiDevice.java
new file mode 100755
index 0000000..163b559
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiDevice.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * Describes information about a detected Wi-Fi STA.
+ * {@hide}
+ */
+public class WifiDevice implements Parcelable {
+ /**
+ * The device MAC address is the unique id of a Wi-Fi STA
+ */
+ public String deviceAddress = "";
+
+ /**
+ * The device name is a readable string of a Wi-Fi STA
+ */
+ public String deviceName = "";
+
+ /**
+ * The device state is the state of a Wi-Fi STA
+ */
+ public int deviceState = 0;
+
+ /**
+ * These definitions are for deviceState
+ */
+ public static final int DISCONNECTED = 0;
+ public static final int CONNECTED = 1;
+ public static final int BLACKLISTED = 2;
+
+ private static final String AP_STA_CONNECTED_STR = "AP-STA-CONNECTED";
+ private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED";
+
+ /** {@hide} */
+ public WifiDevice() {}
+
+ /**
+ * @param string formats supported include
+ *
+ * AP-STA-CONNECTED 42:fc:89:a8:96:09
+ * AP-STA-DISCONNECTED 42:fc:89:a8:96:09
+ *
+ * Note: The events formats can be looked up in the hostapd code
+ * @hide
+ */
+ public WifiDevice(String dataString) throws IllegalArgumentException {
+ String[] tokens = dataString.split(" ");
+
+ if (tokens.length < 2) {
+ throw new IllegalArgumentException();
+ }
+
+ if (tokens[0].indexOf(AP_STA_CONNECTED_STR) != -1) {
+ deviceState = CONNECTED;
+ } else if (tokens[0].indexOf(AP_STA_DISCONNECTED_STR) != -1) {
+ deviceState = DISCONNECTED;
+ } else {
+ throw new IllegalArgumentException();
+ }
+
+ deviceAddress = tokens[1];
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof WifiDevice)) {
+ return false;
+ }
+
+ WifiDevice other = (WifiDevice) obj;
+
+ if (deviceAddress == null) {
+ return (other.deviceAddress == null);
+ } else {
+ return deviceAddress.equals(other.deviceAddress);
+ }
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(deviceAddress);
+ dest.writeString(deviceName);
+ dest.writeInt(deviceState);
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<WifiDevice> CREATOR =
+ new Creator<WifiDevice>() {
+ public WifiDevice createFromParcel(Parcel in) {
+ WifiDevice device = new WifiDevice();
+ device.deviceAddress = in.readString();
+ device.deviceName = in.readString();
+ device.deviceState = in.readInt();
+ return device;
+ }
+
+ public WifiDevice[] newArray(int size) {
+ return new WifiDevice[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index cf88df4..a832c93 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,6 +22,7 @@ package android.net.wifi;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.app.AppOpsManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
@@ -184,6 +188,14 @@ public class WifiManager {
public static final int WIFI_STATE_UNKNOWN = 4;
/**
+ * Wi-Fi is in failed state. This state will occur when load driver failed or start
+ * supplicant failed.
+ *
+ * @hide
+ */
+ public static final int WIFI_STATE_FAILED = 5;
+
+ /**
* Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled,
* enabling, disabling, or failed.
*
@@ -623,6 +635,7 @@ public class WifiManager {
private static final Object sThreadRefLock = new Object();
private static int sThreadRefCount;
private static HandlerThread sHandlerThread;
+ private final AppOpsManager mAppOps;
@GuardedBy("sCM")
// TODO: Introduce refcounting and make this a per-process static callback, instead of a
@@ -644,6 +657,7 @@ public class WifiManager {
mService = service;
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
init();
+ mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
}
/**
@@ -1307,6 +1321,7 @@ public class WifiManager {
* in order to get valid results.
*/
public List<ScanResult> getScanResults() {
+ android.util.SeempLog.record(55);
try {
return mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
@@ -1421,6 +1436,19 @@ public class WifiManager {
}
/**
+ * Check if the chipset supports IBSS (Adhoc) mode
+ * @return {@code true} if supported, {@code false} otherwise.
+ * @hide
+ */
+ public boolean isIbssSupported() {
+ try {
+ return mService.isIbssSupported();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* Return the DHCP-assigned addresses from the last successful DHCP request,
* if any.
* @return the DHCP information
@@ -1440,6 +1468,9 @@ public class WifiManager {
* is the same as the requested state).
*/
public boolean setWifiEnabled(boolean enabled) {
+ if (mAppOps.noteOp(AppOpsManager.OP_WIFI_CHANGE) !=
+ AppOpsManager.MODE_ALLOWED)
+ return false;
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {