diff options
299 files changed, 8132 insertions, 46 deletions
@@ -14,7 +14,8 @@ LOCAL_STATIC_JAVA_LIBRARIES += \ android-support-v7-appcompat \ android-support-v14-preference \ android-support-v17-preference-leanback \ - android-support-v17-leanback + android-support-v17-leanback \ + xz-java LOCAL_RESOURCE_DIR := \ frameworks/support/v17/leanback/res \ diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 9120e7ec..3f1bb1d8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -16,8 +16,11 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" /> <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.KILL_UID" /> + <uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" /> + <application android:label="@string/app_name" android:allowBackup="false" android:theme="@style/Theme.DialogWhenLarge" @@ -97,8 +100,31 @@ android:permission="android.permission.GRANT_RUNTIME_PERMISSIONS"> <intent-filter> <action android:name="android.intent.action.GET_PERMISSIONS_COUNT" /> + <action android:name="android.intent.action.GET_PERMISSIONS_PACKAGES" /> </intent-filter> </receiver> + + <!-- Wearable Components --> + <service android:name=".wear.WearPackageInstallerService" + android:permission="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" + android:exported="true"> + <intent-filter> + <action android:name="com.android.packageinstaller.wear.INSTALL_PACKAGE"/> + <data android:scheme="content" android:mimeType="vnd.android.cursor.item/*"/> + </intent-filter> + <intent-filter> + <action android:name="com.android.packageinstaller.wear.UNINSTALL_PACKAGE"/> + </intent-filter> + </service> + + <provider android:name=".wear.WearPackageIconProvider" + android:authorities="com.google.android.packageinstaller.wear.provider" + android:grantUriPermissions="true" + android:exported="true" /> + + <activity android:name=".permission.ui.wear.WarningConfirmationActivity" + android:permission="android.permission.GRANT_RUNTIME_PERMISSIONS" + android:theme="@style/Settings"/> </application> </manifest> diff --git a/res/drawable-watch-280dpi/ic_cc_cancel.png b/res/drawable-watch-280dpi/ic_cc_cancel.png Binary files differnew file mode 100644 index 00000000..249b8697 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_cc_cancel.png diff --git a/res/drawable-watch-280dpi/ic_cc_checkmark.png b/res/drawable-watch-280dpi/ic_cc_checkmark.png Binary files differnew file mode 100644 index 00000000..94db9ab0 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_cc_checkmark.png diff --git a/res/drawable-watch-280dpi/ic_cc_deny.png b/res/drawable-watch-280dpi/ic_cc_deny.png Binary files differnew file mode 100644 index 00000000..1733669f --- /dev/null +++ b/res/drawable-watch-280dpi/ic_cc_deny.png diff --git a/res/drawable-watch-280dpi/ic_permission_calendar.png b/res/drawable-watch-280dpi/ic_permission_calendar.png Binary files differnew file mode 100644 index 00000000..602bddf0 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_calendar.png diff --git a/res/drawable-watch-280dpi/ic_permission_calendardisable.png b/res/drawable-watch-280dpi/ic_permission_calendardisable.png Binary files differnew file mode 100644 index 00000000..b855932e --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_calendardisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_call.png b/res/drawable-watch-280dpi/ic_permission_call.png Binary files differnew file mode 100644 index 00000000..bcf4f868 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_call.png diff --git a/res/drawable-watch-280dpi/ic_permission_calldisable.png b/res/drawable-watch-280dpi/ic_permission_calldisable.png Binary files differnew file mode 100644 index 00000000..4781e1fe --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_calldisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_camera.png b/res/drawable-watch-280dpi/ic_permission_camera.png Binary files differnew file mode 100644 index 00000000..3d27269f --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_camera.png diff --git a/res/drawable-watch-280dpi/ic_permission_cameradisable.png b/res/drawable-watch-280dpi/ic_permission_cameradisable.png Binary files differnew file mode 100644 index 00000000..51fa2c38 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_cameradisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_contact.png b/res/drawable-watch-280dpi/ic_permission_contact.png Binary files differnew file mode 100644 index 00000000..3e26bfbb --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_contact.png diff --git a/res/drawable-watch-280dpi/ic_permission_contactdisable.png b/res/drawable-watch-280dpi/ic_permission_contactdisable.png Binary files differnew file mode 100644 index 00000000..059b147c --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_contactdisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_location.png b/res/drawable-watch-280dpi/ic_permission_location.png Binary files differnew file mode 100644 index 00000000..f002a9cf --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_location.png diff --git a/res/drawable-watch-280dpi/ic_permission_locationdisable.png b/res/drawable-watch-280dpi/ic_permission_locationdisable.png Binary files differnew file mode 100644 index 00000000..98bbb869 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_locationdisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_mic.png b/res/drawable-watch-280dpi/ic_permission_mic.png Binary files differnew file mode 100644 index 00000000..1ed9c941 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_mic.png diff --git a/res/drawable-watch-280dpi/ic_permission_micdisable.png b/res/drawable-watch-280dpi/ic_permission_micdisable.png Binary files differnew file mode 100644 index 00000000..d74f59b9 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_micdisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_more.png b/res/drawable-watch-280dpi/ic_permission_more.png Binary files differnew file mode 100644 index 00000000..f33e02bf --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_more.png diff --git a/res/drawable-watch-280dpi/ic_permission_sensor.png b/res/drawable-watch-280dpi/ic_permission_sensor.png Binary files differnew file mode 100644 index 00000000..712c5d40 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_sensor.png diff --git a/res/drawable-watch-280dpi/ic_permission_sensordisable.png b/res/drawable-watch-280dpi/ic_permission_sensordisable.png Binary files differnew file mode 100644 index 00000000..8faa436f --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_sensordisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_shield.png b/res/drawable-watch-280dpi/ic_permission_shield.png Binary files differnew file mode 100644 index 00000000..78d6742b --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_shield.png diff --git a/res/drawable-watch-280dpi/ic_permission_shielddisable.png b/res/drawable-watch-280dpi/ic_permission_shielddisable.png Binary files differnew file mode 100644 index 00000000..f0ef4134 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_shielddisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_sms.png b/res/drawable-watch-280dpi/ic_permission_sms.png Binary files differnew file mode 100644 index 00000000..39bb4b3e --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_sms.png diff --git a/res/drawable-watch-280dpi/ic_permission_smsdisable.png b/res/drawable-watch-280dpi/ic_permission_smsdisable.png Binary files differnew file mode 100644 index 00000000..e9375b1f --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_smsdisable.png diff --git a/res/drawable-watch-280dpi/ic_permission_storage.png b/res/drawable-watch-280dpi/ic_permission_storage.png Binary files differnew file mode 100644 index 00000000..60ec50c7 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_storage.png diff --git a/res/drawable-watch-280dpi/ic_permission_storagedisable.png b/res/drawable-watch-280dpi/ic_permission_storagedisable.png Binary files differnew file mode 100644 index 00000000..987b8249 --- /dev/null +++ b/res/drawable-watch-280dpi/ic_permission_storagedisable.png diff --git a/res/drawable-watch-hdpi/ic_cc_cancel.png b/res/drawable-watch-hdpi/ic_cc_cancel.png Binary files differnew file mode 100644 index 00000000..a57893e1 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_cc_cancel.png diff --git a/res/drawable-watch-hdpi/ic_cc_checkmark.png b/res/drawable-watch-hdpi/ic_cc_checkmark.png Binary files differnew file mode 100644 index 00000000..a18fe7ab --- /dev/null +++ b/res/drawable-watch-hdpi/ic_cc_checkmark.png diff --git a/res/drawable-watch-hdpi/ic_cc_deny.png b/res/drawable-watch-hdpi/ic_cc_deny.png Binary files differnew file mode 100644 index 00000000..bab22a3d --- /dev/null +++ b/res/drawable-watch-hdpi/ic_cc_deny.png diff --git a/res/drawable-watch-hdpi/ic_permission_calendar.png b/res/drawable-watch-hdpi/ic_permission_calendar.png Binary files differnew file mode 100644 index 00000000..b7424699 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_calendar.png diff --git a/res/drawable-watch-hdpi/ic_permission_calendardisable.png b/res/drawable-watch-hdpi/ic_permission_calendardisable.png Binary files differnew file mode 100644 index 00000000..def76b03 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_calendardisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_call.png b/res/drawable-watch-hdpi/ic_permission_call.png Binary files differnew file mode 100644 index 00000000..e14a6bd2 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_call.png diff --git a/res/drawable-watch-hdpi/ic_permission_calldisable.png b/res/drawable-watch-hdpi/ic_permission_calldisable.png Binary files differnew file mode 100644 index 00000000..e0f535ff --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_calldisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_camera.png b/res/drawable-watch-hdpi/ic_permission_camera.png Binary files differnew file mode 100644 index 00000000..7c1df6ba --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_camera.png diff --git a/res/drawable-watch-hdpi/ic_permission_cameradisable.png b/res/drawable-watch-hdpi/ic_permission_cameradisable.png Binary files differnew file mode 100644 index 00000000..9637808a --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_cameradisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_contact.png b/res/drawable-watch-hdpi/ic_permission_contact.png Binary files differnew file mode 100644 index 00000000..532e3a2c --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_contact.png diff --git a/res/drawable-watch-hdpi/ic_permission_contactdisable.png b/res/drawable-watch-hdpi/ic_permission_contactdisable.png Binary files differnew file mode 100644 index 00000000..32b45c53 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_contactdisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_location.png b/res/drawable-watch-hdpi/ic_permission_location.png Binary files differnew file mode 100644 index 00000000..3d6c0b9d --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_location.png diff --git a/res/drawable-watch-hdpi/ic_permission_locationdisable.png b/res/drawable-watch-hdpi/ic_permission_locationdisable.png Binary files differnew file mode 100644 index 00000000..c2475e21 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_locationdisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_mic.png b/res/drawable-watch-hdpi/ic_permission_mic.png Binary files differnew file mode 100644 index 00000000..8acb4c5f --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_mic.png diff --git a/res/drawable-watch-hdpi/ic_permission_micdisable.png b/res/drawable-watch-hdpi/ic_permission_micdisable.png Binary files differnew file mode 100644 index 00000000..a37a4e20 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_micdisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_more.png b/res/drawable-watch-hdpi/ic_permission_more.png Binary files differnew file mode 100644 index 00000000..08808bc4 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_more.png diff --git a/res/drawable-watch-hdpi/ic_permission_sensor.png b/res/drawable-watch-hdpi/ic_permission_sensor.png Binary files differnew file mode 100644 index 00000000..fd2939ab --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_sensor.png diff --git a/res/drawable-watch-hdpi/ic_permission_sensordisable.png b/res/drawable-watch-hdpi/ic_permission_sensordisable.png Binary files differnew file mode 100644 index 00000000..487a4861 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_sensordisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_shield.png b/res/drawable-watch-hdpi/ic_permission_shield.png Binary files differnew file mode 100644 index 00000000..cab08e47 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_shield.png diff --git a/res/drawable-watch-hdpi/ic_permission_shielddisable.png b/res/drawable-watch-hdpi/ic_permission_shielddisable.png Binary files differnew file mode 100644 index 00000000..548ac56c --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_shielddisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_sms.png b/res/drawable-watch-hdpi/ic_permission_sms.png Binary files differnew file mode 100644 index 00000000..dc3db2f9 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_sms.png diff --git a/res/drawable-watch-hdpi/ic_permission_smsdisable.png b/res/drawable-watch-hdpi/ic_permission_smsdisable.png Binary files differnew file mode 100644 index 00000000..608c4d04 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_smsdisable.png diff --git a/res/drawable-watch-hdpi/ic_permission_storage.png b/res/drawable-watch-hdpi/ic_permission_storage.png Binary files differnew file mode 100644 index 00000000..031d989f --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_storage.png diff --git a/res/drawable-watch-hdpi/ic_permission_storagedisable.png b/res/drawable-watch-hdpi/ic_permission_storagedisable.png Binary files differnew file mode 100644 index 00000000..08dc6625 --- /dev/null +++ b/res/drawable-watch-hdpi/ic_permission_storagedisable.png diff --git a/res/drawable-watch-mdpi/ic_cc_cancel.png b/res/drawable-watch-mdpi/ic_cc_cancel.png Binary files differnew file mode 100644 index 00000000..87fc65ab --- /dev/null +++ b/res/drawable-watch-mdpi/ic_cc_cancel.png diff --git a/res/drawable-watch-mdpi/ic_cc_checkmark.png b/res/drawable-watch-mdpi/ic_cc_checkmark.png Binary files differnew file mode 100644 index 00000000..02c22b19 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_cc_checkmark.png diff --git a/res/drawable-watch-mdpi/ic_cc_deny.png b/res/drawable-watch-mdpi/ic_cc_deny.png Binary files differnew file mode 100644 index 00000000..f3b29f7f --- /dev/null +++ b/res/drawable-watch-mdpi/ic_cc_deny.png diff --git a/res/drawable-watch-mdpi/ic_permission_calendar.png b/res/drawable-watch-mdpi/ic_permission_calendar.png Binary files differnew file mode 100644 index 00000000..6ae24429 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_calendar.png diff --git a/res/drawable-watch-mdpi/ic_permission_calendardisable.png b/res/drawable-watch-mdpi/ic_permission_calendardisable.png Binary files differnew file mode 100644 index 00000000..639109fa --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_calendardisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_call.png b/res/drawable-watch-mdpi/ic_permission_call.png Binary files differnew file mode 100644 index 00000000..d67a03a5 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_call.png diff --git a/res/drawable-watch-mdpi/ic_permission_calldisable.png b/res/drawable-watch-mdpi/ic_permission_calldisable.png Binary files differnew file mode 100644 index 00000000..39760b74 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_calldisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_camera.png b/res/drawable-watch-mdpi/ic_permission_camera.png Binary files differnew file mode 100644 index 00000000..807a66f6 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_camera.png diff --git a/res/drawable-watch-mdpi/ic_permission_cameradisable.png b/res/drawable-watch-mdpi/ic_permission_cameradisable.png Binary files differnew file mode 100644 index 00000000..edf4f7a7 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_cameradisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_contact.png b/res/drawable-watch-mdpi/ic_permission_contact.png Binary files differnew file mode 100644 index 00000000..2e146e20 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_contact.png diff --git a/res/drawable-watch-mdpi/ic_permission_contactdisable.png b/res/drawable-watch-mdpi/ic_permission_contactdisable.png Binary files differnew file mode 100644 index 00000000..e3903516 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_contactdisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_location.png b/res/drawable-watch-mdpi/ic_permission_location.png Binary files differnew file mode 100644 index 00000000..3862b24c --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_location.png diff --git a/res/drawable-watch-mdpi/ic_permission_locationdisable.png b/res/drawable-watch-mdpi/ic_permission_locationdisable.png Binary files differnew file mode 100644 index 00000000..1f875bd8 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_locationdisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_mic.png b/res/drawable-watch-mdpi/ic_permission_mic.png Binary files differnew file mode 100644 index 00000000..33327f0d --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_mic.png diff --git a/res/drawable-watch-mdpi/ic_permission_micdisable.png b/res/drawable-watch-mdpi/ic_permission_micdisable.png Binary files differnew file mode 100644 index 00000000..7a1b39c4 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_micdisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_more.png b/res/drawable-watch-mdpi/ic_permission_more.png Binary files differnew file mode 100644 index 00000000..a563f1a9 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_more.png diff --git a/res/drawable-watch-mdpi/ic_permission_sensor.png b/res/drawable-watch-mdpi/ic_permission_sensor.png Binary files differnew file mode 100644 index 00000000..59e1c01f --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_sensor.png diff --git a/res/drawable-watch-mdpi/ic_permission_sensordisable.png b/res/drawable-watch-mdpi/ic_permission_sensordisable.png Binary files differnew file mode 100644 index 00000000..d8d55c6d --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_sensordisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_shield.png b/res/drawable-watch-mdpi/ic_permission_shield.png Binary files differnew file mode 100644 index 00000000..7773fa48 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_shield.png diff --git a/res/drawable-watch-mdpi/ic_permission_shielddisable.png b/res/drawable-watch-mdpi/ic_permission_shielddisable.png Binary files differnew file mode 100644 index 00000000..42f452bf --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_shielddisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_sms.png b/res/drawable-watch-mdpi/ic_permission_sms.png Binary files differnew file mode 100644 index 00000000..11333ddb --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_sms.png diff --git a/res/drawable-watch-mdpi/ic_permission_smsdisable.png b/res/drawable-watch-mdpi/ic_permission_smsdisable.png Binary files differnew file mode 100644 index 00000000..b4416f4b --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_smsdisable.png diff --git a/res/drawable-watch-mdpi/ic_permission_storage.png b/res/drawable-watch-mdpi/ic_permission_storage.png Binary files differnew file mode 100644 index 00000000..07bd8f92 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_storage.png diff --git a/res/drawable-watch-mdpi/ic_permission_storagedisable.png b/res/drawable-watch-mdpi/ic_permission_storagedisable.png Binary files differnew file mode 100644 index 00000000..ed8af410 --- /dev/null +++ b/res/drawable-watch-mdpi/ic_permission_storagedisable.png diff --git a/res/drawable-watch-xhdpi/ic_cc_cancel.png b/res/drawable-watch-xhdpi/ic_cc_cancel.png Binary files differnew file mode 100644 index 00000000..fec6ecb8 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_cc_cancel.png diff --git a/res/drawable-watch-xhdpi/ic_cc_checkmark.png b/res/drawable-watch-xhdpi/ic_cc_checkmark.png Binary files differnew file mode 100644 index 00000000..1302723b --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_cc_checkmark.png diff --git a/res/drawable-watch-xhdpi/ic_cc_deny.png b/res/drawable-watch-xhdpi/ic_cc_deny.png Binary files differnew file mode 100644 index 00000000..a5f8dc1b --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_cc_deny.png diff --git a/res/drawable-watch-xhdpi/ic_permission_calendar.png b/res/drawable-watch-xhdpi/ic_permission_calendar.png Binary files differnew file mode 100644 index 00000000..806438c6 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_calendar.png diff --git a/res/drawable-watch-xhdpi/ic_permission_calendardisable.png b/res/drawable-watch-xhdpi/ic_permission_calendardisable.png Binary files differnew file mode 100644 index 00000000..821462e4 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_calendardisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_call.png b/res/drawable-watch-xhdpi/ic_permission_call.png Binary files differnew file mode 100644 index 00000000..079942b5 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_call.png diff --git a/res/drawable-watch-xhdpi/ic_permission_calldisable.png b/res/drawable-watch-xhdpi/ic_permission_calldisable.png Binary files differnew file mode 100644 index 00000000..13cd805e --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_calldisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_camera.png b/res/drawable-watch-xhdpi/ic_permission_camera.png Binary files differnew file mode 100644 index 00000000..03b0d8d0 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_camera.png diff --git a/res/drawable-watch-xhdpi/ic_permission_cameradisable.png b/res/drawable-watch-xhdpi/ic_permission_cameradisable.png Binary files differnew file mode 100644 index 00000000..bcb2a350 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_cameradisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_contact.png b/res/drawable-watch-xhdpi/ic_permission_contact.png Binary files differnew file mode 100644 index 00000000..996fe39d --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_contact.png diff --git a/res/drawable-watch-xhdpi/ic_permission_contactdisable.png b/res/drawable-watch-xhdpi/ic_permission_contactdisable.png Binary files differnew file mode 100644 index 00000000..1063f17b --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_contactdisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_location.png b/res/drawable-watch-xhdpi/ic_permission_location.png Binary files differnew file mode 100644 index 00000000..d9dc1fc9 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_location.png diff --git a/res/drawable-watch-xhdpi/ic_permission_locationdisable.png b/res/drawable-watch-xhdpi/ic_permission_locationdisable.png Binary files differnew file mode 100644 index 00000000..c3e7ae9f --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_locationdisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_mic.png b/res/drawable-watch-xhdpi/ic_permission_mic.png Binary files differnew file mode 100644 index 00000000..3a951ea8 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_mic.png diff --git a/res/drawable-watch-xhdpi/ic_permission_micdisable.png b/res/drawable-watch-xhdpi/ic_permission_micdisable.png Binary files differnew file mode 100644 index 00000000..a9c7c81e --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_micdisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_more.png b/res/drawable-watch-xhdpi/ic_permission_more.png Binary files differnew file mode 100644 index 00000000..a3f7ee5b --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_more.png diff --git a/res/drawable-watch-xhdpi/ic_permission_sensor.png b/res/drawable-watch-xhdpi/ic_permission_sensor.png Binary files differnew file mode 100644 index 00000000..73564014 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_sensor.png diff --git a/res/drawable-watch-xhdpi/ic_permission_sensordisable.png b/res/drawable-watch-xhdpi/ic_permission_sensordisable.png Binary files differnew file mode 100644 index 00000000..ef135a7e --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_sensordisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_shield.png b/res/drawable-watch-xhdpi/ic_permission_shield.png Binary files differnew file mode 100644 index 00000000..2fc8fd07 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_shield.png diff --git a/res/drawable-watch-xhdpi/ic_permission_shielddisable.png b/res/drawable-watch-xhdpi/ic_permission_shielddisable.png Binary files differnew file mode 100644 index 00000000..08a862e8 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_shielddisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_sms.png b/res/drawable-watch-xhdpi/ic_permission_sms.png Binary files differnew file mode 100644 index 00000000..c74ce084 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_sms.png diff --git a/res/drawable-watch-xhdpi/ic_permission_smsdisable.png b/res/drawable-watch-xhdpi/ic_permission_smsdisable.png Binary files differnew file mode 100644 index 00000000..b7256772 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_smsdisable.png diff --git a/res/drawable-watch-xhdpi/ic_permission_storage.png b/res/drawable-watch-xhdpi/ic_permission_storage.png Binary files differnew file mode 100644 index 00000000..1f16bdb6 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_storage.png diff --git a/res/drawable-watch-xhdpi/ic_permission_storagedisable.png b/res/drawable-watch-xhdpi/ic_permission_storagedisable.png Binary files differnew file mode 100644 index 00000000..41d42d57 --- /dev/null +++ b/res/drawable-watch-xhdpi/ic_permission_storagedisable.png diff --git a/res/drawable-watch/action_negative_bg.xml b/res/drawable-watch/action_negative_bg.xml new file mode 100644 index 00000000..7b21ba6d --- /dev/null +++ b/res/drawable-watch/action_negative_bg.xml @@ -0,0 +1,35 @@ +<?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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false"> + <shape android:shape="oval"> + <solid android:color="@color/circular_button_disabled"/> + <size android:width="40dp" android:height="40dp" /> + </shape> + </item> + <item android:state_pressed="true"> + <shape android:shape="oval"> + <solid android:color="#757575"/> + <size android:width="40dp" android:height="40dp" /> + </shape> + </item> + <item> + <shape android:shape="oval"> + <solid android:color="#BDBDBD"/> + <size android:width="40dp" android:height="40dp" /> + </shape> + </item> +</selector> diff --git a/res/drawable-watch/action_positive_bg.xml b/res/drawable-watch/action_positive_bg.xml new file mode 100644 index 00000000..f3457c1a --- /dev/null +++ b/res/drawable-watch/action_positive_bg.xml @@ -0,0 +1,35 @@ +<?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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false"> + <shape android:shape="oval"> + <solid android:color="@color/circular_button_disabled"/> + <size android:width="40dp" android:height="40dp" /> + </shape> + </item> + <item android:state_pressed="true"> + <shape android:shape="oval"> + <solid android:color="#009688"/> + <size android:width="40dp" android:height="40dp" /> + </shape> + </item> + <item> + <shape android:shape="oval"> + <solid android:color="#00BFA5"/> + <size android:width="40dp" android:height="40dp" /> + </shape> + </item> +</selector> diff --git a/res/drawable-watch/cancel_button.xml b/res/drawable-watch/cancel_button.xml new file mode 100644 index 00000000..641526a5 --- /dev/null +++ b/res/drawable-watch/cancel_button.xml @@ -0,0 +1,21 @@ +<?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. +--> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:drawable="@drawable/action_negative_bg" /> + <item> + <bitmap android:src="@drawable/ic_cc_cancel" android:gravity="center" /> + </item> +</layer-list> diff --git a/res/drawable-watch/confirm_button.xml b/res/drawable-watch/confirm_button.xml new file mode 100644 index 00000000..2b53e42e --- /dev/null +++ b/res/drawable-watch/confirm_button.xml @@ -0,0 +1,21 @@ +<?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. +--> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:drawable="@drawable/action_positive_bg" /> + <item> + <bitmap android:src="@drawable/ic_cc_checkmark" android:gravity="center" /> + </item> +</layer-list> diff --git a/res/drawable-watch/deny_button.xml b/res/drawable-watch/deny_button.xml new file mode 100644 index 00000000..1e7582bc --- /dev/null +++ b/res/drawable-watch/deny_button.xml @@ -0,0 +1,21 @@ +<?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. +--> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:drawable="@drawable/action_negative_bg" /> + <item> + <bitmap android:src="@drawable/ic_cc_deny" android:gravity="center" /> + </item> +</layer-list> diff --git a/res/layout-watch/confirmation_dialog.xml b/res/layout-watch/confirmation_dialog.xml new file mode 100644 index 00000000..ea25b6b4 --- /dev/null +++ b/res/layout-watch/confirmation_dialog.xml @@ -0,0 +1,131 @@ +<?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. +--> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/confirmation" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ScrollView + android:id="@+id/scrolling_container" + android:overScrollMode="never" + android:scrollbars="none" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:id="@+id/content" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="@dimen/conf_diag_content_padding_top"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/conf_diag_min_space_above_message" + android:gravity="bottom"> + <TextView + android:id="@+id/current_page_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginTop="@dimen/grant_permissions_app_breadcrumb_margin_top" + android:textAppearance="@style/GrantPermissions.BreadcrumbText" /> + + <ImageView + android:id="@+id/icon" + android:layout_width="@dimen/grant_permissions_app_icon_size" + android:layout_height="@dimen/grant_permissions_app_icon_size" + android:tint="@color/grant_permissions_app_color" + android:layout_gravity="center_horizontal" + android:layout_marginTop="@dimen/grant_permissions_app_icon_margin_top"/> + </LinearLayout> + + <TextView + android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/grant_permissions_title_margin_top" + android:paddingLeft="@dimen/grant_permissions_message_side_padding" + android:paddingRight="@dimen/grant_permissions_message_side_padding" + android:gravity="center" + android:textAppearance="@style/GrantPermissions.TitleText"/> + </LinearLayout> + </ScrollView> + + <!-- TODO: Change this to use a ViewStub instead of show/hiding the two layouts --> + <FrameLayout android:id="@+id/button_bar_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:background="#FF606060"> + <FrameLayout + android:id="@+id/horizontal_button_bar" + android:layout_width="match_parent" + android:layout_height="@dimen/conf_diag_button_container_height"> + <Button + android:id="@+id/permission_deny_button" + android:layout_width="54dp" + android:layout_height="54dp" + android:layout_gravity="top|left" + android:layout_marginLeft="@dimen/conf_diag_2button_margin_side" + android:layout_marginTop="@dimen/conf_diag_2button_margin_top" + android:background="@drawable/cancel_button"/> + + <Button + android:id="@+id/permission_allow_button" + android:layout_width="54dp" + android:layout_height="54dp" + android:layout_gravity="top|right" + android:layout_marginRight="@dimen/conf_diag_2button_margin_side" + android:layout_marginTop="@dimen/conf_diag_2button_margin_top" + android:background="@drawable/confirm_button"/> + </FrameLayout> + + <FrameLayout + android:id="@+id/vertical_button_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingLeft="@dimen/conf_diag_3button_padding_side" + android:paddingRight="@dimen/conf_diag_3button_padding_side" + android:visibility="gone"> + <LinearLayout + android:id="@+id/buttonPanel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> + <Button + android:id="@+id/vertical_button1" + style="@style/Widget.WearDiag.Button"/> + + <Button + android:id="@+id/vertical_button2" + style="@style/Widget.WearDiag.Button"/> + + <Button + android:id="@+id/vertical_button3" + style="@style/Widget.WearDiag.Button"/> + + <!-- Adding padding to the bottom button causes rendering issues, so add + an empty view here instead --> + <Space android:layout_width="match_parent" + android:layout_height="@dimen/conf_diag_3button_padding_bottom"/> + </LinearLayout> + </FrameLayout> + </FrameLayout> +</FrameLayout> diff --git a/res/layout-watch/permissions_settings_item.xml b/res/layout-watch/permissions_settings_item.xml new file mode 100644 index 00000000..b370f1ac --- /dev/null +++ b/res/layout-watch/permissions_settings_item.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + <android.support.wearable.view.CircledImageView + android:id="@+id/image" + android:alpha="0.5" + android:layout_height="52dp" + android:layout_width="52dp" + android:layout_gravity="center_vertical" + app:circle_border_color="#FFFFFFFF" + app:circle_border_width="1dp" + app:circle_color="#00000000" + app:image_tint="#FFFFFFFF"/> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/settings_text_margin_left" + android:layout_gravity="center_vertical" + android:orientation="vertical" > + + <TextView + android:id="@+id/text" + android:alpha="0.5" + android:fontFamily="sans-serif-condensed-light" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/permissions_settings_item_color" + android:textSize="14sp" + android:maxLines="2" + android:ellipsize="end"/> + <TextView + android:id="@+id/state" + android:alpha="0.5" + android:fontFamily="sans-serif-condensed-light" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/permissions_settings_item_color" + android:textSize="14sp" + android:maxLines="1" + android:ellipsize="end"/> + </LinearLayout> + +</LinearLayout> diff --git a/res/layout-watch/settings.xml b/res/layout-watch/settings.xml new file mode 100644 index 00000000..46249d50 --- /dev/null +++ b/res/layout-watch/settings.xml @@ -0,0 +1,21 @@ +<?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. +--> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <include layout="@layout/settings_internal" /> +</FrameLayout> diff --git a/res/layout-watch/settings_internal.xml b/res/layout-watch/settings_internal.xml new file mode 100644 index 00000000..fdd21cef --- /dev/null +++ b/res/layout-watch/settings_internal.xml @@ -0,0 +1,37 @@ +<?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. +--> +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <TextView + android:id="@+id/header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/settings_header_base_height" + android:layout_marginLeft="16dp" + android:layout_marginTop="@dimen/settings_header_top_margin" + android:textSize="@dimen/setting_short_header_text_size" + android:maxLines="2" + android:ellipsize="end" + android:textColor="#9E9E9E" + android:fontFamily="sans-serif-condensed-light" + /> + + <android.support.wearable.view.WearableListView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/wheel" + android:layout_width="match_parent" + android:layout_height="match_parent" + /> +</merge> diff --git a/res/values-af-watch/strings.xml b/res/values-af-watch/strings.xml new file mode 100644 index 00000000..c32ca2b1 --- /dev/null +++ b/res/values-af-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Weier; moenie weer vra nie"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Wys stelselprogramme"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Onveranderbaar"</string> + <string name="generic_enabled" msgid="5221039415230005888">"GEAKTIVEER"</string> + <string name="generic_disabled" msgid="576339310027394867">"GEDEAKTIVEER"</string> +</resources> diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index d814aa9c..635c28b3 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -90,7 +90,7 @@ <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Laat toe"</string> <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Weier"</string> <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> van <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> - <string name="permission_warning_template" msgid="5209102765005869454">"Laat <xliff:g id="APP_NAME">%1$s</xliff:g> toe om te <xliff:g id="ACTION">%2$s</xliff:g>?"</string> + <string name="permission_warning_template" msgid="5209102765005869454">"Laat <xliff:g id="APP_NAME">%1$s</xliff:g> toe om <xliff:g id="ACTION">%2$s</xliff:g>?"</string> <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Programme"</string> <string name="app_permissions" msgid="3146758905824597178">"Programtoestemmings"</string> <string name="never_ask_again" msgid="3798895821072102967">"Moet nooit weer vra nie"</string> @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Skermoorlegger bespeur"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Om hierdie toestemminginstelling te verander, moet jy eers die skermoorlegger by Instellings > Programme afskakel"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Maak instellings oop"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Installeer- en deïnstalleerhandelinge word nie in Wear gesteun nie."</string> </resources> diff --git a/res/values-am-watch/strings.xml b/res/values-am-watch/strings.xml new file mode 100644 index 00000000..73397e34 --- /dev/null +++ b/res/values-am-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ከልክል፣ ዳግም አትጠይቅ"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"የስርዓት መተግበሪያዎችን አሳይ"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ሊለወጥ አይችልም"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ነቅቷል"</string> + <string name="generic_disabled" msgid="576339310027394867">"ተሰናክሏል"</string> +</resources> diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index de1f8538..0b0396fa 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -90,7 +90,7 @@ <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ፍቀድ"</string> <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ከልክል"</string> <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ከ<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> - <string name="permission_warning_template" msgid="5209102765005869454">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="ACTION">%2$s</xliff:g> እንዲያደርግ ይፈቀድለት?"</string> + <string name="permission_warning_template" msgid="5209102765005869454">"<xliff:g id="APP_NAME">%1$s</xliff:g> መተግበሪያ <xliff:g id="ACTION">%2$s</xliff:g> እንዲያደርግ ይፈቀድለት?"</string> <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"መተግበሪያዎች"</string> <string name="app_permissions" msgid="3146758905824597178">"የመተግበሪያ ፈቃዶች"</string> <string name="never_ask_again" msgid="3798895821072102967">"ሁለተኛ እንዳትጠይቅ"</string> @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"የማያ ገጽ ተደራቢ ተገኝቷል"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ይህን የፍቃድ ቅንብር ለመቀየር መጀመሪያ የማያ ገጽ ተደራቢውን ከቅንብሮች > መተግበሪያዎች ማጥፋት አለብዎ"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ቅንብሮችን ክፈት"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"በWear ላይ የመጫን/ማራገፍ እርምጃዎች አይደገፉም።"</string> </resources> diff --git a/res/values-ar-watch/strings.xml b/res/values-ar-watch/strings.xml new file mode 100644 index 00000000..144f7868 --- /dev/null +++ b/res/values-ar-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"الرفض وعدم السؤال مرة أخرى"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"عرض تطبيقات النظام"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"لا يمكن التغيير"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ممكّن"</string> + <string name="generic_disabled" msgid="576339310027394867">"معطّل"</string> +</resources> diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index a4e761a7..788cd44b 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -122,4 +122,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"تم اكتشاف طبقة متراكبة للشاشة"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"لتغيير إعداد هذا الإذن، يتعين عليك أولاً تعطيل الطبقة المتراكبة للشاشة من الإعدادات > التطبيقات"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"فتح الإعدادات"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"لا تتوافق إجراءات التثبيت/إلغاء التثبيت مع Wear."</string> </resources> diff --git a/res/values-az-rAZ-watch/strings.xml b/res/values-az-rAZ-watch/strings.xml new file mode 100644 index 00000000..5d28398e --- /dev/null +++ b/res/values-az-rAZ-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Rədd edin, bir daha soruşmayın"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Sistem tətbiqlərini göstərin"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Dəyişdirilə bilməz"</string> + <string name="generic_enabled" msgid="5221039415230005888">"AKTİV"</string> + <string name="generic_disabled" msgid="576339310027394867">"DEAKTİV"</string> +</resources> diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml index 5fb8257b..d1c9e238 100644 --- a/res/values-az-rAZ/strings.xml +++ b/res/values-az-rAZ/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Ekran örtüyü aşkarlandı"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Bu icazə ayarını dəyişdirmək üçün əvvəldə Ayarlar və Tətbiqlər bölməsindən ekran örtüyünü söndürməlisiniz"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Ayarları açın"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Yükləmə/Silmə fəaliyyətləri Wear\'də dəstəklənmir."</string> </resources> diff --git a/res/values-bg-watch/strings.xml b/res/values-bg-watch/strings.xml new file mode 100644 index 00000000..af81f2a8 --- /dev/null +++ b/res/values-bg-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Отказ, без повторно запитване"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Показване на системните приложения"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Без промяна"</string> + <string name="generic_enabled" msgid="5221039415230005888">"АКТИВИРАНО"</string> + <string name="generic_disabled" msgid="576339310027394867">"ДЕАКТИВИРАНО"</string> +</resources> diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 4260da34..74d29a98 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Открито е екранно наслагване"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"За да промените настройката за това разрешение, трябва първо да изключите екранното наслагване от „Настройки“ > „Приложения“"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Отваряне на настройките"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Действията инсталиране и деинсталиране не се поддържат на устройства с Wear."</string> </resources> diff --git a/res/values-bn-rBD-watch/strings.xml b/res/values-bn-rBD-watch/strings.xml new file mode 100644 index 00000000..d642be1c --- /dev/null +++ b/res/values-bn-rBD-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"অস্বীকার করুন, আবার জিজ্ঞাসা করবেন না"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"সিস্টেম অ্যাপ্লিকেশানগুলি দেখান"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"পরিবর্তন করা যাবে না"</string> + <string name="generic_enabled" msgid="5221039415230005888">"সক্ষম করা রয়েছে"</string> + <string name="generic_disabled" msgid="576339310027394867">"অক্ষম করা রয়েছে"</string> +</resources> diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml index 59bef73a..ce13ce54 100644 --- a/res/values-bn-rBD/strings.xml +++ b/res/values-bn-rBD/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"স্ক্রীন আচ্ছাদন সনাক্ত করা হয়েছে"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"এই অনুমতি সেটিংস পরিবর্তন করতে, আপনাকে প্রথমে সেটিংস > এ গিয়ে অ্যাপ্লিকেশানগুলি থেকে স্ক্রীন ওভারলে বন্ধ করতে হবে"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"সেটিংস খুলুন"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wearএ ইনস্টল/আনইনস্টল করার ক্রিয়াগুলি সমর্থিত নয়।"</string> </resources> diff --git a/res/values-ca-watch/strings.xml b/res/values-ca-watch/strings.xml new file mode 100644 index 00000000..c4f9e3ff --- /dev/null +++ b/res/values-ca-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denega i no m\'ho demanis més"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostra les aplicacions del sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"No es pot canviar"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ACTIVAT"</string> + <string name="generic_disabled" msgid="576339310027394867">"DESACTIVAT"</string> +</resources> diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index c9ce7952..e6971748 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"S\'ha detectat una superposició de pantalla"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Per canviar la configuració de permisos, cal que desactivis la superposició de pantalla des de Configuració > Aplicacions"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Obre Configuració"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Les accions d\'instal·lar o desinstal·lar no s\'admeten a Wear."</string> </resources> diff --git a/res/values-cs-watch/strings.xml b/res/values-cs-watch/strings.xml new file mode 100644 index 00000000..ae6cfbcf --- /dev/null +++ b/res/values-cs-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Odmítnout a již se neptat"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Zobrazit systémové aplikace"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nelze změnit"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ZAPNUTO"</string> + <string name="generic_disabled" msgid="576339310027394867">"VYPNUTO"</string> +</resources> diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 84db63a6..ecc9ce20 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Byla zjištěna překryvná vrstva obrazovky"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Chcete-li změnit nastavení tohoto oprávnění, v Nastavení > Aplikace je třeba nejprve vypnout překryvnou vrstvu obrazovky"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Otevřít nastavení"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Akce instalace/odinstalace nejsou v zařízení Wear podporovány."</string> </resources> diff --git a/res/values-da-watch/strings.xml b/res/values-da-watch/strings.xml new file mode 100644 index 00000000..2fd6279d --- /dev/null +++ b/res/values-da-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Afvis, og spørg ikke igen"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Vis systemapps"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Kan ikke ændres"</string> + <string name="generic_enabled" msgid="5221039415230005888">"AKTIVERET"</string> + <string name="generic_disabled" msgid="576339310027394867">"DEAKTIVERET"</string> +</resources> diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 90f0e8a0..b88dc3b6 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -105,7 +105,7 @@ <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> ud af <xliff:g id="COUNT_1">%2$d</xliff:g> apps har tilladelse"</string> <string name="menu_show_system" msgid="6773743421743728921">"Vis systemapps"</string> <string name="menu_hide_system" msgid="7595471742649432977">"Skjul systemapps"</string> - <string name="permission_title" msgid="6495415273398916381">"<xliff:g id="PERMISSION">%1$s</xliff:g> tilladelser"</string> + <string name="permission_title" msgid="6495415273398916381">"<xliff:g id="PERMISSION">%1$s</xliff:g>-tilladelser"</string> <string name="no_apps" msgid="1965493419005012569">"Ingen apps"</string> <string name="location_settings" msgid="1774875730854491297">"Placeringsindstillinger"</string> <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> udbyder placeringstjenester for denne enhed. Adgangen til din placering kan ændres i Placeringsindstillinger."</string> @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Der er registreret skærmoverlejring"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Hvis du vil ændre denne indstilling for tilladelser, skal du først slå skærmoverlejringen fra i Indstillinger > Apps"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Åbn indstillingerne"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Det er ikke muligt at installere/afinstallere på Wear."</string> </resources> diff --git a/res/values-de-watch/strings.xml b/res/values-de-watch/strings.xml new file mode 100644 index 00000000..be893682 --- /dev/null +++ b/res/values-de-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Ablehnen & nicht mehr fragen"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"System-Apps anzeigen"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Keine Änderung möglich"</string> + <string name="generic_enabled" msgid="5221039415230005888">"Aktiviert"</string> + <string name="generic_disabled" msgid="576339310027394867">"Deaktiviert"</string> +</resources> diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 76776b60..c7798a26 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Display-Overlay erkannt"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Um diese Berechtigungseinstellung zu ändern, müssen Sie zunächst das Display-Overlay über \"Einstellungen\" > \"Apps\" deaktivieren."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Einstellungen öffnen"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Von Android Wear nicht unterstützte Aktionen installieren/deinstallieren."</string> </resources> diff --git a/res/values-el-watch/strings.xml b/res/values-el-watch/strings.xml new file mode 100644 index 00000000..2aa34551 --- /dev/null +++ b/res/values-el-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Απόρριψη και να μην ερωτηθώ ξανά"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Εμφάνιση εφαρμογών συστήματος"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Δεν είναι δυνατή η αλλαγή"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ΕΝΕΡΓΟ"</string> + <string name="generic_disabled" msgid="576339310027394867">"ΑΝΕΝΕΡΓΟ"</string> +</resources> diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index c549a166..a4094cd5 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Εντοπίστηκε επικάλυψη οθόνης"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Για να αλλάξετε αυτή τη ρύθμιση άδειας, θα πρέπει πρώτα να απενεργοποιήσετε την επικάλυψη οθόνης από τις Ρυθμίσεις > Εφαρμογές"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Άνοιγμα ρυθμίσεων"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Οι ενέργειες εγκατάστασης/απεγκατάστασης δεν υποστηρίζονται στο Wear."</string> </resources> diff --git a/res/values-en-rAU-watch/strings.xml b/res/values-en-rAU-watch/strings.xml new file mode 100644 index 00000000..755d64f0 --- /dev/null +++ b/res/values-en-rAU-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ENABLED"</string> + <string name="generic_disabled" msgid="576339310027394867">"DISABLED"</string> +</resources> diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 3986d336..939ce47a 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings > Apps"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Install/Uninstall actions not supported on Wear."</string> </resources> diff --git a/res/values-en-rGB-watch/strings.xml b/res/values-en-rGB-watch/strings.xml new file mode 100644 index 00000000..755d64f0 --- /dev/null +++ b/res/values-en-rGB-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ENABLED"</string> + <string name="generic_disabled" msgid="576339310027394867">"DISABLED"</string> +</resources> diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 3986d336..939ce47a 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings > Apps"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Install/Uninstall actions not supported on Wear."</string> </resources> diff --git a/res/values-en-rIN-watch/strings.xml b/res/values-en-rIN-watch/strings.xml new file mode 100644 index 00000000..755d64f0 --- /dev/null +++ b/res/values-en-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ENABLED"</string> + <string name="generic_disabled" msgid="576339310027394867">"DISABLED"</string> +</resources> diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 3986d336..939ce47a 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings > Apps"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Install/Uninstall actions not supported on Wear."</string> </resources> diff --git a/res/values-es-rUS-watch/strings.xml b/res/values-es-rUS-watch/strings.xml new file mode 100644 index 00000000..120b19bd --- /dev/null +++ b/res/values-es-rUS-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denegar y no preguntar más"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicaciones del sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Inalterable"</string> + <string name="generic_enabled" msgid="5221039415230005888">"HABILITADA"</string> + <string name="generic_disabled" msgid="576339310027394867">"INHABILITADA"</string> +</resources> diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index d65fa542..2c3165ae 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Se detectó una superposición de pantalla"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Para cambiar esta configuración de permisos, primero debes desactivar la superposición de pantalla en Configuración > Aplicaciones"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configuración"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"No se admiten las acciones de instalación y desinstalación en Wear."</string> </resources> diff --git a/res/values-es-watch/strings.xml b/res/values-es-watch/strings.xml new file mode 100644 index 00000000..19b956ac --- /dev/null +++ b/res/values-es-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denegar y no preguntar más"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicaciones del sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"No se puede cambiar"</string> + <string name="generic_enabled" msgid="5221039415230005888">"HABILITADA"</string> + <string name="generic_disabled" msgid="576339310027394867">"INHABILITADA"</string> +</resources> diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 04270e4b..d5e3059b 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Superposición de pantalla detectada"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Para cambiar la configuración de este permiso, desactiva la superposición de pantalla en Ajustes > Aplicaciones"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir ajustes"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"No puedes instalar ni desinstalar aplicaciones en Wear."</string> </resources> diff --git a/res/values-et-rEE-watch/strings.xml b/res/values-et-rEE-watch/strings.xml new file mode 100644 index 00000000..947809d9 --- /dev/null +++ b/res/values-et-rEE-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Keela, ära enam küsi"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Kuva süsteemirakendused"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ei saa muuta"</string> + <string name="generic_enabled" msgid="5221039415230005888">"LUBATUD"</string> + <string name="generic_disabled" msgid="576339310027394867">"KEELATUD"</string> +</resources> diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml index 9f17942b..e600f68a 100644 --- a/res/values-et-rEE/strings.xml +++ b/res/values-et-rEE/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Tuvastati ekraani ülekate"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Selle loa seade muutmiseks peate esmalt välja lülitama ekraani ülekatte menüüs Seaded > Rakendused"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Ava seaded"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear ei toeta installimist/desinstallimist."</string> </resources> diff --git a/res/values-eu-rES-watch/strings.xml b/res/values-eu-rES-watch/strings.xml new file mode 100644 index 00000000..25e2429e --- /dev/null +++ b/res/values-eu-rES-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Ukatu; ez galdetu berriro"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Erakutsi sistema-aplikazioak"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ezin da aldatu"</string> + <string name="generic_enabled" msgid="5221039415230005888">"GAITUTA"</string> + <string name="generic_disabled" msgid="576339310027394867">"DESGAITUTA"</string> +</resources> diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml index 706e1888..d358c1fd 100644 --- a/res/values-eu-rES/strings.xml +++ b/res/values-eu-rES/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Pantailaren gainjartzea detektatu da"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Baimen-ezarpen hau aldatzeko, pantailaren gainjartzea desaktibatu behar duzu Ezarpenak > Aplikazioak atalean"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Ireki ezarpenak"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Instalatzeko eta desinstalatzeko ekintzak ezin dira gauzatu Wear gailuetan."</string> </resources> diff --git a/res/values-fa-watch/strings.xml b/res/values-fa-watch/strings.xml new file mode 100644 index 00000000..15029959 --- /dev/null +++ b/res/values-fa-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"رد شود، دیگر سؤال نشود"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"نمایش برنامههای سیستم"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"نمیتواند تغییر کند"</string> + <string name="generic_enabled" msgid="5221039415230005888">"فعال شد"</string> + <string name="generic_disabled" msgid="576339310027394867">"غیرفعال شد"</string> +</resources> diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 54c6396b..09e20092 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"همپوشانی صفحه شناسایی شد"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"برای تغییر این تنظیم مجوز، ابتدا باید همپوشانی صفحه را از «تنظیمات > برنامهها» خاموش کنید"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"باز کردن تنظیمات"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"نصب/حذف نصب عملکردها در Wear پشتیبانی نمیشود."</string> </resources> diff --git a/res/values-fi-watch/strings.xml b/res/values-fi-watch/strings.xml new file mode 100644 index 00000000..5305299c --- /dev/null +++ b/res/values-fi-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Hylkää, äläkä kysy uudelleen"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Näytä järjestelmäsovellukset"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ei muutettavissa"</string> + <string name="generic_enabled" msgid="5221039415230005888">"KÄYTÖSSÄ"</string> + <string name="generic_disabled" msgid="576339310027394867">"POIS KÄYTÖSTÄ"</string> +</resources> diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 4c69ed96..e7999d36 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Näytön peittokuva havaittiin"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Ennen kuin voit muokata tätä käyttöoikeusasetusta, sinun täytyy poistaa näytön peittokuva käytöstä Asetukset-valikon Sovellukset-kohdasta."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Avaa Asetukset"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear ei tue asennus- ja poistotoimintoja."</string> </resources> diff --git a/res/values-fr-rCA-watch/strings.xml b/res/values-fr-rCA-watch/strings.xml new file mode 100644 index 00000000..cb176c27 --- /dev/null +++ b/res/values-fr-rCA-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Refuser et ne plus demander"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Afficher les applications système"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Inchangeable"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ACTIVÉ"</string> + <string name="generic_disabled" msgid="576339310027394867">"DÉSACTIVÉ"</string> +</resources> diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 25d900c6..5d3cb8c1 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"La superposition d\'écran a été détectée"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Pour modifier ce paramètre d\'autorisation, vous devez tout d\'abord désactiver la superposition d\'écran en accédant à Paramètres > Applications."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Ouvrir les paramètres"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Les actions d\'installation et de désinstallation ne sont pas prises en charge par Android Wear."</string> </resources> diff --git a/res/values-fr-watch/strings.xml b/res/values-fr-watch/strings.xml new file mode 100644 index 00000000..c567d03b --- /dev/null +++ b/res/values-fr-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Refuser et ne plus demander"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Afficher les applications système"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Non modifiable"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ACTIVÉ"</string> + <string name="generic_disabled" msgid="576339310027394867">"DÉSACTIVÉ"</string> +</resources> diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index bd1f9440..a7ff6998 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Superposition d\'écran détectée"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Pour modifier ce paramètre d\'autorisation, vous devez tout d\'abord désactiver la superposition d\'écran en accédant à Paramètres > Applications."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Ouvrir les paramètres"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Opérations d\'installation et de désinstallation impossibles sur Android Wear"</string> </resources> diff --git a/res/values-gl-rES-watch/strings.xml b/res/values-gl-rES-watch/strings.xml new file mode 100644 index 00000000..38e4e6cb --- /dev/null +++ b/res/values-gl-rES-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denegar, non volver preguntar"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicacións do sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Cambio imposible"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ACTIVADO"</string> + <string name="generic_disabled" msgid="576339310027394867">"DESACTIVADO"</string> +</resources> diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml index 19245166..477169ea 100644 --- a/res/values-gl-rES/strings.xml +++ b/res/values-gl-rES/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Detectouse a superposición da pantalla"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Para cambiar a configuración deste permiso, primeiro tes que desactivar a superposición da pantalla en Configuración > Aplicacións"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configuración"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"As accións de instalar e desinstalar non son compatibles con Wear."</string> </resources> diff --git a/res/values-gu-rIN-watch/strings.xml b/res/values-gu-rIN-watch/strings.xml new file mode 100644 index 00000000..3530b6a9 --- /dev/null +++ b/res/values-gu-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"નકારો, ફરીથી પૂછશો નહીં"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"સિસ્ટમ એપ્લિકેશનો બતાવો"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"બદલી શકતાં નથી"</string> + <string name="generic_enabled" msgid="5221039415230005888">"સક્ષમ કરેલ"</string> + <string name="generic_disabled" msgid="576339310027394867">"અક્ષમ કરેલ"</string> +</resources> diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml index fb11e93f..40951dd2 100644 --- a/res/values-gu-rIN/strings.xml +++ b/res/values-gu-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"સ્ક્રીન ઓવરલે મળ્યું"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"આ પરવાનગી સેટિંગ બદલવા માટે, તમારે પહેલા સેટિંગ્સ > Apps માંથી સ્ક્રીન ઓવરલે બંધ કરવું પડશે"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"સેટિંગ્સ ખોલો"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear પર ઇન્સ્ટૉલ/અનઇન્સ્ટૉલ ક્રિયાઓ સમર્થિત નથી."</string> </resources> diff --git a/res/values-hi-watch/strings.xml b/res/values-hi-watch/strings.xml new file mode 100644 index 00000000..39c93948 --- /dev/null +++ b/res/values-hi-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"मना करें, फिर से ना पूछें"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"सिस्टम ऐप्स दिखाएं"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"बदला नहीं जा सकता"</string> + <string name="generic_enabled" msgid="5221039415230005888">"सक्षम"</string> + <string name="generic_disabled" msgid="576339310027394867">"अक्षम"</string> +</resources> diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 0ca0ab17..0f353d30 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"स्क्रीन ओवरले को पहचाना गया"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"इस अनुमति सेटिंग को बदलने के लिए, आपको पहले सेटिंग > ऐप्स से स्क्रीन ओवरले को बंद करना होगा"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"सेटिंग खोलें"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"इंस्टॉल/अनइंस्टॉल किए जाने की कार्रवाइयां Wear पर समर्थित नहीं हैं."</string> </resources> diff --git a/res/values-hr-watch/strings.xml b/res/values-hr-watch/strings.xml new file mode 100644 index 00000000..37658e5e --- /dev/null +++ b/res/values-hr-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Ne, više ne pitaj"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Prikaži aplikacije sustava"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Promjena nemoguća"</string> + <string name="generic_enabled" msgid="5221039415230005888">"OMOGUĆENO"</string> + <string name="generic_disabled" msgid="576339310027394867">"ONEMOGUĆENO"</string> +</resources> diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index be51e443..8cead087 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -119,4 +119,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Otkriveno je preklapanje na zaslonu"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Da biste promijenili tu postavku dopuštenja, prvo morate isključiti preklapanje na zaslonu u Postavkama > Aplikacije"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Otvori postavke"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Radnje instaliranja i deinstaliranja nisu podržane na Wearu."</string> </resources> diff --git a/res/values-hu-watch/strings.xml b/res/values-hu-watch/strings.xml new file mode 100644 index 00000000..8a116dff --- /dev/null +++ b/res/values-hu-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Megtagadás, ne jelenjen meg"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>/<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Rendszeralkalmazások megjelenítése"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nem változtatható"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ENGEDÉLYEZVE"</string> + <string name="generic_disabled" msgid="576339310027394867">"LETILTVA"</string> +</resources> diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 9c8b1db2..84aab320 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Képernyőfedvény észlelve"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Ennek az engedélynek a módosításához először ki kell kapcsolnia a képernyőfedvényt a Beállítások > Alkalmazások menüben"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Beállítások megnyitása"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"A Wear nem támogatja a telepítés/eltávolítás műveletet."</string> </resources> diff --git a/res/values-hy-rAM-watch/strings.xml b/res/values-hy-rAM-watch/strings.xml new file mode 100644 index 00000000..08786c11 --- /dev/null +++ b/res/values-hy-rAM-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Մերժել, այլևս չհարցնել"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Ցուցադրել համակարգի հավելվածները"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Հնարավոր չէ փոխել"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ՄԻԱՑՎԱԾ"</string> + <string name="generic_disabled" msgid="576339310027394867">"ԱՆՋԱՏՎԱԾ"</string> +</resources> diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml index b4b4fde3..00a4e301 100644 --- a/res/values-hy-rAM/strings.xml +++ b/res/values-hy-rAM/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Հայտնաբերվել է էկրանի վերադրում"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Այս թույլտվության կարգավորումները փոխելու համար նախ անհրաժեշտ է անջատել էկրանի վերադրումը՝ անցնելով Կարգավորումներ > Հավելվածներ"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Բացել կարգավորումները"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Տեղադրման/հեռացման գործողությունները Android Wear-ում չեն աջակցվում:"</string> </resources> diff --git a/res/values-in-watch/strings.xml b/res/values-in-watch/strings.xml new file mode 100644 index 00000000..38ad48b9 --- /dev/null +++ b/res/values-in-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Tolak, jangan tanya lagi"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Tampilkan aplikasi sistem"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Tidak dapat diubah"</string> + <string name="generic_enabled" msgid="5221039415230005888">"DIAKTIFKAN"</string> + <string name="generic_disabled" msgid="576339310027394867">"DINONAKTIFKAN"</string> +</resources> diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 589f2954..c20e0b6e 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Hamparan layar terdeteksi"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Untuk mengubah setelan izin ini, terlebih dahulu Anda harus menonaktifkan hamparan layar dari Setelan > Aplikasi"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Buka setelan"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Tindakan Pasang/Copot Pemasangan tidak didukung di Wear."</string> </resources> diff --git a/res/values-is-rIS-watch/strings.xml b/res/values-is-rIS-watch/strings.xml new file mode 100644 index 00000000..c8f92448 --- /dev/null +++ b/res/values-is-rIS-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Hafna, ekki spyrja aftur"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Sýna kerfisforrit"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Má ekki breyta"</string> + <string name="generic_enabled" msgid="5221039415230005888">"VIRKT"</string> + <string name="generic_disabled" msgid="576339310027394867">"ÓVIRKT"</string> +</resources> diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml index 41d176df..7a5a39c9 100644 --- a/res/values-is-rIS/strings.xml +++ b/res/values-is-rIS/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Skjáyfirlögn greindist"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Til að breyta þessari heimildarstillingu þarftu fyrst að slökkva á skjáyfirlögn undir Stillingar > Forrit"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Opna stillingar"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Uppsetningar-/fjarlægingaraðgerðir eru ekki studdar í Wear."</string> </resources> diff --git a/res/values-it-watch/strings.xml b/res/values-it-watch/strings.xml new file mode 100644 index 00000000..4a44dca9 --- /dev/null +++ b/res/values-it-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Nega e non chiedermelo più"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostra app di sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Imposs modif"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ATTIVATO"</string> + <string name="generic_disabled" msgid="576339310027394867">"DISATTIVATO"</string> +</resources> diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 68543309..442d78ca 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Overlay schermo rilevato"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Per modificare questa impostazione di autorizzazione, devi innanzitutto disattivare l\'overlay schermo da Impostazioni > App"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Apri impostazioni"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Le azioni di installazione/disinstallazione non sono supportate su Wear."</string> </resources> diff --git a/res/values-iw-watch/strings.xml b/res/values-iw-watch/strings.xml new file mode 100644 index 00000000..d27e2d7d --- /dev/null +++ b/res/values-iw-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"דחה ואל תשאל שוב"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"הצג אפליקציות מערכת"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"לא ניתן לשנות"</string> + <string name="generic_enabled" msgid="5221039415230005888">"מופעל"</string> + <string name="generic_disabled" msgid="576339310027394867">"מושבת"</string> +</resources> diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index e2f1057b..fc22c872 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"זוהתה שכבת על במסך"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"כדי לשנות את הגדרת ההרשאה הזו, ראשית עליך לכבות את שכבת העל במסך ב\'הגדרות\' > \'אפליקציות\'"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"פתח הגדרות"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"פעולות התקנה/הסרת התקנה אינן נתמכות ב-Wear."</string> </resources> diff --git a/res/values-ja-watch/strings.xml b/res/values-ja-watch/strings.xml new file mode 100644 index 00000000..f3e83c84 --- /dev/null +++ b/res/values-ja-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"許可しない(今後表示しない)"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"システムアプリの表示"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"変更不可"</string> + <string name="generic_enabled" msgid="5221039415230005888">"有効"</string> + <string name="generic_disabled" msgid="576339310027394867">"無効"</string> +</resources> diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index f5f294e9..dc32fc37 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"画面オーバーレイを検出"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"この権限設定を変更するには、まず[設定]>[アプリ]から画面オーバーレイをOFFにします"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"設定を開く"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wearでのインストールおよびアンインストール操作はサポートされていません。"</string> </resources> diff --git a/res/values-ka-rGE-watch/strings.xml b/res/values-ka-rGE-watch/strings.xml new file mode 100644 index 00000000..6498a4dc --- /dev/null +++ b/res/values-ka-rGE-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"უარყავი და აღარ მკითხო"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"სისტემის აპების ჩვენება"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ვერ შეიცვლება"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ჩართულია"</string> + <string name="generic_disabled" msgid="576339310027394867">"გამორთულია"</string> +</resources> diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml index 41ce43b3..f365a6cf 100644 --- a/res/values-ka-rGE/strings.xml +++ b/res/values-ka-rGE/strings.xml @@ -119,4 +119,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"ეკრანის გადაფარვა გამოვლინდა"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ამ ნებართვის პარამეტრის შესაცვლელად, ჯერ უნდა გამორთოთ ეკრანის გადაფარვა პარამეტრებიდან > აპებიდან"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"პარამეტრების გახსნა"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"ინსტალაციის/დეინსტალაციის მოქმედებები არ არის მხარდაჭერილი Wear-ზე."</string> </resources> diff --git a/res/values-kk-rKZ-watch/strings.xml b/res/values-kk-rKZ-watch/strings.xml new file mode 100644 index 00000000..dfff10bf --- /dev/null +++ b/res/values-kk-rKZ-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Тыйым салу, қайтадан сұрамау"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Жүйелік қолданбаларды көрсету"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Өзгерту мүмкін емес"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ҚОСЫЛҒАН"</string> + <string name="generic_disabled" msgid="576339310027394867">"ӨШІРІЛГЕН"</string> +</resources> diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml index 8fe10ee4..c450d48b 100644 --- a/res/values-kk-rKZ/strings.xml +++ b/res/values-kk-rKZ/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Экранды қабаттастыру анықталды"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Бұл рұқсат параметрін өзгерту үшін алдымен «Параметрлер» > «Қолданбалар» тармағында экранды қабаттастыруды өшіру керек"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Параметрлерді ашу"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear құрылғысында \"Орнату\"/\"Жою\" әрекеттеріне қолдау көрсетілмейді."</string> </resources> diff --git a/res/values-km-rKH-watch/strings.xml b/res/values-km-rKH-watch/strings.xml new file mode 100644 index 00000000..1beebfdb --- /dev/null +++ b/res/values-km-rKH-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"បដិសេធ សូមកុំសួរម្តងទៀត"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"បង្ហាញកម្មវិធីប្រព័ន្ធ"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"មិនអាចប្តូរបានទេ"</string> + <string name="generic_enabled" msgid="5221039415230005888">"បានបើកដំណើរការ"</string> + <string name="generic_disabled" msgid="576339310027394867">"បានបិទដំណើរការ"</string> +</resources> diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml index 6396a99e..f8958c0a 100644 --- a/res/values-km-rKH/strings.xml +++ b/res/values-km-rKH/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"បានរកឃើញអេក្រង់ត្រួតគ្នា"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ដើម្បីប្តូរការកំណត់សិទ្ធិអនុញ្ញាតនេះ ជាដំបូងអ្នកត្រូវបិទអេក្រង់ត្រួតគ្នានៅក្នុង ការកំណត់ > កម្មវិធី"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"បើកការកំណត់"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"សកម្មភាពដំឡើង/លុបការដំឡើងមិនគាំទ្រនៅលើ Wear ទេ"</string> </resources> diff --git a/res/values-kn-rIN-watch/strings.xml b/res/values-kn-rIN-watch/strings.xml new file mode 100644 index 00000000..6ed8b36f --- /dev/null +++ b/res/values-kn-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ನಿರಾಕರಿಸಿ, ಮತ್ತೆ ಕೇಳಬೇಡಿ"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"ಸಿಸ್ಟಂ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ತೋರಿಸು"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> + <string name="generic_disabled" msgid="576339310027394867">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> +</resources> diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml index 9ff55f9f..298b7cfd 100644 --- a/res/values-kn-rIN/strings.xml +++ b/res/values-kn-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"ಪರದೆ ಆವರಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಪತ್ತೆಹಚ್ಚಲಾಗಿದೆ"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ಈ ಅನುಮತಿ ಸೆಟ್ಟಿಂಗ್ ಬದಲಾಯಿಸಲು, ನೀವು ಮೊದಲು ಸೆಟ್ಟಿಂಗ್ಗಳು > ಅಪ್ಲಿಕೇಶನ್ಗಳಿಂದ ಪರದೆ ಆವರಿಸಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಆಫ್ ಮಾಡಬೇಕು"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"ಸ್ಥಾಪಿಸುವಿಕೆ/ಅಸ್ಥಾಪಿಸುವಿಕೆ ಕ್ರಿಯೆಗಳು Wear ನಲ್ಲಿ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string> </resources> diff --git a/res/values-ko-watch/strings.xml b/res/values-ko-watch/strings.xml new file mode 100644 index 00000000..0bdafac3 --- /dev/null +++ b/res/values-ko-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"거부 및 다시 묻지 않음"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"시스템 앱 보기"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"변경할 수 없음"</string> + <string name="generic_enabled" msgid="5221039415230005888">"사용"</string> + <string name="generic_disabled" msgid="576339310027394867">"사용 안함"</string> +</resources> diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 55867cc9..17310e3e 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"화면 오버레이 감지됨"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"이 권한 설정을 변경하려면 먼저 설정 > 앱에서 화면 오버레이를 사용하지 않도록 설정해야 합니다."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"설정 열기"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear에서 지원하지 않는 설치/제거 작업입니다."</string> </resources> diff --git a/res/values-ky-rKG-watch/strings.xml b/res/values-ky-rKG-watch/strings.xml new file mode 100644 index 00000000..74a3b8b3 --- /dev/null +++ b/res/values-ky-rKG-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Баш тарам, экинчи суралбасын"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Тутум колдонмолорун көрсөтүү"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Өзгөртүүгө болбойт"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ИШТЕТИЛГЕН"</string> + <string name="generic_disabled" msgid="576339310027394867">"ӨЧҮРҮЛГӨН"</string> +</resources> diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml index 0716c2fa..c1ebdde4 100644 --- a/res/values-ky-rKG/strings.xml +++ b/res/values-ky-rKG/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Экран кабатталышы аныкталды"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Бул уруксаттын жөндөөсүн өзгөртүү үчүн, адегенде Жөндөөлөр > Колдонмолордон экрандын кабатталышын өчүрүңүз"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Жөндөөлөрдү ачуу"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Тагынма"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Орнотуу/чыгарып салуу аракеттери Тагынмада колдоого алынбайт."</string> </resources> diff --git a/res/values-lo-rLA-watch/strings.xml b/res/values-lo-rLA-watch/strings.xml new file mode 100644 index 00000000..e362c39f --- /dev/null +++ b/res/values-lo-rLA-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ປະຕິເສດ, ຢ່າຖາມອີກ"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"ສະແດງແອັບລະບົບ"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ບໍ່ສາມາດປ່ຽນແປງໄດ້"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ເປີດໃຊ້ງານແລ້ວ"</string> + <string name="generic_disabled" msgid="576339310027394867">"ປິດໃຊ້ງານແລ້ວ"</string> +</resources> diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml index 4e0203be..7c67c2ce 100644 --- a/res/values-lo-rLA/strings.xml +++ b/res/values-lo-rLA/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"ກວດພົບການວາງຊ້ອນໜ້າຈໍແລ້ວ"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ເພື່ອປ່ຽນແປງການຕັ້ງຄ່າການອະນຸຍາດນີ້, ກ່ອນອື່ນໝົດທ່ານຕ້ອງປິດການວາງຊ້ອນໜ້າຈໍຈາກແອັບການຕັ້ງຄ່າ"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ເປີດການຕັ້ງຄ່າ"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"ຕິດຕັ້ງ/ຖອນຕິດຕັ້ງການກະທຳທີ່ບໍ່ຮອງຮັບຢູ່ໃນ Wear."</string> </resources> diff --git a/res/values-lt-watch/strings.xml b/res/values-lt-watch/strings.xml new file mode 100644 index 00000000..c10c5e8f --- /dev/null +++ b/res/values-lt-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Atmesti, daugiau neklausti"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Rodyti sistemos programas"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Negalima pakeisti"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ĮGALINTAS"</string> + <string name="generic_disabled" msgid="576339310027394867">"IŠJUNGTAS"</string> +</resources> diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index c8897229..2ce9c3a2 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Aptikta ekrano perdanga"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Jei norite pakeisti šį leidimo nustatymą, pirmiausia turite išjungti ekrano perdangą skiltyje „Nustatymai > Programos“"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Atidaryti nustatymus"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Diegimo / pašalinimo veiksmai nepalaikomi sistemoje „Wear“."</string> </resources> diff --git a/res/values-lv-watch/strings.xml b/res/values-lv-watch/strings.xml new file mode 100644 index 00000000..aeb3c045 --- /dev/null +++ b/res/values-lv-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Neatļaut un vairs nejautāt"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>. no <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Rādīt sistēmas lietotnes"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nevar mainīt"</string> + <string name="generic_enabled" msgid="5221039415230005888">"IESPĒJOTS"</string> + <string name="generic_disabled" msgid="576339310027394867">"ATSPĒJOTS"</string> +</resources> diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 27b71cd0..718c5a5f 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -119,4 +119,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Konstatēts ekrāna pārklājums"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Lai mainītu šo atļaujas iestatījumu, vispirms sadaļā “Iestatījumi un lietotnes” izslēdziet ekrāna pārklājumu."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Atvērt iestatījumus"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear ierīcē netiek atbalstīta instalēšana/atinstalēšana."</string> </resources> diff --git a/res/values-mk-rMK-watch/strings.xml b/res/values-mk-rMK-watch/strings.xml new file mode 100644 index 00000000..d23ce70d --- /dev/null +++ b/res/values-mk-rMK-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Одбиј, не прашувај повторно"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Прикажи ги системските апликации"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Не може да се смени"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ОВОЗМОЖЕНО"</string> + <string name="generic_disabled" msgid="576339310027394867">"ОНЕВОЗМОЖЕНО"</string> +</resources> diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml index 8cc487b2..80b5feb3 100644 --- a/res/values-mk-rMK/strings.xml +++ b/res/values-mk-rMK/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Откривме преклопување на екранот"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"За да ја измените оваа поставка за дозвола, прво мора да го исклучите преклопувањето на екранот од Поставки > Апликации"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Отвори поставки"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Дејствата инсталирај/деинсталирај не се поддржани на Wear."</string> </resources> diff --git a/res/values-ml-rIN-watch/strings.xml b/res/values-ml-rIN-watch/strings.xml new file mode 100644 index 00000000..b5056315 --- /dev/null +++ b/res/values-ml-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"നിരസിക്കുക, വീണ്ടും ആവശ്യപ്പെടരുത്"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"സിസ്റ്റം ആപ്സ് കാണിക്കുക"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"മാറ്റാനാവില്ല"</string> + <string name="generic_enabled" msgid="5221039415230005888">"പ്രവർത്തനക്ഷമമാക്കി"</string> + <string name="generic_disabled" msgid="576339310027394867">"പ്രവർത്തനരഹിതമാക്കി"</string> +</resources> diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml index 55a3d09a..7436447b 100644 --- a/res/values-ml-rIN/strings.xml +++ b/res/values-ml-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"സ്ക്രീൻ ഓവർലേ കണ്ടെത്തി"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ഈ അനുമതി ക്രമീകരണം മാറ്റുന്നതിന്, ക്രമീകരണം > ആപ്സ് എന്നതിൽ നിന്ന് നിങ്ങളാദ്യം സ്ക്രീൻ ഓവർലേ ഓഫാക്കേണ്ടതാണ്"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ക്രമീകരണം തുറക്കുക"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"ഇൻസ്റ്റാളോ അൺഇൻസ്റ്റാളോ ചെയ്യുന്നതിന് Wear-ൽ പിന്തുണയില്ല."</string> </resources> diff --git a/res/values-mn-rMN-watch/strings.xml b/res/values-mn-rMN-watch/strings.xml new file mode 100644 index 00000000..38c8c9a2 --- /dev/null +++ b/res/values-mn-rMN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Татгалзах, дахин бүү асуугаарай"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Системийн апп-ыг харуулах"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Өөрчлөх боломжгүй"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ИДЭВХЖҮҮЛСЭН"</string> + <string name="generic_disabled" msgid="576339310027394867">"ИДЭВХГҮЙ БОЛГОСОН"</string> +</resources> diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml index 3bce33e9..c7d5431e 100644 --- a/res/values-mn-rMN/strings.xml +++ b/res/values-mn-rMN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Дэлгэцийн давхарга илрүүллээ"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Зөвшөөрлийн тохиргоог өөрчлөхийн тулд, эхлээд Тохиргоо ба Апп хэсгээс дэлгэцийн давхаргыг унтраана уу."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Тохиргоог нээх"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Суулгах/Устгах үйлдлийг Wear дэмжээгүй."</string> </resources> diff --git a/res/values-mr-rIN-watch/strings.xml b/res/values-mr-rIN-watch/strings.xml new file mode 100644 index 00000000..55b6dd33 --- /dev/null +++ b/res/values-mr-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"नकार द्या, पुन्हा विचारू नका"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"सिस्टीम अॅप्स दर्शवा"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"बदलू शकत नाही"</string> + <string name="generic_enabled" msgid="5221039415230005888">"सक्षम केले"</string> + <string name="generic_disabled" msgid="576339310027394867">"अक्षम केले"</string> +</resources> diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml index b4a3049f..33329489 100644 --- a/res/values-mr-rIN/strings.xml +++ b/res/values-mr-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"स्क्रीन आच्छादन आढळले"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"हे परवानगी सेटिंग बदलण्यासाठी, आपल्याला सेटिंग्ज > Apps मधून स्क्रीन आच्छादन बंद करावे लागेल"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"सेटिंग्ज उघडा"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"स्थापित करा/विस्थापित करा क्रिया Wear वर समर्थित नाहीत."</string> </resources> diff --git a/res/values-ms-rMY-watch/strings.xml b/res/values-ms-rMY-watch/strings.xml new file mode 100644 index 00000000..b69b711d --- /dev/null +++ b/res/values-ms-rMY-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Tolak, jangan tanya lagi"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Tunjukkan apl sistem"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Tidak dpt diubah"</string> + <string name="generic_enabled" msgid="5221039415230005888">"DIDAYAKAN"</string> + <string name="generic_disabled" msgid="576339310027394867">"DILUMPUHKAN"</string> +</resources> diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml index 1dbe2a5c..c524a9af 100644 --- a/res/values-ms-rMY/strings.xml +++ b/res/values-ms-rMY/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Tindanan skrin dikesan"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Untuk menukar tetapan kebenaran ini, anda perlu mematikan tindanan skrin daripada Tetapan > Apl terlebih dahulu"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Buka tetapan"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Tindakan Pasang/Nyahpasang tidak disokong pada Wear."</string> </resources> diff --git a/res/values-my-rMM-watch/strings.xml b/res/values-my-rMM-watch/strings.xml new file mode 100644 index 00000000..1babba21 --- /dev/null +++ b/res/values-my-rMM-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ငြင်းပယ်သည်၊ ထပ်မမေးပါနှင့်"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"စနစ်အပ်ဖ်များ ပြသရန်"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ပြောင်းလဲ မရနိုင်ပါ"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ဖွင့်ထား"</string> + <string name="generic_disabled" msgid="576339310027394867">"ပိတ်ထား"</string> +</resources> diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml index 401f7280..818d349b 100644 --- a/res/values-my-rMM/strings.xml +++ b/res/values-my-rMM/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"မျက်နှာပြင် ထပ်ပေးမှုကို ရှာတွေ့ခဲ့"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ဒီခွင့်ပြုချက် ဆက်တင်ကို ပြောင်းရန်၊ သင်ဟာ ဦးစွာ ဆက်တင်များ > Appများ ထဲတွင် မျက်နှာပြင် ထပ်ပေးမှုကို ပိတ်လိုက်ရန် လိုမယ်"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ဆက်တင်းများ ဖွင့်ရန်"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android ဆောင်စရာ"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear ပေါ်တွင် ထည့်သွင်းခြင်း/ဖြုတ်ခြင်း လုပ်ဆောင်ချက်များကို မပံ့ပိုးထားပါ။"</string> </resources> diff --git a/res/values-nb-watch/strings.xml b/res/values-nb-watch/strings.xml new file mode 100644 index 00000000..d2c99f3f --- /dev/null +++ b/res/values-nb-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Avvis, ikke spør igjen"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Vis systemapper"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Kan ikke endres"</string> + <string name="generic_enabled" msgid="5221039415230005888">"SLÅTT PÅ"</string> + <string name="generic_disabled" msgid="576339310027394867">"SLÅTT AV"</string> +</resources> diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 7d72c921..8d74eb1a 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Skjermoverlegg oppdaget"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"For å endre denne tillatelsesinnstilingen må du først slå av skjermoverlegget fra Innstillinger > Apper"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Åpne innstillingene"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Handlingene for å installere og avinstallere er ikke støttet på Wear."</string> </resources> diff --git a/res/values-ne-rNP-watch/strings.xml b/res/values-ne-rNP-watch/strings.xml new file mode 100644 index 00000000..89e48dd4 --- /dev/null +++ b/res/values-ne-rNP-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"अस्वीकार गर्नुहोस्, फेरि नसोध्नुहोस्"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"प्रणाली अनुप्रयोगहरू देखाउनुहोस्"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"परिवर्तन गर्न सकिँदैन"</string> + <string name="generic_enabled" msgid="5221039415230005888">"सक्षम गरियो"</string> + <string name="generic_disabled" msgid="576339310027394867">"असक्षम गरियो"</string> +</resources> diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml index 4a3c6708..8e0c4243 100644 --- a/res/values-ne-rNP/strings.xml +++ b/res/values-ne-rNP/strings.xml @@ -28,7 +28,7 @@ <string name="install_confirm_question" msgid="7295206719219043890">"के तपाईँ यो अनुप्रयोग स्थापन गर्न चाहनु हुन्छ? यसले पहुँच प्राप्त गर्ने छ:"</string> <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"के तपाईँ यस अनुप्रयोगलाई जडान गर्न चाहनु हुन्छ? यसको लागि कुनै विशेष पहुँचको आवश्यकता पर्दैन।"</string> <string name="install_confirm_question_update" msgid="4624159567361487964">"के तपाईँसँग अहिले भईरहेको अनुप्रयोगको एक अपडेट लाई स्थापित गर्न चाहानुहुन्छ? तपाईँको अहिलेको डेटा हराउने छैन। अपडेट भएको अनुप्रयोग पहुँच पाउनेछ मा:"</string> - <string name="install_confirm_question_update_system" msgid="1302330093676416336">"के तपाईं यस पूर्व-निर्मित अनुप्रयोगमा अपडेट स्थापित गर्न चाहनु हुन्छ? तपाईंको रहेको डेटा हराउने छैन। अपडेट गरिएको अनुप्रयोगले पहुँच पाउने छ:"</string> + <string name="install_confirm_question_update_system" msgid="1302330093676416336">"के तपाईँ यस पूर्व-निर्मित अनुप्रयोगमा अपडेट स्थापित गर्न चाहनु हुन्छ? तपाईँको रहेको डेटा हराउने छैन। अपडेट गरिएको अनुप्रयोगले पहुँच पाउने छ:"</string> <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"के तपाईँसँग अहिले भइरहेको अनुप्रयोगको एउटा अपडेटलाई स्थापित गर्न चाहनु हुन्छ? तपाईँको अहिलेको डेटा हराउने छैन। यसलाई कुनै विशेष पहुँचको आवश्यकता छैन।"</string> <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"के तपाईँ यस जोडिएको अनुप्रयोगको एउटा अपडेटलाई स्थापित गर्न चाहनुहुन्छ? तपाईँको अहिलेको डेटा हराउने छैन। यसलाई कुनै विशेष पहुँचको आवश्यकता छैन।"</string> <string name="install_failed" msgid="6579998651498970899">"अनुप्रयोग स्थापना भएन।"</string> @@ -67,7 +67,7 @@ <string name="uninstall_update_title" msgid="4146940097553335390">"परिस्कारहरू अस्थापना गर्नुहोस्"</string> <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> निम्न अनुप्रयोगको अंश हो:"</string> <string name="uninstall_application_text" msgid="6691975835951187030">"के तपाईँ यो अनुप्रयोग अस्थापना गर्न चाहनु हुन्छ?"</string> - <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"के तपाईं यो अनुप्रयोग "<b>"सबै"</b>" प्रयोगकर्ताहरूको लागि स्थापना रद्द गर्न चाहनु हुन्छ? अनुप्रयोग र यसको डेटा "<b>"सबै"</b>" प्रयोगकर्ताहरूबाट उपकरणमा हटाइने छ।"</string> + <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"के तपाईँ यो अनुप्रयोग "<b>"सबै"</b>" प्रयोगकर्ताहरूको लागि स्थापना रद्द गर्न चाहनु हुन्छ? अनुप्रयोग र यसको डेटा "<b>"सबै"</b>" प्रयोगकर्ताहरूबाट उपकरणमा हटाइने छ।"</string> <string name="uninstall_application_text_user" msgid="8766882355635485733">"के तपाईँ प्रयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> को लागि यो अनुप्रयोग स्थापना रद्द गर्न चाहनुहुन्छ?"</string> <string name="uninstall_update_text" msgid="2056387942084605027">"के तपाईँ यस अनुप्रयोगलाई मूल संस्करणसँग फेर्न चाहनु हुन्छ?"</string> <string name="uninstalling" msgid="5556217435895938250">"अस्थापना गर्दै..."</string> @@ -86,7 +86,7 @@ <string name="privacyPerms" msgid="1850527049572617">"गोपनीयता"</string> <string name="devicePerms" msgid="6733560207731294504">"उपकरण पहुँच"</string> <string name="no_new_perms" msgid="6657813692169565975">"यस अपडेटलाई नयाँ अनुमति आवश्यक पर्दैन।"</string> - <string name="grant_confirm_question" msgid="4690289297029223742">"के तपाईं निम्न अनुमति प्रदान गर्न चाहनु हुन्छ? यसले पहुँच पाउने छ:"</string> + <string name="grant_confirm_question" msgid="4690289297029223742">"के तपाईँ निम्न अनुमति प्रदान गर्न चाहनु हुन्छ? यसले पहुँच पाउने छ:"</string> <string name="grant_dialog_button_allow" msgid="4616529495342337095">"अनुमति दिनुहोस्"</string> <string name="grant_dialog_button_deny" msgid="2176510645406614340">"अस्वीकार गर्नुहोस्"</string> <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> को <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string> @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"स्क्रिन ओभरले पत्ता लाग्यो"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"यो अनुमति सेटिङ परिवर्तन गर्न, तपाईँले पहिला सेटिङ अनुप्रयोगबाट स्क्रिन ओभरले बन्द गर्नु पर्दछ।"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"सेटिङहरू खोल्नुहोस्"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear मा स्थापना/स्थापना रद्द गर्ने कार्यहरू समर्थित छैनन्।"</string> </resources> diff --git a/res/values-nl-watch/strings.xml b/res/values-nl-watch/strings.xml new file mode 100644 index 00000000..820875e3 --- /dev/null +++ b/res/values-nl-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Weigeren, niet meer vragen"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Systeem-apps weergeven"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Niet aanpasbaar"</string> + <string name="generic_enabled" msgid="5221039415230005888">"INGESCHAKELD"</string> + <string name="generic_disabled" msgid="576339310027394867">"UITGESCHAKELD"</string> +</resources> diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 72fc07dd..a284f7fa 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Schermoverlay gedetecteerd"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Als u deze instelling voor rechten wilt wijzigen, moet u eerst de schermoverlay uitschakelen via \'Instellingen\' > \'Apps\'"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Instellingen openen"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Acties voor installeren/verwijderen niet ondersteund op Wear"</string> </resources> diff --git a/res/values-pa-rIN-watch/strings.xml b/res/values-pa-rIN-watch/strings.xml new file mode 100644 index 00000000..d6cfe6c8 --- /dev/null +++ b/res/values-pa-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ਅਸਵੀਕਾਰ ਕਰੋ, ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"ਸਿਸਟਮ ਐਪਸ ਦਿਖਾਓ"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ਸਮਰਥਿਤ ਕੀਤਾ ਗਿਆ"</string> + <string name="generic_disabled" msgid="576339310027394867">"ਅਸਮਰਥਿਤ ਕੀਤਾ ਗਿਆ"</string> +</resources> diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml index 772258fb..ec19acb5 100644 --- a/res/values-pa-rIN/strings.xml +++ b/res/values-pa-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"ਸਕਰੀਨ ਓਵਰਲੇਅ ਲੱਭ ਗਿਆ"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ਇਸ ਇਜ਼ਾਜਤ ਸੈਟਿੰਗ ਨੂੰ ਬਦਲਣ ਲਈ; ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ ਸੈਟਿੰਗਜ਼ ਅਤੇ ਐਪਸ ਤੋਂ ਸਕ੍ਰੀਨ ਓਵਰਲੇਅ ਬੰਦ ਕਰਨਾ ਪਵੇਗਾ"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ਸੈਟਿੰਗਜ਼ ਖੋਲ੍ਹੋ"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android ਵੀਅਰ"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"ਵੀਅਰ \'ਤੇ ਸਥਾਪਿਤ ਕਰੋ/ਸਥਾਪਨਾ ਰੱਦ ਕਰੋ ਕਾਰਵਾਈਆਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹਨ।"</string> </resources> diff --git a/res/values-pl-watch/strings.xml b/res/values-pl-watch/strings.xml new file mode 100644 index 00000000..d721141c --- /dev/null +++ b/res/values-pl-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Odmów i nie pytaj ponownie"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Pokaż aplikacje systemowe"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nie można zmienić"</string> + <string name="generic_enabled" msgid="5221039415230005888">"WŁĄCZONE"</string> + <string name="generic_disabled" msgid="576339310027394867">"WYŁĄCZONE"</string> +</resources> diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index d6929bd8..51b5bdbd 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Wykryto nakładkę ekranową"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Aby zmodyfikować te uprawnienia, musisz najpierw wyłączyć nakładkę ekranową, klikając Ustawienia > Aplikacje"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Otwórz ustawienia"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear nie obsługuje instalowania ani odinstalowywania."</string> </resources> diff --git a/res/values-pt-rBR-watch/strings.xml b/res/values-pt-rBR-watch/strings.xml new file mode 100644 index 00000000..cb228f9d --- /dev/null +++ b/res/values-pt-rBR-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Negar e não perguntar de novo"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar apps do sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Impossível alterar"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ATIVADA"</string> + <string name="generic_disabled" msgid="576339310027394867">"DESATIVADA"</string> +</resources> diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index 7fd4f79d..0eb08587 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Sobreposição de tela detectada"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Para alterar a configuração dessa permissão, você deve primeiro desativar a sobreposição de tela em \"Config.\" > \"Apps\""</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configurações"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string> </resources> diff --git a/res/values-pt-rPT-watch/strings.xml b/res/values-pt-rPT-watch/strings.xml new file mode 100644 index 00000000..e8d1bda4 --- /dev/null +++ b/res/values-pt-rPT-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Recusar e não perguntar nov."</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicações do sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Não pode ser alterado"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ATIVADO"</string> + <string name="generic_disabled" msgid="576339310027394867">"DESATIVADO"</string> +</resources> diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index f38aac62..5d6931b9 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Sobreposição de ecrã detetada"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Para alterar esta definição de autorização, primeiro tem de desativar a sobreposição do ecrã em Definições > Aplicações"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir definições"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string> </resources> diff --git a/res/values-pt-watch/strings.xml b/res/values-pt-watch/strings.xml new file mode 100644 index 00000000..cb228f9d --- /dev/null +++ b/res/values-pt-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Negar e não perguntar de novo"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar apps do sistema"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Impossível alterar"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ATIVADA"</string> + <string name="generic_disabled" msgid="576339310027394867">"DESATIVADA"</string> +</resources> diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 7fd4f79d..0eb08587 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Sobreposição de tela detectada"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Para alterar a configuração dessa permissão, você deve primeiro desativar a sobreposição de tela em \"Config.\" > \"Apps\""</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configurações"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string> </resources> diff --git a/res/values-ro-watch/strings.xml b/res/values-ro-watch/strings.xml new file mode 100644 index 00000000..5ff2575b --- /dev/null +++ b/res/values-ro-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Respingeți; nu se mai întreabă"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Afișează aplicațiile de sistem"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nu se poate modifica"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ACTIVATĂ"</string> + <string name="generic_disabled" msgid="576339310027394867">"DEZACTIVATĂ"</string> +</resources> diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 2a7800ca..1f963c70 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -110,7 +110,7 @@ <string name="no_apps" msgid="1965493419005012569">"Nicio aplicație"</string> <string name="location_settings" msgid="1774875730854491297">"Setări privind locația"</string> <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> este un furnizor de servicii de localizare pentru acest dispozitiv. Accesul la locație poate fi modificat din setările privind locația."</string> - <string name="system_warning" msgid="7103819124542305179">"Dacă refuzați această permisiune, este posibil ca funcțiile de bază ale dispozitivului să nu mai funcționează corespunzător."</string> + <string name="system_warning" msgid="7103819124542305179">"Dacă refuzați această permisiune, este posibil ca funcțiile de bază ale dispozitivului să nu mai funcționeze corespunzător."</string> <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicată conform politicii"</string> <string name="loading" msgid="7811651799620593731">"Se încarcă..."</string> <string name="all_permissions" msgid="5156669007784613042">"Toate permisiunile"</string> @@ -119,4 +119,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"S-a detectat suprapunerea pe ecran"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Ca să schimbați această setare pentru permisiuni, mai întâi trebuie să dezactivați suprapunerea pe ecran din Setări > Aplicații"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Deschideți setările"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Acțiunile Instalați/Dezinstalați nu sunt acceptate pe Wear."</string> </resources> diff --git a/res/values-round/dimens.xml b/res/values-round/dimens.xml new file mode 100644 index 00000000..bed41ce0 --- /dev/null +++ b/res/values-round/dimens.xml @@ -0,0 +1,26 @@ +<?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> + <!-- Dimensions for the Grant permissions Confirmation Dialog --> + <dimen name="conf_diag_button_container_height">96dp</dimen> + <dimen name="conf_diag_2button_margin_side">32dp</dimen> + <dimen name="conf_diag_2button_margin_top">10dp</dimen> + <!-- On round screens, the message can't be too close to the top or the corners will be + clipped. --> + <dimen name="conf_diag_min_space_above_message">26dp</dimen> + +</resources> diff --git a/res/values-ru-watch/strings.xml b/res/values-ru-watch/strings.xml new file mode 100644 index 00000000..309dc244 --- /dev/null +++ b/res/values-ru-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Запретить и не спрашивать"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Показать системные приложения"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Нельзя изменить"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ВКЛЮЧЕНО"</string> + <string name="generic_disabled" msgid="576339310027394867">"ОТКЛЮЧЕНО"</string> +</resources> diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 21ae1fe6..05450928 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Обнаружены наложения"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Чтобы предоставить или отменить разрешение, сначала отключите наложения. Для этого нажмите \"Настройки > Приложения\"."</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Открыть настройки"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Android Wear не поддерживает установку и удаление."</string> </resources> diff --git a/res/values-si-rLK-watch/strings.xml b/res/values-si-rLK-watch/strings.xml new file mode 100644 index 00000000..b2559567 --- /dev/null +++ b/res/values-si-rLK-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ප්රතික්ෂේප කරන්න, නැවත අසන්න එපා"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"පද්ධති යෙදුම් පෙන්වන්න"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"වෙනස් කළ නොහැකිය"</string> + <string name="generic_enabled" msgid="5221039415230005888">"සබලයි"</string> + <string name="generic_disabled" msgid="576339310027394867">"අබලයි"</string> +</resources> diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml index 1ab14753..d381abcb 100644 --- a/res/values-si-rLK/strings.xml +++ b/res/values-si-rLK/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"තිර උඩැතිරියක් අනාවරණය කරන ලදි"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"මෙම අවසර සැකසීම වෙනස් කිරීම සඳහා, ඔබට මුලින්ම සැකසීම් > යෙදුම් වෙතින් තිර උඩැතිරිය අක්රිය කර යුතුයි"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"සැකසීම් විවෘත කරන්න"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear මත ස්ථාපන/අස්ථාපනය ක්රියා වෙත සහය දක්වන්නේ නැත."</string> </resources> diff --git a/res/values-sk-watch/strings.xml b/res/values-sk-watch/strings.xml new file mode 100644 index 00000000..9b17f9ba --- /dev/null +++ b/res/values-sk-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Zamietnuť a už sa nepýtať"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Zobraziť systémové aplikácie"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nedá sa zmeniť"</string> + <string name="generic_enabled" msgid="5221039415230005888">"POVOLENÉ"</string> + <string name="generic_disabled" msgid="576339310027394867">"ZAKÁZANÉ"</string> +</resources> diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 93f55792..213e4481 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Bolo zistené prekrytie obrazovky"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Ak chcete zmeniť nastavenie tohto povolenia, musíte najprv v časti Nastavenia > Aplikácie vypnúť prekrytie obrazovky"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Otvoriť nastavenia"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Systém Wear nepodporuje akciu inštalácie/odinštalovania"</string> </resources> diff --git a/res/values-sl-watch/strings.xml b/res/values-sl-watch/strings.xml new file mode 100644 index 00000000..cd71f48c --- /dev/null +++ b/res/values-sl-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Zavrni, ne sprašuj več"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Prikaz sistemskih aplikacij"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ni mogoče sprem."</string> + <string name="generic_enabled" msgid="5221039415230005888">"OMOGOČENO"</string> + <string name="generic_disabled" msgid="576339310027394867">"ONEMOGOČENO"</string> +</resources> diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 86219831..362693c6 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Zaznano prekrivanje zaslona"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Če želite spremeniti nastavitev tega dovoljenja, morate najprej izklopiti prekrivanje zaslona v »Nastavitve > Aplikacije«"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Odpri nastavitve"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Dejanja namestitve in odstranitve v sistemu Android Wear niso podprta."</string> </resources> diff --git a/res/values-sq-rAL-watch/strings.xml b/res/values-sq-rAL-watch/strings.xml new file mode 100644 index 00000000..213ce5a4 --- /dev/null +++ b/res/values-sq-rAL-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Refuzoje, mos pyet sërish"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Shfaq aplikacionet e sistemit"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nuk mund të ndryshohet"</string> + <string name="generic_enabled" msgid="5221039415230005888">"AKTIVIZUAR"</string> + <string name="generic_disabled" msgid="576339310027394867">"ÇAKTIVIZUAR"</string> +</resources> diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml index 1e3d9985..319d6e26 100644 --- a/res/values-sq-rAL/strings.xml +++ b/res/values-sq-rAL/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Mbivendosja e ekranit u zbulua"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Për të ndryshuar këtë cilësim të lejes, në fillim duhet të çaktivizosh mbivendosjen e ekranit nga Cilësimet > Aplikacionet"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Hap cilësimet"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Teknologjia \"Android\" që vishet"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Instalo/çinstalo veprimet që nuk mbështeten në teknologjinë që vishet."</string> </resources> diff --git a/res/values-sr-watch/strings.xml b/res/values-sr-watch/strings.xml new file mode 100644 index 00000000..e51b35a4 --- /dev/null +++ b/res/values-sr-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Одбиј и не питај поново"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Прикажи системске апликације"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Не може да се промени"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ОМОГУЋЕНО"</string> + <string name="generic_disabled" msgid="576339310027394867">"ОНЕМОГУЋЕНО"</string> +</resources> diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 0d1af776..67548d0b 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -119,4 +119,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Откривен је елемент који прекрива садржај екрана"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Да бисте променили подешавање ове дозволе, прво треба да искључите елемент који прекрива садржај екрана у одељку Подешавања > Апликације"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Отвори подешавања"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Радње Инсталирај/Деинсталирај нису подржане у Wear-у."</string> </resources> diff --git a/res/values-sv-watch/strings.xml b/res/values-sv-watch/strings.xml new file mode 100644 index 00000000..66465f4d --- /dev/null +++ b/res/values-sv-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Avvisa och fråga inte igen"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Visa systemappar"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Kan inte ändras"</string> + <string name="generic_enabled" msgid="5221039415230005888">"AKTIVERAD"</string> + <string name="generic_disabled" msgid="576339310027394867">"INAKTIVERAD"</string> +</resources> diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 86c19317..faef032f 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -36,18 +36,18 @@ <string name="install_failed_inconsistent_certificates" msgid="1517751954440692054">"Det finns redan ett paket med samma namn och en signatur som är i konflikt."</string> <string name="install_failed_older_sdk" msgid="7947925824732917665">"Paketet fungerar bara med nyare versioner av Android."</string> <string name="install_failed_cpu_abi_incompatible" product="tablet" msgid="7098684468842750800">"Appen är inte kompatibel med din surfplatta."</string> - <string name="install_failed_cpu_abi_incompatible" product="tv" msgid="1309625657882930450">"Appen är inte kompatibel med din tv."</string> + <string name="install_failed_cpu_abi_incompatible" product="tv" msgid="1309625657882930450">"Appen är inte kompatibel med din TV."</string> <string name="install_failed_cpu_abi_incompatible" product="default" msgid="4433316303249711331">"Appen är inte kompatibel med din mobil."</string> <string name="install_failed_file_not_found" msgid="1958430133396322619">"Paketet som angavs togs bort innan installationen var slutförd."</string> <string name="install_failed_verify_failed" msgid="5567372439890440205">"Paketet klarade inte verifieringen och får inte installeras."</string> <string name="install_failed_verify_timeout" msgid="7083090219270140373">"En timeout inträffade när paketet skulle verifieras. Prova att installera paketet senare."</string> <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Det gick inte att installera <xliff:g id="APP_NAME">%1$s</xliff:g> på surfplattan."</string> - <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunde inte installeras på tv:n."</string> + <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunde inte installeras på TV:n."</string> <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Det gick inte att installera <xliff:g id="APP_NAME">%1$s</xliff:g> på mobilen."</string> <string name="launch" msgid="4826921505917605463">"Öppna"</string> <string name="unknown_apps_dlg_title" msgid="2855558586206583032">"Installation blockerad"</string> <string name="unknown_apps_dlg_text" product="tablet" msgid="7504186369474734767">"Av säkerhetsskäl går det inte att installera appar från okända källor på din surfplatta."</string> - <string name="unknown_apps_dlg_text" product="tv" msgid="7195713985140602351">"Tv:n är av säkerhetsskäl inställd på att blockera installationer av appar från okända källor."</string> + <string name="unknown_apps_dlg_text" product="tv" msgid="7195713985140602351">"TV:n är av säkerhetsskäl inställd på att blockera installationer av appar från okända källor."</string> <string name="unknown_apps_dlg_text" product="default" msgid="133213135679009316">"Av säkerhetsskäl går det inte att installera appar från okända källor på din mobil."</string> <string name="unknown_apps_admin_dlg_text" msgid="1189146324736698462">"Administratören tillåter inte installation av appar från okända källor."</string> <string name="ok" msgid="3468756155452870475">"OK"</string> @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Skärmöverlagring har upptäckts"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Innan du kan ändra den här behörighetsinställningen måste du inaktivera skärmöverlagring under Inställningar > Appar"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Öppna inställningarna"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Åtgärder för att installera/avinstallera stöds inte på Wear."</string> </resources> diff --git a/res/values-sw-watch/strings.xml b/res/values-sw-watch/strings.xml new file mode 100644 index 00000000..b4adaca4 --- /dev/null +++ b/res/values-sw-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Kataa, usiulize tena"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Onyesha programu za mfumo"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Haiwezi kubadilishwa"</string> + <string name="generic_enabled" msgid="5221039415230005888">"IMEWASHWA"</string> + <string name="generic_disabled" msgid="576339310027394867">"IMEZIMWA"</string> +</resources> diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index eb9c1474..d6f775e5 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Imetambua tangazo lililowekelewa juu ya skrini"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Ili kubadilisha mpangilio huu wa ruhusa, ni lazima kwanza uzime tangazo lililowekelewa juu ya skrini kwenye Mipangilio na Programu"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Fungua mipangilio"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Vitendo vya Kusakinisha/Kuondoa haviwezi kutumika kwenye Android Wear."</string> </resources> diff --git a/res/values-ta-rIN-watch/strings.xml b/res/values-ta-rIN-watch/strings.xml new file mode 100644 index 00000000..54c61e7c --- /dev/null +++ b/res/values-ta-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"நிராகரி, மீண்டும் கேட்காதே"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"முறைமைப் பயன்பாடுகளைக் காட்டு"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"மாற்ற முடியாது"</string> + <string name="generic_enabled" msgid="5221039415230005888">"இயக்கப்பட்டது"</string> + <string name="generic_disabled" msgid="576339310027394867">"முடக்கப்பட்டது"</string> +</resources> diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml index 6c16c03d..860e671e 100644 --- a/res/values-ta-rIN/strings.xml +++ b/res/values-ta-rIN/strings.xml @@ -90,7 +90,7 @@ <string name="grant_dialog_button_allow" msgid="4616529495342337095">"அனுமதி"</string> <string name="grant_dialog_button_deny" msgid="2176510645406614340">"நிராகரி"</string> <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> - <string name="permission_warning_template" msgid="5209102765005869454">"<xliff:g id="ACTION">%2$s</xliff:g> செயலுக்கு <xliff:g id="APP_NAME">%1$s</xliff:g>-ஐ அனுமதிக்கவா?"</string> + <string name="permission_warning_template" msgid="5209102765005869454">"<xliff:g id="ACTION">%2$s</xliff:g> செயலுக்கு <xliff:g id="APP_NAME">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string> <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"பயன்பாடுகள்"</string> <string name="app_permissions" msgid="3146758905824597178">"பயன்பாட்டு அனுமதிகள்"</string> <string name="never_ask_again" msgid="3798895821072102967">"மீண்டும் கேட்காதே"</string> @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"திரையின் மேலே செயல்படும் பயன்பாடுகள் கண்டறியப்பட்டன"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"இந்த அனுமதியை மாற்ற, அமைப்புகள் > பயன்பாடுகள் என்பதற்குச் சென்று, திரையின் மேலே செயல்படும் பயன்பாடுகளை முதலில் முடக்கவும்"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"அமைப்புகளைத் திற"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear இல் நிறுவுதல்/நிறுவல் நீக்குதலுக்கு ஆதரவில்லை."</string> </resources> diff --git a/res/values-te-rIN-watch/strings.xml b/res/values-te-rIN-watch/strings.xml new file mode 100644 index 00000000..e13ba44e --- /dev/null +++ b/res/values-te-rIN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"నిరాకరిస్తున్నాను,ఇక అడగవద్దు"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"సిస్టమ్ అనువర్తనాలను చూపు"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"మార్చడం సాధ్యపడదు"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ప్రారంభించబడింది"</string> + <string name="generic_disabled" msgid="576339310027394867">"నిలిపివేయబడింది"</string> +</resources> diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml index de29a0be..ddcfcc50 100644 --- a/res/values-te-rIN/strings.xml +++ b/res/values-te-rIN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"స్క్రీన్ అతివ్యాప్తి గుర్తించబడింది"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ఈ అనుమతి సెట్టింగ్ను మార్చడానికి, మీరు ముందుగా సెట్టింగ్లు > అనువర్తనాల నుండి స్క్రీన్ అతివ్యాప్తిని ఆఫ్ చేయాలి"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"సెట్టింగ్లను తెరువు"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android వేర్"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"వేర్లో ఇన్స్టాల్/అన్ఇన్స్టాల్ చర్యలకు మద్దతు లేదు"</string> </resources> diff --git a/res/values-th-watch/strings.xml b/res/values-th-watch/strings.xml new file mode 100644 index 00000000..ba86f12c --- /dev/null +++ b/res/values-th-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ปฏิเสธ ไม่ต้องถามอีก"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"แสดงแอประบบ"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ไม่สามารถเปลี่ยน"</string> + <string name="generic_enabled" msgid="5221039415230005888">"เปิดใช้อยู่"</string> + <string name="generic_disabled" msgid="576339310027394867">"ปิดใช้อยู่"</string> +</resources> diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 7058a652..8ca2486d 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"ตรวจพบการวางซ้อนหน้าจอ"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"ในการเปลี่ยนแปลงการตั้งค่าสิทธิ์นี้ ก่อนอื่น คุณต้องปิดการวางซ้อนหน้าจอที่การตั้งค่า > แอป"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"เปิดการตั้งค่า"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"ไม่สามารถติดตั้ง/ถอนการติดตั้งบน Wear"</string> </resources> diff --git a/res/values-tl-watch/strings.xml b/res/values-tl-watch/strings.xml new file mode 100644 index 00000000..8885a84f --- /dev/null +++ b/res/values-tl-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Tanggihan, huwag nang tatanunging muli"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Ipakita ang mga app ng system"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Hindi mababago"</string> + <string name="generic_enabled" msgid="5221039415230005888">"NAKA-ENABLE"</string> + <string name="generic_disabled" msgid="576339310027394867">"NAKA-DISABLE"</string> +</resources> diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index eb7dbc99..f8eead24 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Natukoy ang overlay ng screen"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Upang baguhin ang setting ng pahintulot na ito, kailangan mo munang i-off ang overlay ng screen mula sa Mga Setting > Mga App"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Buksan ang mga setting"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"I-install/I-uninstall ang mga pagkilos na hindi sinusuportahan sa Wear."</string> </resources> diff --git a/res/values-tr-watch/strings.xml b/res/values-tr-watch/strings.xml new file mode 100644 index 00000000..c7eddced --- /dev/null +++ b/res/values-tr-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Reddet, bir daha sorma"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Sistem uygulamalarını göster"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Değiştirilemez"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ETKİN"</string> + <string name="generic_disabled" msgid="576339310027394867">"DEVRE DIŞI"</string> +</resources> diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 6b5437b8..e41aa52d 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Ekran yer paylaşımı tespit edildi"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Bu izin ayarını değiştirmek için ilk olarak Ayarlar > Uygulamalar\'dan ekran yer paylaşımını kapatmanız gerekir"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Ayarları aç"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Yükleme/Yüklemeyi Kaldırma işlemleri Wear\'da desteklenmiyor."</string> </resources> diff --git a/res/values-uk-watch/strings.xml b/res/values-uk-watch/strings.xml new file mode 100644 index 00000000..aac71cbe --- /dev/null +++ b/res/values-uk-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Відхилити й більше не запитувати"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Показати системні додатки"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Не можна змінити"</string> + <string name="generic_enabled" msgid="5221039415230005888">"УВІМКНЕНО"</string> + <string name="generic_disabled" msgid="576339310027394867">"ВИМКНЕНО"</string> +</resources> diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 1450c9d6..a78d828e 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -120,4 +120,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Виявлено накладання на екрані"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Щоб змінити налаштування цього дозволу, спершу вимкніть накладання на екрані в меню \"Налаштування\" > \"Додатки\""</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Відкрити налаштування"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Функція \"Встановити/видалити\" не підтримується на пристроях Android Wear."</string> </resources> diff --git a/res/values-ur-rPK-watch/strings.xml b/res/values-ur-rPK-watch/strings.xml new file mode 100644 index 00000000..f3746d50 --- /dev/null +++ b/res/values-ur-rPK-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"انکار کریں، دوبارہ مت پوچھیں"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"سسٹم ایپس دکھائیں"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ناقابل تبدیل"</string> + <string name="generic_enabled" msgid="5221039415230005888">"فعال"</string> + <string name="generic_disabled" msgid="576339310027394867">"غیر فعال"</string> +</resources> diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml index 2ed1a3dd..51aa8e26 100644 --- a/res/values-ur-rPK/strings.xml +++ b/res/values-ur-rPK/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"اسکرین اورلے کا پتہ چلا ہے"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"اس اجازت کی ترتیب کو تبدیل کرنے کیلئے آپ کو پہلے ترتیبات > Apps سے سکرین اورلے آف کرنا ہوگا"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"ترتیبات کھولیں"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear پر غیر تعاون یافتہ کاروائیاں انسٹال/ان انسٹال کریں۔"</string> </resources> diff --git a/res/values-uz-rUZ-watch/strings.xml b/res/values-uz-rUZ-watch/strings.xml new file mode 100644 index 00000000..dca320a9 --- /dev/null +++ b/res/values-uz-rUZ-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Rad etilsin va boshqa so‘ralmasin"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Tizim ilovalarini ko‘rsatish"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"O‘zgartirilmaydi"</string> + <string name="generic_enabled" msgid="5221039415230005888">"YONIQ"</string> + <string name="generic_disabled" msgid="576339310027394867">"O‘CHIQ"</string> +</resources> diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml index cebee29a..aba004e2 100644 --- a/res/values-uz-rUZ/strings.xml +++ b/res/values-uz-rUZ/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Ekran ustidan ochiladigan ilova aniqlandi"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Bu ruxsatnoma parametrini o‘zgartirish uchun avval Sozlamalar > Ilovalar bo‘limidan ekran ustidan ochilish funksiyasini o‘chirib qo‘ying"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Sozlamalarni ochish"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear qurilmasi o‘rnatish/o‘chirish amallarini qo‘llab-quvvatlamaydi."</string> </resources> diff --git a/res/values-vi-watch/strings.xml b/res/values-vi-watch/strings.xml new file mode 100644 index 00000000..c342949e --- /dev/null +++ b/res/values-vi-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Từ chối, không hỏi lại"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Hiển thị ứng dụng hệ thống"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ko thể thay đổi"</string> + <string name="generic_enabled" msgid="5221039415230005888">"ĐÃ BẬT"</string> + <string name="generic_disabled" msgid="576339310027394867">"ĐÃ TẮT"</string> +</resources> diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 69bc823b..6ca7e0ce 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Đã phát hiện lớp phủ màn hình"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Để thay đổi cài đặt quyền này, trước tiên bạn phải tắt lớp phủ màn hình từ Cài đặt > Ứng dụng"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Mở cài đặt"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Không hỗ trợ tác vụ Cài đặt/Gỡ cài đặt trên Wear."</string> </resources> diff --git a/res/values-watch/attrs.xml b/res/values-watch/attrs.xml new file mode 100644 index 00000000..e220f4c8 --- /dev/null +++ b/res/values-watch/attrs.xml @@ -0,0 +1,35 @@ +<?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> + <!-- START: Ported from WearableSupport --> + <declare-styleable name="CircledImageView"> + <attr name="android:src" /> + <attr name="circle_color" format="color" /> + <attr name="circle_radius" format="dimension" /> + <attr name="circle_radius_pressed" format="dimension" /> + <attr name="circle_border_width" format="dimension" /> + <attr name="circle_border_color" format="color" /> + <attr name="circle_padding" format="dimension" /> + <attr name="shadow_width" format="dimension" /> + <attr name="image_circle_percentage" format="dimension" /> + <attr name="image_horizontal_offcenter_percentage" format="dimension" /> + <attr name="image_tint" format="color" /> + <attr name="circle_radius_percent" format="fraction" /> + <attr name="circle_radius_pressed_percent" format="fraction" /> + </declare-styleable> + <!-- END: Ported from WearableSupport --> +</resources> diff --git a/res/values-watch/colors.xml b/res/values-watch/colors.xml new file mode 100644 index 00000000..b81d6e3b --- /dev/null +++ b/res/values-watch/colors.xml @@ -0,0 +1,36 @@ +<?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="grant_permissions_app_color">@color/grant_permissions_white_text_alpha_100</color> + <color name="grant_permissions_progress_color">@color/grant_permissions_white_text_alpha_100</color> + <color name="grant_permissions_title_color">@color/grant_permissions_white_text_alpha_70</color> + + <color name="grant_permissions_white_text_alpha_100">@color/off_white</color> + <color name="grant_permissions_white_text_alpha_70">#b2eeeeee</color> + + <color name="permissions_settings_item_color">#FFFFFFFF</color> + + <color name="off_white">#ffeeeeee</color> + + <color name="primary_text_light">#424242</color> + + <!-- Copied from wearable support --> + <color name="circular_button_disabled">#757575</color> + + <!-- Copied from wearable Clockwork Settings --> + <color name="cw_dark_gray">#424242</color> +</resources> diff --git a/res/values-watch/dimens.xml b/res/values-watch/dimens.xml new file mode 100644 index 00000000..96f32148 --- /dev/null +++ b/res/values-watch/dimens.xml @@ -0,0 +1,57 @@ +<?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> + <dimen name="grant_permissions_app_icon_size">20dp</dimen> + <dimen name="grant_permissions_app_icon_margin_top">6dp</dimen> + + <dimen name="grant_permissions_app_breadcrumb_margin_top">6dp</dimen> + <dimen name="grant_permissions_title_margin_top">6dp</dimen> + <dimen name="grant_permissions_message_side_padding">32dp</dimen> + + <dimen name="action_dialog_z">16dp</dimen> + + <!-- Dimensions for the Grant permissions Confirmation Dialog --> + <dimen name="conf_diag_floating_height">16dp</dimen> + <dimen name="conf_diag_button_container_top_margin">6dp</dimen> + <dimen name="conf_diag_button_container_height">72dp</dimen> + <dimen name="conf_diag_2button_margin_side">16dp</dimen> + <dimen name="conf_diag_2button_margin_top">9dp</dimen> + <dimen name="conf_diag_3button_padding_side">32dp</dimen> + <dimen name="conf_diag_3button_padding_bottom">22dp</dimen> + <dimen name="conf_diag_content_padding_top">6dp</dimen> + <!-- On square screens, the message can be at the top of the screen. --> + <dimen name="conf_diag_min_space_above_message">0dp</dimen> + + + <!-- START: Ported values --> + <item name="default_settings_circle_radius_percent" format="fraction" type="dimen">40%</item> + <item name="selected_settings_circle_radius_percent" format="fraction" type="dimen">50%</item> + <dimen name="round_content_padding_left">40dp</dimen> + <dimen name="round_content_padding_right">24dp</dimen> + <dimen name="content_padding_left">12dp</dimen> + <dimen name="settings_wearable_list_view_vertical_padding_round">14dp</dimen> + <dimen name="setting_header_extra_line_height">16dp</dimen> + <dimen name="setting_long_header_text_size">20dp</dimen> + <dimen name="settings_header_base_height">50dp</dimen> + <dimen name="settings_header_top_margin">14dp</dimen> + <dimen name="settings_header_top_margin_circular">18dp</dimen> + <dimen name="settings_header_top_margin_multiline">6dp</dimen> + <dimen name="settings_header_top_margin_circular_multiline">16dp</dimen> + <dimen name="setting_short_header_text_size">24dp</dimen> + <dimen name="settings_text_margin_left">10dp</dimen> + <!-- END: Ported values --> +</resources> diff --git a/res/values-watch/integers.xml b/res/values-watch/integers.xml new file mode 100644 index 00000000..365ac3ab --- /dev/null +++ b/res/values-watch/integers.xml @@ -0,0 +1,22 @@ +<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- START: Ported values --> + <integer name="short_title_length">13</integer> + <integer name="char_limit_per_line">18</integer> + <!-- END: Ported values --> +</resources> diff --git a/res/values-watch/strings.xml b/res/values-watch/strings.xml new file mode 100644 index 00000000..82fe4ae9 --- /dev/null +++ b/res/values-watch/strings.xml @@ -0,0 +1,37 @@ +<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Title for the dialog button to deny a permission grant and never ask the user again. [CHAR LIMIT=29]--> + <string name="grant_dialog_button_deny_dont_ask_again">Deny, don\'t ask again</string> + + <!-- Template for the current permission from the total number of permissions. --> + <string name="current_permission_template"> + <xliff:g id="current_permission_index" example="1">%1$s</xliff:g> / + <xliff:g id="permission_count" example="2">%2$s</xliff:g> + </string> + + <!-- Preference row title for showing system apps. --> + <string name="preference_show_system_apps">Show system apps</string> + + <!-- Summary of a permission switch when it's enforced by policy [CHAR LIMIT=17] --> + <string name="permission_summary_enforced_by_policy">Can\'t be changed</string> + + <!-- Generic text to indicate that a setting is enabled. Should be in all caps. [CHAR LIMIT=40] --> + <string name="generic_enabled">ENABLED</string> + <!-- Generic text to indicate that a setting is disabled. Should be in all caps. [CHAR LIMIT=40] --> + <string name="generic_disabled">DISABLED</string> +</resources> diff --git a/res/values-watch/styles.xml b/res/values-watch/styles.xml new file mode 100644 index 00000000..01ab90eb --- /dev/null +++ b/res/values-watch/styles.xml @@ -0,0 +1,49 @@ +<?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> + <style name="Theme.DialogWhenLarge" parent="@android:style/Theme.DeviceDefault.NoActionBar"/> + + <!-- START: Ported values --> + <style name="TextAppearance.Wearable.Small" parent="android:TextAppearance.Medium"> + <item name="android:textSize">16sp</item> + <item name="android:textColor">@color/primary_text_light</item> + </style> + + <style name="TextView.Small" parent="@android:style/Widget.Holo.Light"> + <item name="android:fontFamily">sans-serif-condensed</item> + <item name="android:textAppearance">@style/TextAppearance.Wearable.Small</item> + </style> + + <style name="TextView.Small.Light"> + <item name="android:fontFamily">sans-serif-condensed-light</item> + <item name="android:textAppearance">@style/TextAppearance.Wearable.Small</item> + </style> + + <style name="TextAppearance.Settings.Label" parent="android:TextAppearance.Medium"> + <item name="android:textSize">14sp</item> + <item name="android:textColor">#FFFFFFFF</item> + </style> + + <style name="TextAppearance.Settings.Label.Large"> + <item name="android:textSize">16sp</item> + </style> + + <style name="TextView.Settings.Label" parent="TextView.Small.Light"> + <item name="android:textAppearance">@style/TextAppearance.Settings.Label</item> + </style> + <!-- END: Ported values --> +</resources> diff --git a/res/values-watch/themes.xml b/res/values-watch/themes.xml new file mode 100644 index 00000000..dea42907 --- /dev/null +++ b/res/values-watch/themes.xml @@ -0,0 +1,64 @@ +<?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> + <style name="Settings" parent="@android:style/Theme.DeviceDefault.NoActionBar"> + <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Permissions</item> + <item name="android:windowBackground">@color/cw_dark_gray</item> + <item name="android:colorBackground">@color/cw_dark_gray</item> + </style> + + <style name="GrantPermissions" parent="Settings"> + <item name="android:windowIsFloating">true</item> + <item name="android:windowElevation">@dimen/action_dialog_z</item> + <item name="android:windowSwipeToDismiss">false</item> + </style> + + <style name="GrantPermissions.BreadcrumbText"> + <item name="android:fontFamily">sans-serif-condensed</item> + <item name="android:textSize">16sp</item> + <item name="android:textColor">@color/grant_permissions_progress_color</item> + </style> + + <style name="GrantPermissions.TitleText"> + <item name="android:fontFamily">sans-serif-condensed-light</item> + <item name="android:textSize">18sp</item> + <item name="android:textColor">@color/grant_permissions_title_color</item> + <item name="android:lineSpacingMultiplier">1.221</item> + </style> + + <!-- Copied from WearableSupport lib --> + <style name="TextAppearance.WearDiag" parent="android:TextAppearance.Medium"> + <item name="android:textColor">#FFFFFF</item> + <item name="android:textSize">16sp</item> + </style> + <style name="TextAppearance.WearDiag.Button"> + <item name="android:textSize">16sp</item> + </style> + <style name="Widget.WearDiag.Button" parent="@android:style/Widget.DeviceDefault.Button"> + <item name="android:fontFamily">sans-serif-condensed-light</item> + <item name="android:gravity">center_vertical|left</item> + <item name="android:textAppearance">@style/TextAppearance.WearDiag.Button</item> + <item name="android:background">@android:color/transparent</item> + <item name="android:minLines">1</item> + <item name="android:maxLines">3</item> + <item name="android:ellipsize">marquee</item> + <item name="android:layout_height">60dp</item> + <item name="android:layout_width">wrap_content</item> + <item name="android:drawablePadding">12dp</item> + </style> +</resources> diff --git a/res/values-zh-rCN-watch/strings.xml b/res/values-zh-rCN-watch/strings.xml new file mode 100644 index 00000000..d6e64c34 --- /dev/null +++ b/res/values-zh-rCN-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"拒绝,不要再询问"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"显示系统应用"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"无法更改"</string> + <string name="generic_enabled" msgid="5221039415230005888">"已启用"</string> + <string name="generic_disabled" msgid="576339310027394867">"已停用"</string> +</resources> diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 4248b05c..d2cb7aa7 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"检测到屏幕叠加层"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"要更改此权限设置,您必须首先在“设置”>“应用”中关闭屏幕叠加层"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"打开设置"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear 不支持安装/卸载操作。"</string> </resources> diff --git a/res/values-zh-rHK-watch/strings.xml b/res/values-zh-rHK-watch/strings.xml new file mode 100644 index 00000000..9c21b2ab --- /dev/null +++ b/res/values-zh-rHK-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"拒絕,不要再詢問"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"顯示系統應用程式"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"不可變更"</string> + <string name="generic_enabled" msgid="5221039415230005888">"已啟用"</string> + <string name="generic_disabled" msgid="576339310027394867">"已停用"</string> +</resources> diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 947ba084..56ea1404 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"已偵測到螢幕重疊功能"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"如要變更此權限設定,請先前往 [設定] > [應用程式],以關閉螢幕重疊功能"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"開啟設定"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear 不支援安裝/解除安裝操作。"</string> </resources> diff --git a/res/values-zh-rTW-watch/strings.xml b/res/values-zh-rTW-watch/strings.xml new file mode 100644 index 00000000..4c9245d1 --- /dev/null +++ b/res/values-zh-rTW-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"拒絕且不要再詢問"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"顯示系統應用程式"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"無法變更"</string> + <string name="generic_enabled" msgid="5221039415230005888">"已啟用"</string> + <string name="generic_disabled" msgid="576339310027394867">"已停用"</string> +</resources> diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 2c9861f4..7c7f732c 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"偵測到畫面重疊圖層"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"如要變更這項權限設定,您必須先依序前往 [設定] > [應用程式],關閉裝置畫面重疊圖層"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"開啟設定"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Wear 不支援安裝及解除安裝操作。"</string> </resources> diff --git a/res/values-zu-watch/strings.xml b/res/values-zu-watch/strings.xml new file mode 100644 index 00000000..82f45df9 --- /dev/null +++ b/res/values-zu-watch/strings.xml @@ -0,0 +1,25 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Yenqaba, ungangibuzi futhi"</string> + <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> + <string name="preference_show_system_apps" msgid="7042886929865431207">"Bonisa izinhlelo zokusebenza zesistimu"</string> + <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Akukwazi ukushintshwa"</string> + <string name="generic_enabled" msgid="5221039415230005888">"KUNIKWE AMANDLA"</string> + <string name="generic_disabled" msgid="576339310027394867">"KUKHUTSHAZIWE"</string> +</resources> diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index f0524bab..acd9b5b2 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -118,4 +118,6 @@ <string name="screen_overlay_title" msgid="3021729846864038529">"Kutholwe imbondela yesikrini"</string> <string name="screen_overlay_message" msgid="2141944461571677331">"Ukuze uguqule lesi silungiselelo semvume, kuzomele uqale uvale imbondela yesikrini kusukela ku-Izilungiselelo > Izinhlelo zokusebenza"</string> <string name="screen_overlay_button" msgid="4344544843349937743">"Vula izilungiselelo"</string> + <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"I-Android Wear"</string> + <string name="wear_not_allowed_dlg_text" msgid="1618381127237173068">"Izenzo zokufaka/ukukhipha azisekelwe ku-Wear."</string> </resources> diff --git a/res/values/strings.xml b/res/values/strings.xml index d79ba63d..0f1a73f2 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -274,4 +274,9 @@ before permissions can be changed. [CHAR LIMIT=NONE] --> <string name="screen_overlay_button">Open settings</string> + <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. --> + <string name="wear_not_allowed_dlg_title">Android Wear</string> + <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. --> + <string name="wear_not_allowed_dlg_text">Instal/Uninstall actions not supported on Wear.</string> + </resources> diff --git a/src/android/support/wearable/view/CircledImageView.java b/src/android/support/wearable/view/CircledImageView.java new file mode 100644 index 00000000..53cb78cf --- /dev/null +++ b/src/android/support/wearable/view/CircledImageView.java @@ -0,0 +1,603 @@ +/* + * 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 android.support.wearable.view; + +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.RadialGradient; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.AttributeSet; +import android.view.View; + +import java.util.Objects; +import com.android.packageinstaller.R; + +import com.android.packageinstaller.R; + +/** + * An image view surrounded by a circle. + */ +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +public class CircledImageView extends View { + + private static final ArgbEvaluator ARGB_EVALUATOR = new ArgbEvaluator(); + + private Drawable mDrawable; + + private final RectF mOval; + private final Paint mPaint; + + private ColorStateList mCircleColor; + + private float mCircleRadius; + private float mCircleRadiusPercent; + + private float mCircleRadiusPressed; + private float mCircleRadiusPressedPercent; + + private float mRadiusInset; + + private int mCircleBorderColor; + + private float mCircleBorderWidth; + private float mProgress = 1f; + private final float mShadowWidth; + + private float mShadowVisibility; + private boolean mCircleHidden = false; + + private float mInitialCircleRadius; + + private boolean mPressed = false; + + private boolean mProgressIndeterminate; + private ProgressDrawable mIndeterminateDrawable; + private Rect mIndeterminateBounds = new Rect(); + private long mColorChangeAnimationDurationMs = 0; + + private float mImageCirclePercentage = 1f; + private float mImageHorizontalOffcenterPercentage = 0f; + private Integer mImageTint; + + private final Drawable.Callback mDrawableCallback = new Drawable.Callback() { + @Override + public void invalidateDrawable(Drawable drawable) { + invalidate(); + } + + @Override + public void scheduleDrawable(Drawable drawable, Runnable runnable, long l) { + // Not needed. + } + + @Override + public void unscheduleDrawable(Drawable drawable, Runnable runnable) { + // Not needed. + } + }; + + private int mCurrentColor; + + private final AnimatorUpdateListener mAnimationListener = new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + int color = (int) animation.getAnimatedValue(); + if (color != CircledImageView.this.mCurrentColor) { + CircledImageView.this.mCurrentColor = color; + CircledImageView.this.invalidate(); + } + } + }; + + private ValueAnimator mColorAnimator; + + public CircledImageView(Context context) { + this(context, null); + } + + public CircledImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircledImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CircledImageView); + mDrawable = a.getDrawable(R.styleable.CircledImageView_android_src); + + mCircleColor = a.getColorStateList(R.styleable.CircledImageView_circle_color); + if (mCircleColor == null) { + mCircleColor = ColorStateList.valueOf(android.R.color.darker_gray); + } + + mCircleRadius = a.getDimension( + R.styleable.CircledImageView_circle_radius, 0); + mInitialCircleRadius = mCircleRadius; + mCircleRadiusPressed = a.getDimension( + R.styleable.CircledImageView_circle_radius_pressed, mCircleRadius); + mCircleBorderColor = a.getColor( + R.styleable.CircledImageView_circle_border_color, Color.BLACK); + mCircleBorderWidth = a.getDimension(R.styleable.CircledImageView_circle_border_width, 0); + + if (mCircleBorderWidth > 0) { + mRadiusInset += mCircleBorderWidth; + } + + float circlePadding = a.getDimension(R.styleable.CircledImageView_circle_padding, 0); + if (circlePadding > 0) { + mRadiusInset += circlePadding; + } + mShadowWidth = a.getDimension(R.styleable.CircledImageView_shadow_width, 0); + + mImageCirclePercentage = a.getFloat( + R.styleable.CircledImageView_image_circle_percentage, 0f); + + mImageHorizontalOffcenterPercentage = a.getFloat( + R.styleable.CircledImageView_image_horizontal_offcenter_percentage, 0f); + + if (a.hasValue(R.styleable.CircledImageView_image_tint)) { + mImageTint = a.getColor(R.styleable.CircledImageView_image_tint, 0); + } + + mCircleRadiusPercent = a.getFraction(R.styleable.CircledImageView_circle_radius_percent, + 1, 1, 0f); + + mCircleRadiusPressedPercent = a.getFraction( + R.styleable.CircledImageView_circle_radius_pressed_percent, 1, 1, + mCircleRadiusPercent); + + a.recycle(); + + mOval = new RectF(); + mPaint = new Paint(); + mPaint.setAntiAlias(true); + + mIndeterminateDrawable = new ProgressDrawable(); + // {@link #mDrawableCallback} must be retained as a member, as Drawable callback + // is held by weak reference, we must retain it for it to continue to be called. + mIndeterminateDrawable.setCallback(mDrawableCallback); + + setWillNotDraw(false); + + setColorForCurrentState(); + } + + public void setCircleHidden(boolean circleHidden) { + if (circleHidden != mCircleHidden) { + mCircleHidden = circleHidden; + invalidate(); + } + } + + + @Override + protected boolean onSetAlpha(int alpha) { + return true; + } + + @Override + protected void onDraw(Canvas canvas) { + int paddingLeft = getPaddingLeft(); + int paddingTop = getPaddingTop(); + + + float circleRadius = mPressed ? getCircleRadiusPressed() : getCircleRadius(); + if (mShadowWidth > 0 && mShadowVisibility > 0) { + // First let's find the center of the view. + mOval.set(paddingLeft, paddingTop, getWidth() - getPaddingRight(), + getHeight() - getPaddingBottom()); + // Having the center, lets make the shadow start beyond the circled and possibly the + // border. + final float radius = circleRadius + mCircleBorderWidth + + mShadowWidth * mShadowVisibility; + mPaint.setColor(Color.BLACK); + mPaint.setAlpha(Math.round(mPaint.getAlpha() * getAlpha())); + mPaint.setStyle(Style.FILL); + // TODO: precalc and pre-allocate this + mPaint.setShader(new RadialGradient(mOval.centerX(), mOval.centerY(), radius, + new int[]{Color.BLACK, Color.TRANSPARENT}, new float[]{0.6f, 1f}, + Shader.TileMode.MIRROR)); + canvas.drawCircle(mOval.centerX(), mOval.centerY(), radius, mPaint); + mPaint.setShader(null); + } + if (mCircleBorderWidth > 0) { + // First let's find the center of the view. + mOval.set(paddingLeft, paddingTop, getWidth() - getPaddingRight(), + getHeight() - getPaddingBottom()); + // Having the center, lets make the border meet the circle. + mOval.set(mOval.centerX() - circleRadius, mOval.centerY() - circleRadius, + mOval.centerX() + circleRadius, mOval.centerY() + circleRadius); + mPaint.setColor(mCircleBorderColor); + // {@link #Paint.setAlpha} is a helper method that just sets the alpha portion of the + // color. {@link #Paint.setPaint} will clear any previously set alpha value. + mPaint.setAlpha(Math.round(mPaint.getAlpha() * getAlpha())); + mPaint.setStyle(Style.STROKE); + mPaint.setStrokeWidth(mCircleBorderWidth); + + if (mProgressIndeterminate) { + mOval.roundOut(mIndeterminateBounds); + mIndeterminateDrawable.setBounds(mIndeterminateBounds); + mIndeterminateDrawable.setRingColor(mCircleBorderColor); + mIndeterminateDrawable.setRingWidth(mCircleBorderWidth); + mIndeterminateDrawable.draw(canvas); + } else { + canvas.drawArc(mOval, -90, 360 * mProgress, false, mPaint); + } + } + if (!mCircleHidden) { + mOval.set(paddingLeft, paddingTop, getWidth() - getPaddingRight(), + getHeight() - getPaddingBottom()); + // {@link #Paint.setAlpha} is a helper method that just sets the alpha portion of the + // color. {@link #Paint.setPaint} will clear any previously set alpha value. + mPaint.setColor(mCurrentColor); + mPaint.setAlpha(Math.round(mPaint.getAlpha() * getAlpha())); + + mPaint.setStyle(Style.FILL); + float centerX = mOval.centerX(); + float centerY = mOval.centerY(); + + canvas.drawCircle(centerX, centerY, circleRadius, mPaint); + } + + if (mDrawable != null) { + mDrawable.setAlpha(Math.round(getAlpha() * 255)); + + if (mImageTint != null) { + mDrawable.setTint(mImageTint); + } + mDrawable.draw(canvas); + } + + super.onDraw(canvas); + } + + private void setColorForCurrentState() { + int newColor = mCircleColor.getColorForState(getDrawableState(), + mCircleColor.getDefaultColor()); + if (mColorChangeAnimationDurationMs > 0) { + if (mColorAnimator != null) { + mColorAnimator.cancel(); + } else { + mColorAnimator = new ValueAnimator(); + } + mColorAnimator.setIntValues(new int[] { + mCurrentColor, newColor }); + mColorAnimator.setEvaluator(ARGB_EVALUATOR); + mColorAnimator.setDuration(mColorChangeAnimationDurationMs); + mColorAnimator.addUpdateListener(this.mAnimationListener); + mColorAnimator.start(); + } else { + if (newColor != mCurrentColor) { + mCurrentColor = newColor; + invalidate(); + } + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + final float radius = getCircleRadius() + mCircleBorderWidth + + mShadowWidth * mShadowVisibility; + float desiredWidth = radius * 2; + float desiredHeight = radius * 2; + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + int width; + int height; + + if (widthMode == MeasureSpec.EXACTLY) { + width = widthSize; + } else if (widthMode == MeasureSpec.AT_MOST) { + width = (int) Math.min(desiredWidth, widthSize); + } else { + width = (int) desiredWidth; + } + + if (heightMode == MeasureSpec.EXACTLY) { + height = heightSize; + } else if (heightMode == MeasureSpec.AT_MOST) { + height = (int) Math.min(desiredHeight, heightSize); + } else { + height = (int) desiredHeight; + } + + super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mDrawable != null) { + // Retrieve the sizes of the drawable and the view. + final int nativeDrawableWidth = mDrawable.getIntrinsicWidth(); + final int nativeDrawableHeight = mDrawable.getIntrinsicHeight(); + final int viewWidth = getMeasuredWidth(); + final int viewHeight = getMeasuredHeight(); + final float imageCirclePercentage = mImageCirclePercentage > 0 + ? mImageCirclePercentage : 1; + + final float scaleFactor = Math.min(1f, + Math.min( + (float) nativeDrawableWidth != 0 + ? imageCirclePercentage * viewWidth / nativeDrawableWidth : 1, + (float) nativeDrawableHeight != 0 + ? imageCirclePercentage + * viewHeight / nativeDrawableHeight : 1)); + + // Scale the drawable down to fit the view, if needed. + final int drawableWidth = Math.round(scaleFactor * nativeDrawableWidth); + final int drawableHeight = Math.round(scaleFactor * nativeDrawableHeight); + + // Center the drawable within the view. + final int drawableLeft = (viewWidth - drawableWidth) / 2 + + Math.round(mImageHorizontalOffcenterPercentage * drawableWidth); + final int drawableTop = (viewHeight - drawableHeight) / 2; + + mDrawable.setBounds(drawableLeft, drawableTop, drawableLeft + drawableWidth, + drawableTop + drawableHeight); + } + + super.onLayout(changed, left, top, right, bottom); + } + + public void setImageDrawable(Drawable drawable) { + if (drawable != mDrawable) { + final Drawable existingDrawable = mDrawable; + mDrawable = drawable; + + final boolean skipLayout = drawable != null + && existingDrawable != null + && existingDrawable.getIntrinsicHeight() == drawable.getIntrinsicHeight() + && existingDrawable.getIntrinsicWidth() == drawable.getIntrinsicWidth(); + + if (skipLayout) { + mDrawable.setBounds(existingDrawable.getBounds()); + } else { + requestLayout(); + } + + invalidate(); + } + } + + public void setImageResource(int resId) { + setImageDrawable(resId == 0 ? null : getContext().getDrawable(resId)); + } + + public void setImageCirclePercentage(float percentage) { + float clamped = Math.max(0, Math.min(1, percentage)); + if (clamped != mImageCirclePercentage) { + mImageCirclePercentage = clamped; + invalidate(); + } + } + + public void setImageHorizontalOffcenterPercentage(float percentage) { + if (percentage != mImageHorizontalOffcenterPercentage) { + mImageHorizontalOffcenterPercentage = percentage; + invalidate(); + } + } + + public void setImageTint(int tint) { + if (tint != mImageTint) { + mImageTint = tint; + invalidate(); + } + } + + public float getCircleRadius() { + float radius = mCircleRadius; + if (mCircleRadius <= 0 && mCircleRadiusPercent > 0) { + radius = Math.max(getMeasuredHeight(), getMeasuredWidth()) * mCircleRadiusPercent; + } + + return radius - mRadiusInset; + } + + public float getCircleRadiusPercent() { + return mCircleRadiusPercent; + } + + public float getCircleRadiusPressed() { + float radius = mCircleRadiusPressed; + + if (mCircleRadiusPressed <= 0 && mCircleRadiusPressedPercent > 0) { + radius = Math.max(getMeasuredHeight(), getMeasuredWidth()) + * mCircleRadiusPressedPercent; + } + + return radius - mRadiusInset; + } + + public float getCircleRadiusPressedPercent() { + return mCircleRadiusPressedPercent; + } + + public void setCircleRadius(float circleRadius) { + if (circleRadius != mCircleRadius) { + mCircleRadius = circleRadius; + invalidate(); + } + } + + /** + * Sets the radius of the circle to be a percentage of the largest dimension of the view. + * @param circleRadiusPercent A {@code float} from 0 to 1 representing the radius percentage. + */ + public void setCircleRadiusPercent(float circleRadiusPercent) { + if (circleRadiusPercent != mCircleRadiusPercent) { + mCircleRadiusPercent = circleRadiusPercent; + invalidate(); + } + } + + public void setCircleRadiusPressed(float circleRadiusPressed) { + if (circleRadiusPressed != mCircleRadiusPressed) { + mCircleRadiusPressed = circleRadiusPressed; + invalidate(); + } + } + + /** + * Sets the radius of the circle to be a percentage of the largest dimension of the view when + * pressed. + * @param circleRadiusPressedPercent A {@code float} from 0 to 1 representing the radius + * percentage. + */ + public void setCircleRadiusPressedPercent(float circleRadiusPressedPercent) { + if (circleRadiusPressedPercent != mCircleRadiusPressedPercent) { + mCircleRadiusPressedPercent = circleRadiusPressedPercent; + invalidate(); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + setColorForCurrentState(); + } + + public void setCircleColor(int circleColor) { + setCircleColorStateList(ColorStateList.valueOf(circleColor)); + } + + public void setCircleColorStateList(ColorStateList circleColor) { + if (!Objects.equals(circleColor, mCircleColor)) { + mCircleColor = circleColor; + setColorForCurrentState(); + invalidate(); + } + } + + public ColorStateList getCircleColorStateList() { + return mCircleColor; + } + + public int getDefaultCircleColor() { + return mCircleColor.getDefaultColor(); + } + + /** + * Show the circle border as an indeterminate progress spinner. + * The views circle border width and color must be set for this to have an effect. + * + * @param show true if the progress spinner is shown, false to hide it. + */ + public void showIndeterminateProgress(boolean show) { + mProgressIndeterminate = show; + if (show) { + mIndeterminateDrawable.startAnimation(); + } else { + mIndeterminateDrawable.stopAnimation(); + } + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (visibility != View.VISIBLE) { + showIndeterminateProgress(false); + } else if (mProgressIndeterminate) { + showIndeterminateProgress(true); + } + } + + public void setProgress(float progress) { + if (progress != mProgress) { + mProgress = progress; + invalidate(); + } + } + + /** + * Set how much of the shadow should be shown. + * @param shadowVisibility Value between 0 and 1. + */ + public void setShadowVisibility(float shadowVisibility) { + if (shadowVisibility != mShadowVisibility) { + mShadowVisibility = shadowVisibility; + invalidate(); + } + } + + public float getInitialCircleRadius() { + return mInitialCircleRadius; + } + + public void setCircleBorderColor(int circleBorderColor) { + mCircleBorderColor = circleBorderColor; + } + + /** + * Set the border around the circle. + * @param circleBorderWidth Width of the border around the circle. + */ + public void setCircleBorderWidth(float circleBorderWidth) { + if (circleBorderWidth != mCircleBorderWidth) { + mCircleBorderWidth = circleBorderWidth; + invalidate(); + } + } + + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + if (pressed != mPressed) { + mPressed = pressed; + invalidate(); + } + } + + public Drawable getImageDrawable() { + return mDrawable; + } + + /** + * @return the milliseconds duration of the transition animation when the color changes. + */ + public long getColorChangeAnimationDuration() { + return mColorChangeAnimationDurationMs; + } + + /** + * @param mColorChangeAnimationDurationMs the milliseconds duration of the color change + * animation. The color change animation will run if the color changes with {@link #setCircleColor} + * or as a result of the active state changing. + */ + public void setColorChangeAnimationDuration(long mColorChangeAnimationDurationMs) { + this.mColorChangeAnimationDurationMs = mColorChangeAnimationDurationMs; + } +} diff --git a/src/android/support/wearable/view/Gusterpolator.java b/src/android/support/wearable/view/Gusterpolator.java new file mode 100644 index 00000000..dc85bcb5 --- /dev/null +++ b/src/android/support/wearable/view/Gusterpolator.java @@ -0,0 +1,84 @@ +/* + * 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 android.support.wearable.view; + +import android.animation.TimeInterpolator; +import android.annotation.TargetApi; +import android.os.Build; + +/** + * Interpolator that uses a Bezier derived S shaped curve. + * @hide + */ +@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) +class Gusterpolator implements TimeInterpolator { + + /** An instance of {@link android.support.wearable.view.Gusterpolator}. */ + public static final Gusterpolator INSTANCE = new Gusterpolator(); + + /** + * To avoid users of this class creating multiple copies needlessly, the constructor is + * private. + */ + private Gusterpolator() {} + + /** + * Lookup table values. + * Generated using a Bezier curve from (0,0) to (1,1) with control points: + * P0 (0,0) + * P1 (0.4, 0) + * P2 (0.2, 1.0) + * P3 (1.0, 1.0) + * + * Values sampled with x at regular intervals between 0 and 1. + */ + private static final float[] VALUES = new float[] { + 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f, + 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f, + 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f, + 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f, + 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f, + 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f, + 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f, + 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f, + 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f, + 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f + }; + + private static final float STEP_SIZE = 1.0f / (VALUES.length - 1); + + @Override + public float getInterpolation(float input) { + if (input >= 1.0f) { + return 1.0f; + } + + if (input <= 0f) { + return 0f; + } + + int position = Math.min( + (int)(input * (VALUES.length - 1)), + VALUES.length - 2); + + float quantized = position * STEP_SIZE; + float difference = input - quantized; + float weight = difference / STEP_SIZE; + + return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]); + } +} diff --git a/src/android/support/wearable/view/ProgressDrawable.java b/src/android/support/wearable/view/ProgressDrawable.java new file mode 100644 index 00000000..63e6a039 --- /dev/null +++ b/src/android/support/wearable/view/ProgressDrawable.java @@ -0,0 +1,176 @@ +/* + * 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 android.support.wearable.view; + +import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.annotation.TargetApi; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.Property; +import android.view.animation.LinearInterpolator; + +/** + * Drawable for showing an indeterminate progress indicator. + * + * TODO: When Material progress drawable is available in the support library stop using this. + * + * @hide + */ +@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) +class ProgressDrawable extends Drawable { + + private static Property<ProgressDrawable, Integer> LEVEL = + new Property<ProgressDrawable, Integer>(Integer.class, "level") { + @Override + public Integer get(ProgressDrawable drawable) { + return drawable.getLevel(); + } + + @Override + public void set(ProgressDrawable drawable, Integer value) { + drawable.setLevel(value); + drawable.invalidateSelf(); + } + }; + /** Max level for a level drawable, as specified in developer docs for {@link Drawable}. */ + private static final int MAX_LEVEL = 10000; + + /** How many different sections are there, five gives us the material style star. **/ + private static final int NUMBER_OF_SEGMENTS = 5; + + private static final int LEVELS_PER_SEGMENT = MAX_LEVEL / NUMBER_OF_SEGMENTS; + private static final float STARTING_ANGLE = -90f; + private static final long ANIMATION_DURATION = 6000; + private static final int FULL_CIRCLE = 360; + private static final int MAX_SWEEP = 306; + private static final int CORRECTION_ANGLE = FULL_CIRCLE - MAX_SWEEP; + /** How far through each cycle does the bar stop growing and start shrinking, half way. **/ + private static final float GROW_SHRINK_RATIO = 0.5f; + // TODO: replace this with BakedBezierInterpolator when its available in support library. + private static final TimeInterpolator mInterpolator = Gusterpolator.INSTANCE; + + private final RectF mInnerCircleBounds = new RectF(); + private final Paint mPaint = new Paint(); + private final ObjectAnimator mAnimator; + private float mCircleBorderWidth; + private int mCircleBorderColor; + + public ProgressDrawable() { + mPaint.setAntiAlias(true); + mPaint.setStyle(Paint.Style.STROKE); + mAnimator = ObjectAnimator.ofInt(this, LEVEL, 0, MAX_LEVEL); + mAnimator.setRepeatCount(ValueAnimator.INFINITE); + mAnimator.setRepeatMode(ValueAnimator.RESTART); + mAnimator.setDuration(ANIMATION_DURATION); + mAnimator.setInterpolator(new LinearInterpolator()); + } + + public void setRingColor(int color) { + mCircleBorderColor = color; + } + + public void setRingWidth(float width) { + mCircleBorderWidth = width; + } + + public void startAnimation() { + mAnimator.start(); + } + + public void stopAnimation() { + mAnimator.cancel(); + } + + @Override + public void draw(Canvas canvas) { + canvas.save(); + mInnerCircleBounds.set(getBounds()); + mInnerCircleBounds.inset(mCircleBorderWidth / 2.0f, mCircleBorderWidth / 2.0f); + mPaint.setStrokeWidth(mCircleBorderWidth); + mPaint.setColor(mCircleBorderColor); + + float sweepAngle = FULL_CIRCLE; + boolean growing = false; + float correctionAngle = 0; + int level = getLevel(); + + int currentSegment = level / LEVELS_PER_SEGMENT; + int offset = currentSegment * LEVELS_PER_SEGMENT; + float progress = (level - offset) / (float) LEVELS_PER_SEGMENT; + + growing = progress < GROW_SHRINK_RATIO; + correctionAngle = CORRECTION_ANGLE * progress; + + if (growing) { + sweepAngle = MAX_SWEEP * mInterpolator.getInterpolation( + lerpInv(0f, GROW_SHRINK_RATIO, progress)); + } else { + sweepAngle = MAX_SWEEP * (1.0f - mInterpolator.getInterpolation( + lerpInv(GROW_SHRINK_RATIO, 1.0f, progress))); + } + + sweepAngle = Math.max(1, sweepAngle); + + canvas.rotate( + level * (1.0f / MAX_LEVEL) * 2 * FULL_CIRCLE + STARTING_ANGLE + correctionAngle, + mInnerCircleBounds.centerX(), + mInnerCircleBounds.centerY()); + canvas.drawArc(mInnerCircleBounds, + growing ? 0 : MAX_SWEEP - sweepAngle, + sweepAngle, + false, + mPaint); + canvas.restore(); + } + + @Override + public void setAlpha(int i) { + // Not supported. + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + // Not supported. + } + + @Override + public int getOpacity() { + return PixelFormat.OPAQUE; + } + + @Override + protected boolean onLevelChange(int level) { + return true; // Changing the level of this drawable does change its appearance. + } + + /** + * Returns the interpolation scalar (s) that satisfies the equation: + * {@code value = }lerp(a, b, s) + * + * <p>If {@code a == b}, then this function will return 0. + */ + private static float lerpInv(float a, float b, float value) { + return a != b ? ((value - a) / (b - a)) : 0.0f; + } +} diff --git a/src/android/support/wearable/view/SimpleAnimatorListener.java b/src/android/support/wearable/view/SimpleAnimatorListener.java new file mode 100644 index 00000000..13631a2a --- /dev/null +++ b/src/android/support/wearable/view/SimpleAnimatorListener.java @@ -0,0 +1,67 @@ +/* + * 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 android.support.wearable.view; + +import android.animation.Animator; +import android.annotation.TargetApi; +import android.os.Build; + +/** + * Convenience class for listening for Animator events that implements the AnimatorListener + * interface and allows extending only methods that are necessary. + */ +@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) +public class SimpleAnimatorListener implements Animator.AnimatorListener { + + private boolean mWasCanceled; + + @Override + public void onAnimationCancel(Animator animator) { + mWasCanceled = true; + } + + @Override + public void onAnimationEnd(Animator animator) { + if (!mWasCanceled) { + onAnimationComplete(animator); + } + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + + @Override + public void onAnimationStart(Animator animator) { + mWasCanceled = false; + } + + /** + * Called when the animation finishes. Not called if the animation was canceled. + */ + public void onAnimationComplete(Animator animator) { + } + + /** + * Provides information if the animation was cancelled. + * @return True if animation was cancelled. + */ + public boolean wasCanceled() { + return mWasCanceled; + } + +} diff --git a/src/android/support/wearable/view/WearableListView.java b/src/android/support/wearable/view/WearableListView.java new file mode 100644 index 00000000..01baa98b --- /dev/null +++ b/src/android/support/wearable/view/WearableListView.java @@ -0,0 +1,1387 @@ +/* + * 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 android.support.wearable.view; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.PointF; +import android.os.Build; +import android.os.Handler; +import android.support.v7.widget.LinearSmoothScroller; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.Property; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.Scroller; + +import java.util.ArrayList; +import java.util.List; + +/** + * An alternative version of ListView that is optimized for ease of use on small screen wearable + * devices. It displays a vertically scrollable list of items, and automatically snaps to the + * nearest item when the user stops scrolling. + * + * <p> + * For a quick start, you will need to implement a subclass of {@link .Adapter}, + * which will create and bind your views to the {@link .ViewHolder} objects. If you want to add + * more visual treatment to your views when they become the central items of the + * WearableListView, have them implement the {@link .OnCenterProximityListener} interface. + * </p> + */ +@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) +public class WearableListView extends RecyclerView { + @SuppressWarnings("unused") + private static final String TAG = "WearableListView"; + + private static final long FLIP_ANIMATION_DURATION_MS = 150; + private static final long CENTERING_ANIMATION_DURATION_MS = 150; + + private static final float TOP_TAP_REGION_PERCENTAGE = .33f; + private static final float BOTTOM_TAP_REGION_PERCENTAGE = .33f; + + // Each item will occupy one third of the height. + private static final int THIRD = 3; + + private final int mMinFlingVelocity; + private final int mMaxFlingVelocity; + + private boolean mMaximizeSingleItem; + private boolean mCanClick = true; + // WristGesture navigation signals are delivered as KeyEvents. Allow developer to disable them + // for this specific View. It might be cleaner to simply have users re-implement onKeyDown(). + // TOOD: Finalize the disabling mechanism here. + private boolean mGestureNavigationEnabled = true; + private int mTapPositionX; + private int mTapPositionY; + private ClickListener mClickListener; + + private Animator mScrollAnimator; + // This is a little hacky due to the fact that animator provides incremental values instead of + // deltas and scrolling code requires deltas. We animate WearableListView directly and use this + // field to calculate deltas. Obviously this means that only one scrolling algorithm can run at + // a time, but I don't think it would be wise to have more than one running. + private int mLastScrollChange; + + private SetScrollVerticallyProperty mSetScrollVerticallyProperty = + new SetScrollVerticallyProperty(); + + private final List<OnScrollListener> mOnScrollListeners = new ArrayList<OnScrollListener>(); + + private final List<OnCentralPositionChangedListener> mOnCentralPositionChangedListeners = + new ArrayList<OnCentralPositionChangedListener>(); + + private OnOverScrollListener mOverScrollListener; + + private boolean mGreedyTouchMode; + + private float mStartX; + + private float mStartY; + + private float mStartFirstTop; + + private final int mTouchSlop; + + private boolean mPossibleVerticalSwipe; + + private int mInitialOffset = 0; + + private Scroller mScroller; + + // Top and bottom boundaries for tap checking. Need to recompute by calling computeTapRegions + // before referencing. + private final float[] mTapRegions = new float[2]; + + private boolean mGestureDirectionLocked; + private int mPreviousCentral = 0; + + // Temp variable for storing locations on screen. + private final int[] mLocation = new int[2]; + + // TODO: Consider clearing this when underlying data set changes. If the data set changes, you + // can't safely assume that this pressed view is in the same place as it was before and it will + // receive setPressed(false) unnecessarily. In theory it should be fine, but in practice we + // have places like this: mIconView.setCircleColor(pressed ? mPressedColor : mSelectedColor); + // This might set selected color on non selected item. Our logic should be: if you change + // underlying data set, all best are off and you need to preserve the state; we will clear + // this field. However, I am not willing to introduce this so late in C development. + private View mPressedView = null; + + private final Runnable mPressedRunnable = new Runnable() { + @Override + public void run() { + if (getChildCount() > 0) { + mPressedView = getChildAt(findCenterViewIndex()); + mPressedView.setPressed(true); + } else { + Log.w(TAG, "mPressedRunnable: the children were removed, skipping."); + } + } + }; + + private final Runnable mReleasedRunnable = new Runnable() { + @Override + public void run() { + releasePressedItem(); + } + }; + + private Runnable mNotifyChildrenPostLayoutRunnable = new Runnable() { + @Override + public void run() { + notifyChildrenAboutProximity(false); + } + }; + + private final AdapterDataObserver mObserver = new AdapterDataObserver() { + @Override + public void onChanged() { + WearableListView.this.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) { + WearableListView.this.removeOnLayoutChangeListener(this); + if (WearableListView.this.getChildCount() > 0) { + WearableListView.this.animateToCenter(); + } + } + }); + } + }; + + public WearableListView(Context context) { + this(context, null); + } + + public WearableListView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public WearableListView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setHasFixedSize(true); + setOverScrollMode(View.OVER_SCROLL_NEVER); + setLayoutManager(new LayoutManager()); + + final RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_IDLE && getChildCount() > 0) { + handleTouchUp(null, newState); + } + for (OnScrollListener listener : mOnScrollListeners) { + listener.onScrollStateChanged(newState); + } + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + onScroll(dy); + } + }; + setOnScrollListener(onScrollListener); + + final ViewConfiguration vc = ViewConfiguration.get(context); + mTouchSlop = vc.getScaledTouchSlop(); + + mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); + mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); + } + + @Override + public void setAdapter(RecyclerView.Adapter adapter) { + RecyclerView.Adapter currentAdapter = getAdapter(); + if (currentAdapter != null) { + currentAdapter.unregisterAdapterDataObserver(mObserver); + } + + super.setAdapter(adapter); + + if (adapter != null) { + adapter.registerAdapterDataObserver(mObserver); + } + } + + /** + * @return the position of the center child's baseline; -1 if no center child exists or if + * the center child does not return a valid baseline. + */ + @Override + public int getBaseline() { + // No children implies there is no center child for which a baseline can be computed. + if (getChildCount() == 0) { + return super.getBaseline(); + } + + // Compute the baseline of the center child. + final int centerChildIndex = findCenterViewIndex(); + final int centerChildBaseline = getChildAt(centerChildIndex).getBaseline(); + + // If the center child has no baseline, neither does this list view. + if (centerChildBaseline == -1) { + return super.getBaseline(); + } + + return getCentralViewTop() + centerChildBaseline; + } + + /** + * @return true if the list is scrolled all the way to the top. + */ + public boolean isAtTop() { + if (getChildCount() == 0) { + return true; + } + + int centerChildIndex = findCenterViewIndex(); + View centerView = getChildAt(centerChildIndex); + return getChildAdapterPosition(centerView) == 0 && + getScrollState() == RecyclerView.SCROLL_STATE_IDLE; + } + + /** + * Clears the state of the layout manager that positions list items. + */ + public void resetLayoutManager() { + setLayoutManager(new LayoutManager()); + } + + /** + * Controls whether WearableListView should intercept all touch events and also prevent the + * parent from receiving them. + * @param greedy If true it will intercept all touch events. + */ + public void setGreedyTouchMode(boolean greedy) { + mGreedyTouchMode = greedy; + } + + /** + * By default the first element of the list is initially positioned in the center of the screen. + * This method allows the developer to specify a different offset, e.g. to hide the + * WearableListView before the user is allowed to use it. + * + * @param top How far the elements should be pushed down. + */ + public void setInitialOffset(int top) { + mInitialOffset = top; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; + } + + if (mGreedyTouchMode && getChildCount() > 0) { + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_DOWN) { + mStartX = event.getX(); + mStartY = event.getY(); + mStartFirstTop = getChildCount() > 0 ? getChildAt(0).getTop() : 0; + mPossibleVerticalSwipe = true; + mGestureDirectionLocked = false; + } else if (action == MotionEvent.ACTION_MOVE && mPossibleVerticalSwipe) { + handlePossibleVerticalSwipe(event); + } + getParent().requestDisallowInterceptTouchEvent(mPossibleVerticalSwipe); + } + return super.onInterceptTouchEvent(event); + } + + private boolean handlePossibleVerticalSwipe(MotionEvent event) { + if (mGestureDirectionLocked) { + return mPossibleVerticalSwipe; + } + float deltaX = Math.abs(mStartX - event.getX()); + float deltaY = Math.abs(mStartY - event.getY()); + float distance = (deltaX * deltaX) + (deltaY * deltaY); + // Verify that the distance moved in the combined x/y direction is at + // least touch slop before determining the gesture direction. + if (distance > (mTouchSlop * mTouchSlop)) { + if (deltaX > deltaY) { + mPossibleVerticalSwipe = false; + } + mGestureDirectionLocked = true; + } + return mPossibleVerticalSwipe; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; + } + + // super.onTouchEvent can change the state of the scroll, keep a copy so that handleTouchUp + // can exit early if scrollState != IDLE when the touch event started. + int scrollState = getScrollState(); + boolean result = super.onTouchEvent(event); + if (getChildCount() > 0) { + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_DOWN) { + handleTouchDown(event); + } else if (action == MotionEvent.ACTION_UP) { + handleTouchUp(event, scrollState); + getParent().requestDisallowInterceptTouchEvent(false); + } else if (action == MotionEvent.ACTION_MOVE) { + if (Math.abs(mTapPositionX - (int) event.getX()) >= mTouchSlop || + Math.abs(mTapPositionY - (int) event.getY()) >= mTouchSlop) { + releasePressedItem(); + mCanClick = false; + } + result |= handlePossibleVerticalSwipe(event); + getParent().requestDisallowInterceptTouchEvent(mPossibleVerticalSwipe); + } else if (action == MotionEvent.ACTION_CANCEL) { + getParent().requestDisallowInterceptTouchEvent(false); + mCanClick = true; + } + } + return result; + } + + private void releasePressedItem() { + if (mPressedView != null) { + mPressedView.setPressed(false); + mPressedView = null; + } + Handler handler = getHandler(); + if (handler != null) { + handler.removeCallbacks(mPressedRunnable); + } + } + + private void onScroll(int dy) { + for (OnScrollListener listener : mOnScrollListeners) { + listener.onScroll(dy); + } + notifyChildrenAboutProximity(true); + } + + /** + * Adds a listener that will be called when the content of the list view is scrolled. + */ + public void addOnScrollListener(OnScrollListener listener) { + mOnScrollListeners.add(listener); + } + + /** + * Removes listener for scroll events. + */ + public void removeOnScrollListener(OnScrollListener listener) { + mOnScrollListeners.remove(listener); + } + + /** + * Adds a listener that will be called when the central item of the list changes. + */ + public void addOnCentralPositionChangedListener(OnCentralPositionChangedListener listener) { + mOnCentralPositionChangedListeners.add(listener); + } + + /** + * Removes a listener that would be called when the central item of the list changes. + */ + public void removeOnCentralPositionChangedListener(OnCentralPositionChangedListener listener) { + mOnCentralPositionChangedListeners.remove(listener); + } + + /** + * Determines if navigation of list with wrist gestures is enabled. + */ + public boolean isGestureNavigationEnabled() { + return mGestureNavigationEnabled; + } + + /** + * Sets whether navigation of list with wrist gestures is enabled. + */ + public void setEnableGestureNavigation(boolean enabled) { + mGestureNavigationEnabled = enabled; + } + + @Override /* KeyEvent.Callback */ + public boolean onKeyDown(int keyCode, KeyEvent event) { + // Respond to keycodes (at least originally generated and injected by wrist gestures). + if (mGestureNavigationEnabled) { + switch (keyCode) { + case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS: + fling(0, -mMinFlingVelocity); + return true; + case KeyEvent.KEYCODE_NAVIGATE_NEXT: + fling(0, mMinFlingVelocity); + return true; + case KeyEvent.KEYCODE_NAVIGATE_IN: + return tapCenterView(); + case KeyEvent.KEYCODE_NAVIGATE_OUT: + // Returing false leaves the action to the container of this WearableListView + // (e.g. finishing the activity containing this WearableListView). + return false; + } + } + return super.onKeyDown(keyCode, event); + } + + /** + * Simulate tapping the child view at the center of this list. + */ + private boolean tapCenterView() { + if (!isEnabled() || getVisibility() != View.VISIBLE) { + return false; + } + int index = findCenterViewIndex(); + View view = getChildAt(index); + ViewHolder holder = getChildViewHolder(view); + if (mClickListener != null) { + mClickListener.onClick(holder); + return true; + } + return false; + } + + private boolean checkForTap(MotionEvent event) { + // No taps are accepted if this view is disabled. + if (!isEnabled()) { + return false; + } + + float rawY = event.getRawY(); + int index = findCenterViewIndex(); + View view = getChildAt(index); + ViewHolder holder = getChildViewHolder(view); + computeTapRegions(mTapRegions); + if (rawY > mTapRegions[0] && rawY < mTapRegions[1]) { + if (mClickListener != null) { + mClickListener.onClick(holder); + } + return true; + } + if (index > 0 && rawY <= mTapRegions[0]) { + animateToMiddle(index - 1, index); + return true; + } + if (index < getChildCount() - 1 && rawY >= mTapRegions[1]) { + animateToMiddle(index + 1, index); + return true; + } + if (index == 0 && rawY <= mTapRegions[0] && mClickListener != null) { + // Special case: if the top third of the screen is empty and the touch event happens + // there, we don't want to immediately disallow the parent from using it. We tell + // parent to disallow intercept only after we locked a gesture. Before that he + // might do something with the action. + mClickListener.onTopEmptyRegionClick(); + return true; + } + return false; + } + + private void animateToMiddle(int newCenterIndex, int oldCenterIndex) { + if (newCenterIndex == oldCenterIndex) { + throw new IllegalArgumentException( + "newCenterIndex must be different from oldCenterIndex"); + } + List<Animator> animators = new ArrayList<Animator>(); + View child = getChildAt(newCenterIndex); + int scrollToMiddle = getCentralViewTop() - child.getTop(); + startScrollAnimation(animators, scrollToMiddle, FLIP_ANIMATION_DURATION_MS); + } + + private void startScrollAnimation(List<Animator> animators, int scroll, long duration) { + startScrollAnimation(animators, scroll, duration, 0); + } + + private void startScrollAnimation(List<Animator> animators, int scroll, long duration, + long delay) { + startScrollAnimation(animators, scroll, duration, delay, null); + } + + private void startScrollAnimation( + int scroll, long duration, long delay, Animator.AnimatorListener listener) { + startScrollAnimation(null, scroll, duration, delay, listener); + } + + private void startScrollAnimation(List<Animator> animators, int scroll, long duration, + long delay, Animator.AnimatorListener listener) { + if (mScrollAnimator != null) { + mScrollAnimator.cancel(); + } + + mLastScrollChange = 0; + ObjectAnimator scrollAnimator = ObjectAnimator.ofInt(this, mSetScrollVerticallyProperty, + 0, -scroll); + + if (animators != null) { + animators.add(scrollAnimator); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(animators); + mScrollAnimator = animatorSet; + } else { + mScrollAnimator = scrollAnimator; + } + mScrollAnimator.setDuration(duration); + if (listener != null) { + mScrollAnimator.addListener(listener); + } + if (delay > 0) { + mScrollAnimator.setStartDelay(delay); + } + mScrollAnimator.start(); + } + + @Override + public boolean fling(int velocityX, int velocityY) { + if (getChildCount() == 0) { + return false; + } + // If we are flinging towards empty space (before first element or after last), we reuse + // original flinging mechanism. + final int index = findCenterViewIndex(); + final View child = getChildAt(index); + int currentPosition = getChildPosition(child); + if ((currentPosition == 0 && velocityY < 0) || + (currentPosition == getAdapter().getItemCount() - 1 && velocityY > 0)) { + return super.fling(velocityX, velocityY); + } + + if (Math.abs(velocityY) < mMinFlingVelocity) { + return false; + } + velocityY = Math.max(Math.min(velocityY, mMaxFlingVelocity), -mMaxFlingVelocity); + + if (mScroller == null) { + mScroller = new Scroller(getContext(), null, true); + } + mScroller.fling(0, 0, 0, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE, + Integer.MIN_VALUE, Integer.MAX_VALUE); + int finalY = mScroller.getFinalY(); + int delta = finalY / (getPaddingTop() + getAdjustedHeight() / 2); + if (delta == 0) { + // If the fling would not be enough to change position, we increase it to satisfy user's + // intent of switching current position. + delta = velocityY > 0 ? 1 : -1; + } + int finalPosition = Math.max( + 0, Math.min(getAdapter().getItemCount() - 1, currentPosition + delta)); + smoothScrollToPosition(finalPosition); + return true; + } + + public void smoothScrollToPosition(int position, RecyclerView.SmoothScroller smoothScroller) { + LayoutManager layoutManager = (LayoutManager) getLayoutManager(); + layoutManager.setCustomSmoothScroller(smoothScroller); + smoothScrollToPosition(position); + layoutManager.clearCustomSmoothScroller(); + } + + @Override + public ViewHolder getChildViewHolder(View child) { + return (ViewHolder) super.getChildViewHolder(child); + } + + /** + * Adds a listener that will be called when the user taps on the WearableListView or its items. + */ + public void setClickListener(ClickListener clickListener) { + mClickListener = clickListener; + } + + /** + * Adds a listener that will be called when the user drags the top element below its allowed + * bottom position. + * + * @hide + */ + public void setOverScrollListener(OnOverScrollListener listener) { + mOverScrollListener = listener; + } + + private int findCenterViewIndex() { + // TODO(gruszczy): This could be easily optimized, so that we stop looking when we the + // distance starts growing again, instead of finding the closest. It would safe half of + // the loop. + int count = getChildCount(); + int index = -1; + int closest = Integer.MAX_VALUE; + int centerY = getCenterYPos(this); + for (int i = 0; i < count; ++i) { + final View child = getChildAt(i); + int childCenterY = getTop() + getCenterYPos(child); + final int distance = Math.abs(centerY - childCenterY); + if (distance < closest) { + closest = distance; + index = i; + } + } + if (index == -1) { + throw new IllegalStateException("Can't find central view."); + } + return index; + } + + private static int getCenterYPos(View v) { + return v.getTop() + v.getPaddingTop() + getAdjustedHeight(v) / 2; + } + + private void handleTouchUp(MotionEvent event, int scrollState) { + if (mCanClick && event != null && checkForTap(event)) { + Handler handler = getHandler(); + if (handler != null) { + handler.postDelayed(mReleasedRunnable, ViewConfiguration.getTapTimeout()); + } + return; + } + + if (scrollState != RecyclerView.SCROLL_STATE_IDLE) { + // We are flinging, so let's not start animations just yet. Instead we will start them + // when the fling finishes. + return; + } + + if (isOverScrolling()) { + mOverScrollListener.onOverScroll(); + } else { + animateToCenter(); + } + } + + private boolean isOverScrolling() { + return getChildCount() > 0 + // If first view top was below the central top, it means it was never centered. + // Don't allow overscroll, otherwise a simple touch (instead of a drag) will be + // enough to trigger overscroll. + && mStartFirstTop <= getCentralViewTop() + && getChildAt(0).getTop() >= getTopViewMaxTop() + && mOverScrollListener != null; + } + + private int getTopViewMaxTop() { + return getHeight() / 2; + } + + private int getItemHeight() { + // Round up so that the screen is fully occupied by 3 items. + return getAdjustedHeight() / THIRD + 1; + } + + /** + * Returns top of the central {@code View} in the list when such view is fully centered. + * + * This is a more or a less a static value that you can use to align other views with the + * central one. + */ + public int getCentralViewTop() { + return getPaddingTop() + getItemHeight(); + } + + /** + * Automatically starts an animation that snaps the list to center on the element closest to the + * middle. + */ + public void animateToCenter() { + final int index = findCenterViewIndex(); + final View child = getChildAt(index); + final int scrollToMiddle = getCentralViewTop() - child.getTop(); + startScrollAnimation(scrollToMiddle, CENTERING_ANIMATION_DURATION_MS, 0, + new SimpleAnimatorListener() { + @Override + public void onAnimationEnd(Animator animator) { + if (!wasCanceled()) { + mCanClick = true; + } + } + }); + } + + /** + * Animate the list so that the first view is back to its initial position. + * @param endAction Action to execute when the animation is done. + * @hide + */ + public void animateToInitialPosition(final Runnable endAction) { + final View child = getChildAt(0); + final int scrollToMiddle = getCentralViewTop() + mInitialOffset - child.getTop(); + startScrollAnimation(scrollToMiddle, CENTERING_ANIMATION_DURATION_MS, 0, + new SimpleAnimatorListener() { + @Override + public void onAnimationEnd(Animator animator) { + if (endAction != null) { + endAction.run(); + } + } + }); + } + + private void handleTouchDown(MotionEvent event) { + if (mCanClick) { + mTapPositionX = (int) event.getX(); + mTapPositionY = (int) event.getY(); + float rawY = event.getRawY(); + computeTapRegions(mTapRegions); + if (rawY > mTapRegions[0] && rawY < mTapRegions[1]) { + View view = getChildAt(findCenterViewIndex()); + if (view instanceof OnCenterProximityListener) { + Handler handler = getHandler(); + if (handler != null) { + handler.removeCallbacks(mReleasedRunnable); + handler.postDelayed(mPressedRunnable, ViewConfiguration.getTapTimeout()); + } + } + } + } + } + + private void setScrollVertically(int scroll) { + scrollBy(0, scroll - mLastScrollChange); + mLastScrollChange = scroll; + } + + private int getAdjustedHeight() { + return getAdjustedHeight(this); + } + + private static int getAdjustedHeight(View v) { + return v.getHeight() - v.getPaddingBottom() - v.getPaddingTop(); + } + + private void computeTapRegions(float[] tapRegions) { + mLocation[0] = mLocation[1] = 0; + getLocationOnScreen(mLocation); + int mScreenTop = mLocation[1]; + int height = getHeight(); + tapRegions[0] = mScreenTop + height * TOP_TAP_REGION_PERCENTAGE; + tapRegions[1] = mScreenTop + height * (1 - BOTTOM_TAP_REGION_PERCENTAGE); + } + + /** + * Determines if, when there is only one item in the WearableListView, that the single item + * is laid out so that it's height fills the entire WearableListView. + */ + public boolean getMaximizeSingleItem() { + return mMaximizeSingleItem; + } + + /** + * When set to true, if there is only one item in the WearableListView, it will fill the entire + * WearableListView. When set to false, the default behavior will be used and the single item + * will fill only a third of the screen. + */ + public void setMaximizeSingleItem(boolean maximizeSingleItem) { + mMaximizeSingleItem = maximizeSingleItem; + } + + private void notifyChildrenAboutProximity(boolean animate) { + LayoutManager layoutManager = (LayoutManager) getLayoutManager(); + int count = layoutManager.getChildCount(); + + if (count == 0) { + return; + } + + int index = layoutManager.findCenterViewIndex(); + for (int i = 0; i < count; ++i) { + final View view = layoutManager.getChildAt(i); + ViewHolder holder = getChildViewHolder(view); + holder.onCenterProximity(i == index, animate); + } + final int position = getChildViewHolder(getChildAt(index)).getPosition(); + if (position != mPreviousCentral) { + for (OnScrollListener listener : mOnScrollListeners) { + listener.onCentralPositionChanged(position); + } + for (OnCentralPositionChangedListener listener : + mOnCentralPositionChangedListeners) { + listener.onCentralPositionChanged(position); + } + mPreviousCentral = position; + } + } + + // TODO: Move this to a separate class, so it can't directly interact with the WearableListView. + private class LayoutManager extends RecyclerView.LayoutManager { + private int mFirstPosition; + + private boolean mPushFirstHigher; + + private int mAbsoluteScroll; + + private boolean mUseOldViewTop = true; + + private boolean mWasZoomedIn = false; + + private RecyclerView.SmoothScroller mSmoothScroller; + + private RecyclerView.SmoothScroller mDefaultSmoothScroller; + + // We need to have another copy of the same method, because this one uses + // LayoutManager.getChildCount/getChildAt instead of View.getChildCount/getChildAt and + // they return different values. + private int findCenterViewIndex() { + // TODO(gruszczy): This could be easily optimized, so that we stop looking when we the + // distance starts growing again, instead of finding the closest. It would safe half of + // the loop. + int count = getChildCount(); + int index = -1; + int closest = Integer.MAX_VALUE; + int centerY = getCenterYPos(WearableListView.this); + for (int i = 0; i < count; ++i) { + final View child = getLayoutManager().getChildAt(i); + int childCenterY = getTop() + getCenterYPos(child); + final int distance = Math.abs(centerY - childCenterY); + if (distance < closest) { + closest = distance; + index = i; + } + } + if (index == -1) { + throw new IllegalStateException("Can't find central view."); + } + return index; + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, State state) { + final int parentBottom = getHeight() - getPaddingBottom(); + // By default we assume this is the first run and the first element will be centered + // with optional initial offset. + int oldTop = getCentralViewTop() + mInitialOffset; + // Here we handle any other situation where we relayout or we want to achieve a + // specific layout of children. + if (mUseOldViewTop && getChildCount() > 0) { + // We are performing a relayout after we already had some children, because e.g. the + // contents of an adapter has changed. First we want to check, if the central item + // from before the layout is still here, because we want to preserve it. + int index = findCenterViewIndex(); + int position = getPosition(getChildAt(index)); + if (position == NO_POSITION) { + // Central item was removed. Let's find the first surviving item and use it + // as an anchor. + for (int i = 0, N = getChildCount(); index + i < N || index - i >= 0; ++i) { + View child = getChildAt(index + i); + if (child != null) { + position = getPosition(child); + if (position != NO_POSITION) { + index = index + i; + break; + } + } + child = getChildAt(index - i); + if (child != null) { + position = getPosition(child); + if (position != NO_POSITION) { + index = index - i; + break; + } + } + } + } + if (position == NO_POSITION) { + // None of the children survives the relayout, let's just use the top of the + // first one. + oldTop = getChildAt(0).getTop(); + int count = state.getItemCount(); + // Lets first make sure that the first position is not above the last element, + // which can happen if elements were removed. + while (mFirstPosition >= count && mFirstPosition > 0) { + mFirstPosition--; + } + } else { + // Some of the children survived the relayout. We will keep it in its place, + // but go through previous children and maybe add them. + if (!mWasZoomedIn) { + // If we were previously zoomed-in on a single item, ignore this and just + // use the default value set above. Reasoning: if we are still zoomed-in, + // oldTop will be ignored when laying out the single child element. If we + // are no longer zoomed in, then we want to position items using the top + // of the single item as if the single item was not zoomed in, which is + // equal to the default value. + oldTop = getChildAt(index).getTop(); + } + while (oldTop > getPaddingTop() && position > 0) { + position--; + oldTop -= getItemHeight(); + } + if (position == 0 && oldTop > getCentralViewTop()) { + // We need to handle special case where the first, central item was removed + // and now the first element is hanging below, instead of being nicely + // centered. + oldTop = getCentralViewTop(); + } + mFirstPosition = position; + } + } else if (mPushFirstHigher) { + // We are trying to position elements ourselves, so we force position of the first + // one. + oldTop = getCentralViewTop() - getItemHeight(); + } + + performLayoutChildren(recycler, state, parentBottom, oldTop); + + // Since the content might have changed, we need to adjust the absolute scroll in case + // some elements have disappeared or were added. + if (getChildCount() == 0) { + setAbsoluteScroll(0); + } else { + View child = getChildAt(findCenterViewIndex()); + setAbsoluteScroll(child.getTop() - getCentralViewTop() + getPosition(child) * + getItemHeight()); + } + + mUseOldViewTop = true; + mPushFirstHigher = false; + } + + private void performLayoutChildren(Recycler recycler, State state, int parentBottom, + int top) { + detachAndScrapAttachedViews(recycler); + + if (mMaximizeSingleItem && state.getItemCount() == 1) { + performLayoutOneChild(recycler, parentBottom); + mWasZoomedIn = true; + } else { + performLayoutMultipleChildren(recycler, state, parentBottom, top); + mWasZoomedIn = false; + } + + if (getChildCount() > 0) { + post(mNotifyChildrenPostLayoutRunnable); + } + } + + private void performLayoutOneChild(Recycler recycler, int parentBottom) { + final int right = getWidth() - getPaddingRight(); + View v = recycler.getViewForPosition(getFirstPosition()); + addView(v, 0); + measureZoomView(v); + v.layout(getPaddingLeft(), getPaddingTop(), right, parentBottom); + } + + private void performLayoutMultipleChildren(Recycler recycler, State state, int parentBottom, + int top) { + int bottom; + final int left = getPaddingLeft(); + final int right = getWidth() - getPaddingRight(); + final int count = state.getItemCount(); + // If we are laying out children with center element being different than the first, we + // need to start with previous child which appears half visible at the top. + for (int i = 0; getFirstPosition() + i < count; i++, top = bottom) { + if (top >= parentBottom) { + break; + } + View v = recycler.getViewForPosition(getFirstPosition() + i); + addView(v, i); + measureThirdView(v); + bottom = top + getItemHeight(); + v.layout(left, top, right, bottom); + } + } + + private void setAbsoluteScroll(int absoluteScroll) { + mAbsoluteScroll = absoluteScroll; + for (OnScrollListener listener : mOnScrollListeners) { + listener.onAbsoluteScrollChange(mAbsoluteScroll); + } + } + + private void measureView(View v, int height) { + final LayoutParams lp = (LayoutParams) v.getLayoutParams(); + final int widthSpec = getChildMeasureSpec(getWidth(), + getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, lp.width, + canScrollHorizontally()); + final int heightSpec = getChildMeasureSpec(getHeight(), + getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, + height, canScrollVertically()); + v.measure(widthSpec, heightSpec); + } + + private void measureThirdView(View v) { + measureView(v, (int) (1 + (float) getHeight() / THIRD)); + } + + private void measureZoomView(View v) { + measureView(v, getHeight()); + } + + @Override + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } + + @Override + public boolean canScrollVertically() { + // Disable vertical scrolling when zoomed. + return getItemCount() != 1 || !mWasZoomedIn; + } + + @Override + public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, State state) { + // TODO(gruszczy): This code is shit, needs to be rewritten. + if (getChildCount() == 0) { + return 0; + } + int scrolled = 0; + final int left = getPaddingLeft(); + final int right = getWidth() - getPaddingRight(); + if (dy < 0) { + while (scrolled > dy) { + final View topView = getChildAt(0); + if (getFirstPosition() > 0) { + final int hangingTop = Math.max(-topView.getTop(), 0); + final int scrollBy = Math.min(scrolled - dy, hangingTop); + scrolled -= scrollBy; + offsetChildrenVertical(scrollBy); + if (getFirstPosition() > 0 && scrolled > dy) { + mFirstPosition--; + View v = recycler.getViewForPosition(getFirstPosition()); + addView(v, 0); + measureThirdView(v); + final int bottom = topView.getTop(); + final int top = bottom - getItemHeight(); + v.layout(left, top, right, bottom); + } else { + break; + } + } else { + mPushFirstHigher = false; + int maxScroll = mOverScrollListener!= null ? + getHeight() : getTopViewMaxTop(); + final int scrollBy = Math.min(-dy + scrolled, maxScroll - topView.getTop()); + scrolled -= scrollBy; + offsetChildrenVertical(scrollBy); + break; + } + } + } else if (dy > 0) { + final int parentHeight = getHeight(); + while (scrolled < dy) { + final View bottomView = getChildAt(getChildCount() - 1); + if (state.getItemCount() > mFirstPosition + getChildCount()) { + final int hangingBottom = + Math.max(bottomView.getBottom() - parentHeight, 0); + final int scrollBy = -Math.min(dy - scrolled, hangingBottom); + scrolled -= scrollBy; + offsetChildrenVertical(scrollBy); + if (scrolled < dy) { + View v = recycler.getViewForPosition(mFirstPosition + getChildCount()); + final int top = getChildAt(getChildCount() - 1).getBottom(); + addView(v); + measureThirdView(v); + final int bottom = top + getItemHeight(); + v.layout(left, top, right, bottom); + } else { + break; + } + } else { + final int scrollBy = + Math.max(-dy + scrolled, getHeight() / 2 - bottomView.getBottom()); + scrolled -= scrollBy; + offsetChildrenVertical(scrollBy); + break; + } + } + } + recycleViewsOutOfBounds(recycler); + setAbsoluteScroll(mAbsoluteScroll + scrolled); + return scrolled; + } + + @Override + public void scrollToPosition(int position) { + mUseOldViewTop = false; + if (position > 0) { + mFirstPosition = position - 1; + mPushFirstHigher = true; + } else { + mFirstPosition = position; + mPushFirstHigher = false; + } + requestLayout(); + } + + public void setCustomSmoothScroller(RecyclerView.SmoothScroller smoothScroller) { + mSmoothScroller = smoothScroller; + } + + public void clearCustomSmoothScroller() { + mSmoothScroller = null; + } + + public RecyclerView.SmoothScroller getDefaultSmoothScroller(RecyclerView recyclerView) { + if (mDefaultSmoothScroller == null) { + mDefaultSmoothScroller = new SmoothScroller( + recyclerView.getContext(), this); + } + return mDefaultSmoothScroller; + } + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, State state, + int position) { + RecyclerView.SmoothScroller scroller = mSmoothScroller; + if (scroller == null) { + scroller = getDefaultSmoothScroller(recyclerView); + } + scroller.setTargetPosition(position); + startSmoothScroll(scroller); + } + + private void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) { + final int childCount = getChildCount(); + final int parentWidth = getWidth(); + // Here we want to use real height, so we don't remove views that are only visible in + // padded section. + final int parentHeight = getHeight(); + boolean foundFirst = false; + int first = 0; + int last = 0; + for (int i = 0; i < childCount; i++) { + final View v = getChildAt(i); + if (v.hasFocus() || (v.getRight() >= 0 && v.getLeft() <= parentWidth && + v.getBottom() >= 0 && v.getTop() <= parentHeight)) { + if (!foundFirst) { + first = i; + foundFirst = true; + } + last = i; + } + } + for (int i = childCount - 1; i > last; i--) { + removeAndRecycleViewAt(i, recycler); + } + for (int i = first - 1; i >= 0; i--) { + removeAndRecycleViewAt(i, recycler); + } + if (getChildCount() == 0) { + mFirstPosition = 0; + } else if (first > 0) { + mPushFirstHigher = true; + mFirstPosition += first; + } + } + + public int getFirstPosition() { + return mFirstPosition; + } + + @Override + public void onAdapterChanged(RecyclerView.Adapter oldAdapter, + RecyclerView.Adapter newAdapter) { + removeAllViews(); + } + } + + /** + * Interface for receiving callbacks when WearableListView children become or cease to be the + * central item. + */ + public interface OnCenterProximityListener { + /** + * Called when this view becomes central item of the WearableListView. + * + * @param animate Whether you should animate your transition of the View to become the + * central item. If false, this is the initial setting and you should + * transition immediately. + */ + void onCenterPosition(boolean animate); + + /** + * Called when this view stops being the central item of the WearableListView. + * @param animate Whether you should animate your transition of the View to being + * non central item. If false, this is the initial setting and you should + * transition immediately. + */ + void onNonCenterPosition(boolean animate); + } + + /** + * Interface for listening for click events on WearableListView. + */ + public interface ClickListener { + /** + * Called when the central child of the WearableListView is tapped. + * @param view View that was clicked. + */ + public void onClick(ViewHolder view); + + /** + * Called when the user taps the top third of the WearableListView and no item is present + * there. This can happen when you are in initial state and the first, top-most item of the + * WearableListView is centered. + */ + public void onTopEmptyRegionClick(); + } + + /** + * @hide + */ + public interface OnOverScrollListener { + public void onOverScroll(); + } + + /** + * Interface for listening to WearableListView content scrolling. + */ + public interface OnScrollListener { + /** + * Called when the content is scrolled, reporting the relative scroll value. + * @param scroll Amount the content was scrolled. This is a delta from the previous + * position to the new position. + */ + public void onScroll(int scroll); + + /** + * Called when the content is scrolled, reporting the absolute scroll value. + * + * @deprecated BE ADVISED DO NOT USE THIS This might provide wrong values when contents + * of a RecyclerView change. + * + * @param scroll Absolute scroll position of the content inside the WearableListView. + */ + @Deprecated + public void onAbsoluteScrollChange(int scroll); + + /** + * Called when WearableListView's scroll state changes. + * + * @param scrollState The updated scroll state. One of {@link #SCROLL_STATE_IDLE}, + * {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}. + */ + public void onScrollStateChanged(int scrollState); + + /** + * Called when the central item of the WearableListView changes. + * + * @param centralPosition Position of the item in the Adapter. + */ + public void onCentralPositionChanged(int centralPosition); + } + + /** + * A listener interface that can be added to the WearableListView to get notified when the + * central item is changed. + */ + public interface OnCentralPositionChangedListener { + /** + * Called when the central item of the WearableListView changes. + * + * @param centralPosition Position of the item in the Adapter. + */ + void onCentralPositionChanged(int centralPosition); + } + + /** + * Base class for adapters providing data for the WearableListView. For details refer to + * RecyclerView.Adapter. + */ + public static abstract class Adapter extends RecyclerView.Adapter<ViewHolder> { + } + + private static class SmoothScroller extends LinearSmoothScroller { + + private static final float MILLISECONDS_PER_INCH = 100f; + + private final LayoutManager mLayoutManager; + + public SmoothScroller(Context context, WearableListView.LayoutManager manager) { + super(context); + mLayoutManager = manager; + } + + @Override + protected void onStart() { + super.onStart(); + } + + // TODO: (mindyp): when flinging, return the dydt that triggered the fling. + @Override + protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { + return MILLISECONDS_PER_INCH / displayMetrics.densityDpi; + } + + @Override + public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int + snapPreference) { + // Snap to center. + return (boxStart + boxEnd) / 2 - (viewStart + viewEnd) / 2; + } + + @Override + public PointF computeScrollVectorForPosition(int targetPosition) { + if (targetPosition < mLayoutManager.getFirstPosition()) { + return new PointF(0, -1); + } else { + return new PointF(0, 1); + } + } + } + + /** + * Wrapper around items displayed in the list view. {@link .Adapter} must return objects that + * are instances of this class. Consider making the wrapped View implement + * {@link .OnCenterProximityListener} if you want to receive a callback when it becomes or + * ceases to be the central item in the WearableListView. + */ + public static class ViewHolder extends RecyclerView.ViewHolder { + public ViewHolder(View itemView) { + super(itemView); + } + + /** + * Called when the wrapped view is becoming or ceasing to be the central item of the + * WearableListView. + * + * Retained as protected for backwards compatibility. + * + * @hide + */ + protected void onCenterProximity(boolean isCentralItem, boolean animate) { + if (!(itemView instanceof OnCenterProximityListener)) { + return; + } + OnCenterProximityListener item = (OnCenterProximityListener) itemView; + if (isCentralItem) { + item.onCenterPosition(animate); + } else { + item.onNonCenterPosition(animate); + } + } + } + + private class SetScrollVerticallyProperty extends Property<WearableListView, Integer> { + public SetScrollVerticallyProperty() { + super(Integer.class, "scrollVertically"); + } + + @Override + public Integer get(WearableListView wearableListView) { + return wearableListView.mLastScrollChange; + } + + @Override + public void set(WearableListView wearableListView, Integer value) { + wearableListView.setScrollVertically(value); + } + } +} diff --git a/src/com/android/packageinstaller/DeviceUtils.java b/src/com/android/packageinstaller/DeviceUtils.java new file mode 100644 index 00000000..8e2d57ea --- /dev/null +++ b/src/com/android/packageinstaller/DeviceUtils.java @@ -0,0 +1,32 @@ +/* + * 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.packageinstaller; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.res.Configuration; + +public class DeviceUtils { + public static boolean isTelevision(Context context) { + int uiMode = context.getResources().getConfiguration().uiMode; + return (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION; + } + + public static boolean isWear(final Context context) { + return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH); + } +} diff --git a/src/com/android/packageinstaller/InstallFlowAnalytics.java b/src/com/android/packageinstaller/InstallFlowAnalytics.java index 2fc6db37..4591f31c 100644 --- a/src/com/android/packageinstaller/InstallFlowAnalytics.java +++ b/src/com/android/packageinstaller/InstallFlowAnalytics.java @@ -85,6 +85,11 @@ public class InstallFlowAnalytics implements Parcelable { */ static final byte RESULT_PACKAGE_MANAGER_INSTALL_FAILED = 6; + /** + * Installation blocked since this feature is not allowed on Android Wear devices yet. + */ + static final byte RESULT_NOT_ALLOWED_ON_WEAR = 7; + private static final int FLAG_INSTALLS_FROM_UNKNOWN_SOURCES_PERMITTED = 1 << 0; private static final int FLAG_INSTALL_REQUEST_FROM_UNKNOWN_SOURCE = 1 << 1; private static final int FLAG_VERIFY_APPS_ENABLED = 1 << 2; @@ -600,4 +605,4 @@ public class InstallFlowAnalytics implements Parcelable { } return digest.digest(); } -}
\ No newline at end of file +} diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java index 6bcd80e4..868872a9 100644 --- a/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -110,6 +110,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen private static final int DLG_INSTALL_ERROR = DLG_BASE + 4; private static final int DLG_ALLOW_SOURCE = DLG_BASE + 5; private static final int DLG_ADMIN_RESTRICTS_UNKNOWN_SOURCES = DLG_BASE + 6; + private static final int DLG_NOT_SUPPORTED_ON_WEAR = DLG_BASE + 7; private void startInstallConfirm() { TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost); @@ -293,7 +294,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen Log.i(TAG, "Canceling installation"); finish(); } - }) + }) .setOnCancelListener(this) .create(); case DLG_INSTALL_ERROR : @@ -333,6 +334,18 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen }) .setOnCancelListener(this) .create(); + case DLG_NOT_SUPPORTED_ON_WEAR: + return new AlertDialog.Builder(this) + .setTitle(R.string.wear_not_allowed_dlg_title) + .setMessage(R.string.wear_not_allowed_dlg_text) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + setResult(RESULT_OK); + finish(); + } + }) + .setOnCancelListener(this) + .create(); } return null; } @@ -478,6 +491,13 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen mInstallFlowAnalytics.setAppVerifierInstalled(isAppVerifierInstalled()); mInstallFlowAnalytics.setPackageUri(mPackageURI.toString()); + if (DeviceUtils.isWear(this)) { + showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR); + mInstallFlowAnalytics.setFlowFinished( + InstallFlowAnalytics.RESULT_NOT_ALLOWED_ON_WEAR); + return; + } + final String scheme = mPackageURI.getScheme(); if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) { Log.w(TAG, "Unsupported scheme " + scheme); diff --git a/src/com/android/packageinstaller/permission/model/AppPermissions.java b/src/com/android/packageinstaller/permission/model/AppPermissions.java index d465ee09..a0f23d64 100644 --- a/src/com/android/packageinstaller/permission/model/AppPermissions.java +++ b/src/com/android/packageinstaller/permission/model/AppPermissions.java @@ -23,6 +23,8 @@ import android.text.BidiFormatter; import android.text.TextPaint; import android.text.TextUtils; +import com.android.packageinstaller.DeviceUtils; + import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -165,9 +167,12 @@ public final class AppPermissions { private static CharSequence loadEllipsizedAppLabel(Context context, PackageInfo packageInfo) { String label = packageInfo.applicationInfo.loadLabel( context.getPackageManager()).toString(); - String noNewLineLabel = label.replace("\n", " "); - String ellipsizedLabel = TextUtils.ellipsize(noNewLineLabel, sAppLabelEllipsizePaint, + String ellipsizedLabel = label.replace("\n", " "); + if (!DeviceUtils.isWear(context)) { + // Only ellipsize for non-Wear devices. + ellipsizedLabel = TextUtils.ellipsize(ellipsizedLabel, sAppLabelEllipsizePaint, MAX_APP_LABEL_LENGTH_PIXELS, TextUtils.TruncateAt.END).toString(); + } return BidiFormatter.getInstance().unicodeWrap(ellipsizedLabel); } } diff --git a/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java b/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java index 2a46f1a6..810ae8ec 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java +++ b/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java @@ -18,6 +18,7 @@ package com.android.packageinstaller.permission.model; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -30,37 +31,55 @@ import com.android.packageinstaller.permission.utils.Utils; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; +import java.util.List; public class PermissionStatusReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - int[] counts = new int[3]; - ArrayList<CharSequence> grantedGroups = new ArrayList<>(); - boolean succeeded = false; + if (Intent.ACTION_GET_PERMISSIONS_COUNT.equals(intent.getAction())) { + Intent responseIntent = new Intent(intent.getStringExtra( + Intent.EXTRA_GET_PERMISSIONS_RESPONSE_INTENT)); + responseIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); - boolean isForPackage = intent.hasExtra(Intent.EXTRA_PACKAGE_NAME); + int[] counts = new int[3]; + ArrayList<CharSequence> grantedGroups = new ArrayList<>(); + boolean succeeded = false; - Intent responseIntent = new Intent(intent.getStringExtra( - Intent.EXTRA_GET_PERMISSIONS_RESPONSE_INTENT)); - responseIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); - - - if (isForPackage) { - String pkg = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); - succeeded = getPermissionsCount(context, pkg, counts, grantedGroups); - } else { - succeeded = getAppsWithPermissionsCount(context, counts); - } - if (succeeded) { - responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_COUNT_RESULT, counts); + boolean isForPackage = intent.hasExtra(Intent.EXTRA_PACKAGE_NAME); if (isForPackage) { - responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT, - grantedGroups.toArray(new CharSequence[grantedGroups.size()])); + String pkg = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); + succeeded = getPermissionsCount(context, pkg, counts, grantedGroups); + } else { + succeeded = getAppsWithPermissionsCount(context, counts); } - } + if (succeeded) { + responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_COUNT_RESULT, counts); - context.sendBroadcast(responseIntent); + if (isForPackage) { + responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT, + grantedGroups.toArray(new CharSequence[grantedGroups.size()])); + } + } + context.sendBroadcast(responseIntent); + } else if (Intent.ACTION_GET_PERMISSIONS_PACKAGES.equals(intent.getAction())) { + Intent responseIntent = new Intent(intent.getStringExtra( + Intent.EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT)); + responseIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); + + List<String> appsList = new ArrayList<>(); + List<CharSequence> appLabelsList = new ArrayList<>(); + List<Boolean> isSystemAppList = new ArrayList<>(); + if (getAppsWithRuntimePermissions(context, appsList, appLabelsList, isSystemAppList)) { + responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_APP_LIST_RESULT, + appsList.toArray(new String[appsList.size()])); + responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT, + appLabelsList.toArray(new String[appLabelsList.size()])); + responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT, + toPrimitiveBoolArray(isSystemAppList)); + } + context.sendBroadcast(responseIntent); + } } public boolean getPermissionsCount(Context context, String pkg, int[] counts, @@ -105,6 +124,42 @@ public class PermissionStatusReceiver extends BroadcastReceiver { } } + public boolean getAppsWithRuntimePermissions(Context context, List<String> appsList, + List<CharSequence> appLabelsList, List<Boolean> isSystemAppList) { + final List<ApplicationInfo> appInfos = Utils.getAllInstalledApplications(context); + if (appInfos == null) { + return false; + } + final int appInfosSize = appInfos.size(); + try { + ArraySet<String> launcherPackages = Utils.getLauncherPackages(context); + for (int i = 0; i < appInfosSize; ++i) { + final String packageName = appInfos.get(i).packageName; + PackageInfo packageInfo = context.getPackageManager().getPackageInfo( + packageName, PackageManager.GET_PERMISSIONS); + AppPermissions appPermissions = + new AppPermissions(context, packageInfo, null, false, null); + + boolean shouldShow = false; + for (AppPermissionGroup group : appPermissions.getPermissionGroups()) { + if (Utils.shouldShowPermission(group, packageName)) { + shouldShow = true; + break; + } + } + if (shouldShow) { + appsList.add(packageName); + appLabelsList.add(appPermissions.getAppLabel()); + isSystemAppList.add(Utils.isSystem(appPermissions, launcherPackages)); + } + } + } catch (NameNotFoundException e) { + return false; + } + + return true; + } + public boolean getAppsWithPermissionsCount(Context context, int[] counts) { ArraySet<String> launcherPkgs = Utils.getLauncherPackages(context); // Indexed by uid. @@ -130,4 +185,14 @@ public class PermissionStatusReceiver extends BroadcastReceiver { counts[1] = allApps.size(); return true; } + + private boolean[] toPrimitiveBoolArray(final List<Boolean> list) { + final int count = list.size(); + final boolean[] result = new boolean[count]; + for (int i = 0; i < count; ++i) { + result[i] = list.get(i); + } + + return result; + } } diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java index c8446039..102fd6ef 100644 --- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java @@ -39,6 +39,7 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; +import com.android.packageinstaller.DeviceUtils; import com.android.packageinstaller.R; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.AppPermissions; @@ -72,9 +73,11 @@ public class GrantPermissionsActivity extends OverlayTouchActivity setTitle(R.string.permission_request_title); - if (Utils.isTelevision(this)) { + if (DeviceUtils.isTelevision(this)) { mViewHandler = new com.android.packageinstaller.permission.ui.television .GrantPermissionsViewHandlerImpl(this).setResultListener(this); + } else if (DeviceUtils.isWear(this)) { + mViewHandler = new GrantPermissionsWatchViewHandler(this).setResultListener(this); } else { mViewHandler = new com.android.packageinstaller.permission.ui.handheld .GrantPermissionsViewHandlerImpl(this).setResultListener(this); diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java new file mode 100644 index 00000000..21042f00 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java @@ -0,0 +1,176 @@ +package com.android.packageinstaller.permission.ui; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.WindowManager; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.ui.wear.ConfirmationViewHandler; + +/** + * Watch-specific view handler for the grant permissions activity. + */ +final class GrantPermissionsWatchViewHandler extends ConfirmationViewHandler + implements GrantPermissionsViewHandler { + private static final String TAG = "GrantPermsWatchViewH"; + + private static final String ARG_GROUP_NAME = "ARG_GROUP_NAME"; + + private final Context mContext; + + private ResultListener mResultListener; + + private String mGroupName; + private boolean mShowDoNotAsk; + + private CharSequence mMessage; + private String mCurrentPageText; + private Icon mIcon; + + GrantPermissionsWatchViewHandler(Context context) { + super(context); + mContext = context; + } + + @Override + public GrantPermissionsWatchViewHandler setResultListener(ResultListener listener) { + mResultListener = listener; + return this; + } + + @Override + public View createView() { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "createView()"); + } + + mShowDoNotAsk = false; + + return super.createView(); + } + + @Override + public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) { + outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; + outLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; + outLayoutParams.format = PixelFormat.OPAQUE; + outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; + outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; + } + + @Override + public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon, + CharSequence message, boolean showDoNotAsk) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "updateUi() - groupName: " + groupName + + ", groupCount: " + groupCount + + ", groupIndex: " + groupIndex + + ", icon: " + icon + + ", message: " + message + + ", showDoNotAsk: " + showDoNotAsk); + } + + mGroupName = groupName; + mShowDoNotAsk = showDoNotAsk; + mMessage = message; + mIcon = icon; + mCurrentPageText = (groupCount > 1 ? + mContext.getString(R.string.current_permission_template, groupIndex + 1, groupCount) + : null); + + invalidate(); + } + + @Override + public void saveInstanceState(Bundle outState) { + outState.putString(ARG_GROUP_NAME, mGroupName); + } + + @Override + public void loadInstanceState(Bundle savedInstanceState) { + mGroupName = savedInstanceState.getString(ARG_GROUP_NAME); + } + + @Override + public void onBackPressed() { + if (mResultListener != null) { + mResultListener.onPermissionGrantResult(mGroupName, false, false); + } + } + + @Override // ConfirmationViewHandler + public void onButton1() { + onClick(true /* granted */, false /* doNotAskAgain */); + } + + @Override // ConfirmationViewHandler + public void onButton2() { + onClick(false /* granted */, false /* doNotAskAgain */); + } + + @Override // ConfirmationViewHandler + public void onButton3() { + onClick(false /* granted */, true /* doNotAskAgain */); + } + + @Override // ConfirmationViewHandler + public CharSequence getCurrentPageText() { + return mCurrentPageText; + } + + @Override // ConfirmationViewHandler + public Icon getPermissionIcon() { + return mIcon; + } + + @Override // ConfirmationViewHandler + public CharSequence getMessage() { + return mMessage; + } + + @Override // ConfirmationViewHandler + public int getButtonBarMode() { + return mShowDoNotAsk ? MODE_VERTICAL_BUTTONS : MODE_HORIZONTAL_BUTTONS; + } + + @Override // ConfirmationViewHandler + public CharSequence getVerticalButton1Text() { + return mContext.getString(R.string.grant_dialog_button_allow); + } + + @Override // ConfirmationViewHandler + public CharSequence getVerticalButton2Text() { + return mContext.getString(R.string.grant_dialog_button_deny); + } + + @Override // ConfirmationViewHandler + public CharSequence getVerticalButton3Text() { + return mContext.getString(R.string.grant_dialog_button_deny_dont_ask_again); + } + + @Override // ConfirmationViewHandler + public Drawable getVerticalButton1Icon(){ + return mContext.getDrawable(R.drawable.confirm_button); + } + + @Override // ConfirmationViewHandler + public Drawable getVerticalButton2Icon(){ + return mContext.getDrawable(R.drawable.cancel_button); + } + + @Override // ConfirmationViewHandler + public Drawable getVerticalButton3Icon(){ + return mContext.getDrawable(R.drawable.deny_button); + } + + private void onClick(boolean granted, boolean doNotAskAgain) { + if (mResultListener != null) { + mResultListener.onPermissionGrantResult(mGroupName, granted, doNotAskAgain); + } + } +} diff --git a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java index f5703564..a92b0ea4 100644 --- a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java +++ b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java @@ -21,6 +21,12 @@ import android.content.Intent; import android.os.Bundle; import android.util.Log; import com.android.packageinstaller.permission.utils.Utils; +<<<<<<< HEAD + +import com.android.packageinstaller.permission.ui.wear.AppPermissionsFragmentWear; +import com.android.packageinstaller.DeviceUtils; +======= +>>>>>>> c10abb25f3864e56b2a24ef3661511cd78921225 public final class ManagePermissionsActivity extends OverlayTouchActivity { private static final String LOG_TAG = "ManagePermissionsActivity"; @@ -54,7 +60,9 @@ public final class ManagePermissionsActivity extends OverlayTouchActivity { finish(); return; } - if (Utils.isTelevision(this)) { + if (DeviceUtils.isWear(this)) { + fragment = AppPermissionsFragmentWear.newInstance(packageName); + } else if (Utils.isTelevision(this)) { fragment = com.android.packageinstaller.permission.ui.television .AppPermissionsFragment.newInstance(packageName); } else { diff --git a/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java index e41e05fb..0f240bef 100644 --- a/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java @@ -39,6 +39,7 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import com.android.packageinstaller.DeviceUtils; import com.android.packageinstaller.R; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.PermissionApps; @@ -186,7 +187,7 @@ public final class PermissionAppsFragment extends PermissionsFrameFragment imple return; } - boolean isTelevision = Utils.isTelevision(context); + boolean isTelevision = DeviceUtils.isTelevision(context); PreferenceScreen screen = getPreferenceScreen(); ArraySet<String> preferencesToRemove = new ArraySet<>(); diff --git a/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java b/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java new file mode 100644 index 00000000..aba97fc8 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java @@ -0,0 +1,335 @@ +/* +* 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.packageinstaller.permission.ui.wear; + +import android.Manifest; +import android.annotation.Nullable; +import android.app.Activity; +import android.app.Fragment; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.support.wearable.view.WearableListView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.model.AppPermissionGroup; +import com.android.packageinstaller.permission.model.AppPermissions; +import com.android.packageinstaller.permission.ui.OverlayTouchActivity; +import com.android.packageinstaller.permission.ui.wear.settings.PermissionsSettingsAdapter; +import com.android.packageinstaller.permission.ui.wear.settings.SettingsAdapter; +import com.android.packageinstaller.permission.utils.LocationUtils; +import com.android.packageinstaller.permission.utils.SafetyNetLogger; +import com.android.packageinstaller.permission.utils.Utils; + +import java.util.ArrayList; +import java.util.List; + +public final class AppPermissionsFragmentWear extends TitledSettingsFragment { + + private static final String LOG_TAG = "ManagePermsFragment"; + + private static final int WARNING_CONFIRMATION_REQUEST = 252; + private List<AppPermissionGroup> mToggledGroups; + private AppPermissions mAppPermissions; + private PermissionsSettingsAdapter mAdapter; + + private boolean mHasConfirmedRevoke; + + public static AppPermissionsFragmentWear newInstance(String packageName) { + return setPackageName(new AppPermissionsFragmentWear(), packageName); + } + + private static <T extends Fragment> T setPackageName(T fragment, String packageName) { + Bundle arguments = new Bundle(); + arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); + fragment.setArguments(arguments); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); + Activity activity = getActivity(); + PackageManager pm = activity.getPackageManager(); + PackageInfo packageInfo; + + try { + packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS); + } catch (PackageManager.NameNotFoundException e) { + Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); + packageInfo = null; + } + + if (packageInfo == null) { + Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); + activity.finish(); + return; + } + + mAppPermissions = new AppPermissions(activity, packageInfo, null, true, new Runnable() { + @Override + public void run() { + getActivity().finish(); + } + }); + + mAdapter = new PermissionsSettingsAdapter(getContext()); + + initializePermissionGroupList(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.settings, container, false); + } + + @Override + public void onResume() { + super.onResume(); + mAppPermissions.refresh(); + + // Also refresh the UI + final int count = mAdapter.getItemCount(); + for (int i = 0; i < count; ++i) { + updatePermissionGroupSetting(i); + } + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (mAppPermissions != null) { + initializeLayout(mAdapter); + bindHeader(mAppPermissions.getPackageInfo()); + } + } + + private void bindHeader(PackageInfo packageInfo) { + Activity activity = getActivity(); + PackageManager pm = activity.getPackageManager(); + ApplicationInfo appInfo = packageInfo.applicationInfo; + CharSequence label = appInfo.loadLabel(pm); + mHeader.setText(label); + } + + private void initializePermissionGroupList() { + final String packageName = mAppPermissions.getPackageInfo().packageName; + List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups(); + List<SettingsAdapter.Setting<AppPermissionGroup>> nonSystemGroups = new ArrayList<>(); + + final int count = groups.size(); + for (int i = 0; i < count; ++i) { + final AppPermissionGroup group = groups.get(i); + if (!Utils.shouldShowPermission(group, packageName)) { + continue; + } + + boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG); + + SettingsAdapter.Setting<AppPermissionGroup> setting = + new SettingsAdapter.Setting<AppPermissionGroup>( + group.getLabel(), + getPermissionGroupIcon(group), + i); + setting.data = group; + + // The UI shows System settings first, then non-system settings + if (isPlatform) { + mAdapter.addSetting(setting); + } else { + nonSystemGroups.add(setting); + } + } + + // Now add the non-system settings to the end of the list + final int nonSystemCount = nonSystemGroups.size(); + for (int i = 0; i < nonSystemCount; ++i) { + final SettingsAdapter.Setting<AppPermissionGroup> setting = nonSystemGroups.get(i); + mAdapter.addSetting(setting); + } + } + + @Override + public void onPause() { + super.onPause(); + logAndClearToggledGroups(); + } + + @Override + public void onClick(WearableListView.ViewHolder view) { + final int index = view.getPosition(); + SettingsAdapter.Setting<AppPermissionGroup> setting = mAdapter.get(index); + final AppPermissionGroup group = setting.data; + + if (group == null) { + Log.e(LOG_TAG, "Error: AppPermissionGroup is null"); + return; + } + + // The way WearableListView is designed, there is no way to avoid this click handler + // Since the policy is fixed, ignore the click as the user is not able to change the state + // of this permission group + if (group.isPolicyFixed()) { + return; + } + + OverlayTouchActivity activity = (OverlayTouchActivity) getActivity(); + if (activity.isObscuredTouch()) { + activity.showOverlayDialog(); + return; + } + + addToggledGroup(group); + + if (LocationUtils.isLocationGroupAndProvider(group.getName(), group.getApp().packageName)) { + LocationUtils.showLocationDialog(getContext(), mAppPermissions.getAppLabel()); + return; + } + + if (!group.areRuntimePermissionsGranted()) { + group.grantRuntimePermissions(false); + } else { + final boolean grantedByDefault = group.hasGrantedByDefaultPermission(); + if (grantedByDefault || (!group.hasRuntimePermission() && !mHasConfirmedRevoke)) { + Intent intent = new Intent(getActivity(), WarningConfirmationActivity.class); + intent.putExtra(WarningConfirmationActivity.EXTRA_WARNING_MESSAGE, + getString(grantedByDefault ? + R.string.system_warning : R.string.old_sdk_deny_warning)); + intent.putExtra(WarningConfirmationActivity.EXTRA_INDEX, index); + startActivityForResult(intent, WARNING_CONFIRMATION_REQUEST); + } else { + group.revokeRuntimePermissions(false); + } + } + + updatePermissionGroupSetting(index); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == WARNING_CONFIRMATION_REQUEST) { + if (resultCode == Activity.RESULT_OK) { + int index = data.getIntExtra(WarningConfirmationActivity.EXTRA_INDEX, -1); + if (index == -1) { + Log.e(LOG_TAG, "Warning confirmation request came back with no index."); + return; + } + + SettingsAdapter.Setting<AppPermissionGroup> setting = mAdapter.get(index); + final AppPermissionGroup group = setting.data; + group.revokeRuntimePermissions(false); + if (!group.hasGrantedByDefaultPermission()) { + mHasConfirmedRevoke = true; + } + + updatePermissionGroupSetting(index); + } + } else { + super.onActivityResult(requestCode, resultCode, data); + } + } + + private void updatePermissionGroupSetting(int index) { + SettingsAdapter.Setting<AppPermissionGroup> setting = mAdapter.get(index); + AppPermissionGroup group = setting.data; + mAdapter.updateSetting( + index, + group.getLabel(), + getPermissionGroupIcon(group), + group); + } + + private void addToggledGroup(AppPermissionGroup group) { + if (mToggledGroups == null) { + mToggledGroups = new ArrayList<>(); + } + // Double toggle is back to initial state. + if (mToggledGroups.contains(group)) { + mToggledGroups.remove(group); + } else { + mToggledGroups.add(group); + } + } + + private void logAndClearToggledGroups() { + if (mToggledGroups != null) { + String packageName = mAppPermissions.getPackageInfo().packageName; + SafetyNetLogger.logPermissionsToggled(packageName, mToggledGroups); + mToggledGroups = null; + } + } + + private int getPermissionGroupIcon(AppPermissionGroup group) { + String groupName = group.getName(); + boolean isEnabled = group.areRuntimePermissionsGranted(); + int resId; + + switch (groupName) { + case Manifest.permission_group.CALENDAR: + resId = isEnabled ? R.drawable.ic_permission_calendar + : R.drawable.ic_permission_calendardisable; + break; + case Manifest.permission_group.CAMERA: + resId = isEnabled ? R.drawable.ic_permission_camera + : R.drawable.ic_permission_cameradisable; + break; + case Manifest.permission_group.CONTACTS: + resId = isEnabled ? R.drawable.ic_permission_contact + : R.drawable.ic_permission_contactdisable; + break; + case Manifest.permission_group.LOCATION: + resId = isEnabled ? R.drawable.ic_permission_location + : R.drawable.ic_permission_locationdisable; + break; + case Manifest.permission_group.MICROPHONE: + resId = isEnabled ? R.drawable.ic_permission_mic + : R.drawable.ic_permission_micdisable; + break; + case Manifest.permission_group.PHONE: + resId = isEnabled ? R.drawable.ic_permission_call + : R.drawable.ic_permission_calldisable; + break; + case Manifest.permission_group.SENSORS: + resId = isEnabled ? R.drawable.ic_permission_sensor + : R.drawable.ic_permission_sensordisable; + break; + case Manifest.permission_group.SMS: + resId = isEnabled ? R.drawable.ic_permission_sms + : R.drawable.ic_permission_smsdisable; + break; + case Manifest.permission_group.STORAGE: + resId = isEnabled ? R.drawable.ic_permission_storage + : R.drawable.ic_permission_storagedisable; + break; + default: + resId = isEnabled ? R.drawable.ic_permission_shield + : R.drawable.ic_permission_shielddisable; + } + + return resId; + } +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java b/src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java new file mode 100644 index 00000000..1c55e1bd --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java @@ -0,0 +1,381 @@ +package com.android.packageinstaller.permission.ui.wear; + +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; + +import com.android.packageinstaller.R; + +public abstract class ConfirmationViewHandler implements + Handler.Callback, + View.OnClickListener, + ViewTreeObserver.OnScrollChangedListener, + ViewTreeObserver.OnGlobalLayoutListener { + private static final String TAG = "ConfirmationViewHandler"; + + public static final int MODE_HORIZONTAL_BUTTONS = 0; + public static final int MODE_VERTICAL_BUTTONS = 1; + + private static final int MSG_SHOW_BUTTON_BAR = 1001; + private static final int MSG_HIDE_BUTTON_BAR = 1002; + private static final long HIDE_ANIM_DURATION = 500; + + private View mRoot; + private TextView mCurrentPageText; + private ImageView mIcon; + private TextView mMessage; + private ScrollView mScrollingContainer; + private ViewGroup mContent; + private ViewGroup mHorizontalButtonBar; + private ViewGroup mVerticalButtonBar; + private Button mVerticalButton1; + private Button mVerticalButton2; + private Button mVerticalButton3; + private View mButtonBarContainer; + + private Context mContext; + + private Handler mHideHandler; + private Interpolator mInterpolator; + private float mButtonBarFloatingHeight; + private ObjectAnimator mButtonBarAnimator; + private float mCurrentTranslation; + private boolean mHiddenBefore; + + // TODO: Move these into a builder + /** In the 2 button layout, this is allow button */ + public abstract void onButton1(); + /** In the 2 button layout, this is deny button */ + public abstract void onButton2(); + public abstract void onButton3(); + public abstract CharSequence getVerticalButton1Text(); + public abstract CharSequence getVerticalButton2Text(); + public abstract CharSequence getVerticalButton3Text(); + public abstract Drawable getVerticalButton1Icon(); + public abstract Drawable getVerticalButton2Icon(); + public abstract Drawable getVerticalButton3Icon(); + public abstract CharSequence getCurrentPageText(); + public abstract Icon getPermissionIcon(); + public abstract CharSequence getMessage(); + + public ConfirmationViewHandler(Context context) { + mContext = context; + } + + public View createView() { + mRoot = LayoutInflater.from(mContext).inflate(R.layout.confirmation_dialog, null); + + mMessage = (TextView) mRoot.findViewById(R.id.message); + mCurrentPageText = (TextView) mRoot.findViewById(R.id.current_page_text); + mIcon = (ImageView) mRoot.findViewById(R.id.icon); + mButtonBarContainer = mRoot.findViewById(R.id.button_bar_container); + mContent = (ViewGroup) mRoot.findViewById(R.id.content); + mScrollingContainer = (ScrollView) mRoot.findViewById(R.id.scrolling_container); + mHorizontalButtonBar = (ViewGroup) mRoot.findViewById(R.id.horizontal_button_bar); + mVerticalButtonBar = (ViewGroup) mRoot.findViewById(R.id.vertical_button_bar); + + Button horizontalAllow = (Button) mRoot.findViewById(R.id.permission_allow_button); + Button horizontalDeny = (Button) mRoot.findViewById(R.id.permission_deny_button); + horizontalAllow.setOnClickListener(this); + horizontalDeny.setOnClickListener(this); + + mVerticalButton1 = (Button) mRoot.findViewById(R.id.vertical_button1); + mVerticalButton2 = (Button) mRoot.findViewById(R.id.vertical_button2); + mVerticalButton3 = (Button) mRoot.findViewById(R.id.vertical_button3); + mVerticalButton1.setOnClickListener(this); + mVerticalButton2.setOnClickListener(this); + mVerticalButton3.setOnClickListener(this); + + mInterpolator = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.fast_out_slow_in); + mButtonBarFloatingHeight = mContext.getResources().getDimension( + R.dimen.conf_diag_floating_height); + mHideHandler = new Handler(Looper.getMainLooper(), this); + + mScrollingContainer.getViewTreeObserver().addOnScrollChangedListener(this); + mRoot.getViewTreeObserver().addOnGlobalLayoutListener(this); + + return mRoot; + } + + /** + * Child class should override this for other modes. Call invalidate() to update the UI to the + * new button mode. + * @return The current mode the layout should use for the buttons + */ + public int getButtonBarMode() { + return MODE_HORIZONTAL_BUTTONS; + } + + public void invalidate() { + CharSequence currentPageText = getCurrentPageText(); + if (!TextUtils.isEmpty(currentPageText)) { + mCurrentPageText.setText(currentPageText); + mCurrentPageText.setVisibility(View.VISIBLE); + } else { + mCurrentPageText.setVisibility(View.GONE); + } + + Icon icon = getPermissionIcon(); + if (icon != null) { + mIcon.setImageIcon(icon); + mIcon.setVisibility(View.VISIBLE); + } else { + mIcon.setVisibility(View.GONE); + } + mMessage.setText(getMessage()); + + switch (getButtonBarMode()) { + case MODE_HORIZONTAL_BUTTONS: + mHorizontalButtonBar.setVisibility(View.VISIBLE); + mVerticalButtonBar.setVisibility(View.GONE); + break; + case MODE_VERTICAL_BUTTONS: + mHorizontalButtonBar.setVisibility(View.GONE); + mVerticalButtonBar.setVisibility(View.VISIBLE); + + mVerticalButton1.setText(getVerticalButton1Text()); + mVerticalButton2.setText(getVerticalButton2Text()); + + mVerticalButton1.setCompoundDrawablesWithIntrinsicBounds( + getVerticalButton1Icon(), null, null, null); + mVerticalButton2.setCompoundDrawablesWithIntrinsicBounds( + getVerticalButton2Icon(), null, null, null); + + CharSequence verticalButton3Text = getVerticalButton3Text(); + if (TextUtils.isEmpty(verticalButton3Text)) { + mVerticalButton3.setVisibility(View.GONE); + } else { + mVerticalButton3.setText(getVerticalButton3Text()); + mVerticalButton3.setCompoundDrawablesWithIntrinsicBounds( + getVerticalButton3Icon(), null, null, null); + } + break; + } + + mScrollingContainer.scrollTo(0, 0); + + mHideHandler.removeMessages(MSG_HIDE_BUTTON_BAR); + mHideHandler.removeMessages(MSG_SHOW_BUTTON_BAR); + } + + @Override + public void onGlobalLayout() { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onGlobalLayout"); + Log.d(TAG, " contentHeight: " + mContent.getHeight()); + } + + if (mButtonBarAnimator != null) { + mButtonBarAnimator.cancel(); + } + + // In order to fake the buttons peeking at the bottom, need to do set the + // padding properly. + if (mContent.getPaddingBottom() != mButtonBarContainer.getHeight()) { + mContent.setPadding(mContent.getPaddingLeft(), mContent.getPaddingTop(), + mContent.getPaddingRight(), mButtonBarContainer.getHeight()); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, " set mContent.PaddingBottom: " + mButtonBarContainer.getHeight()); + } + } + + mButtonBarContainer.setTranslationY(mButtonBarContainer.getHeight()); + + // Give everything a chance to render + mHideHandler.removeMessages(MSG_HIDE_BUTTON_BAR); + mHideHandler.removeMessages(MSG_SHOW_BUTTON_BAR); + mHideHandler.sendEmptyMessageDelayed(MSG_SHOW_BUTTON_BAR, 50); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + switch (id) { + case R.id.permission_allow_button: + case R.id.vertical_button1: + onButton1(); + break; + case R.id.permission_deny_button: + case R.id.vertical_button2: + onButton2(); + break; + case R.id.vertical_button3: + onButton3(); + break; + } + } + + @Override + public boolean handleMessage (Message msg) { + switch (msg.what) { + case MSG_SHOW_BUTTON_BAR: + showButtonBar(); + return true; + case MSG_HIDE_BUTTON_BAR: + hideButtonBar(); + return true; + } + return false; + } + + @Override + public void onScrollChanged () { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onScrollChanged"); + } + mHideHandler.removeMessages(MSG_HIDE_BUTTON_BAR); + hideButtonBar(); + } + + private void showButtonBar() { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "showButtonBar"); + } + + // Setup Button animation. + // pop the button bar back to full height, stop all animation + if (mButtonBarAnimator != null) { + mButtonBarAnimator.cancel(); + } + + // stop any calls to hide the button bar in the future + mHideHandler.removeMessages(MSG_HIDE_BUTTON_BAR); + mHiddenBefore = false; + + // Evaluate the max height the button bar can go + final int screenHeight = mRoot.getHeight(); + final int halfScreenHeight = screenHeight / 2; + final int buttonBarHeight = mButtonBarContainer.getHeight(); + final int contentHeight = mContent.getHeight() - buttonBarHeight; + final int buttonBarMaxHeight = + Math.min(buttonBarHeight, halfScreenHeight); + + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, " screenHeight: " + screenHeight); + Log.d(TAG, " contentHeight: " + contentHeight); + Log.d(TAG, " buttonBarHeight: " + buttonBarHeight); + Log.d(TAG, " buttonBarMaxHeight: " + buttonBarMaxHeight); + } + + mButtonBarContainer.setTranslationZ(mButtonBarFloatingHeight); + + // Only hide the button bar if it is occluding the content or the button bar is bigger than + // half the screen + if (contentHeight > (screenHeight - buttonBarHeight) + || buttonBarHeight > halfScreenHeight) { + mHideHandler.sendEmptyMessageDelayed(MSG_HIDE_BUTTON_BAR, 3000); + } + + generateButtonBarAnimator(buttonBarHeight, + buttonBarHeight - buttonBarMaxHeight, 0, mButtonBarFloatingHeight, 1000); + } + + private void hideButtonBar() { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "hideButtonBar"); + } + + // The desired margin space between the button bar and the bottom of the dialog text + final int topMargin = mContext.getResources().getDimensionPixelSize( + R.dimen.conf_diag_button_container_top_margin); + final int contentHeight = mContent.getHeight() + topMargin; + final int screenHeight = mRoot.getHeight(); + final int buttonBarHeight = mButtonBarContainer.getHeight(); + + final int offset = screenHeight + buttonBarHeight + - contentHeight + Math.max(mScrollingContainer.getScrollY(), 0); + final int translationY = (offset > 0 ? + mButtonBarContainer.getHeight() - offset : mButtonBarContainer.getHeight()); + + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, " topMargin: " + topMargin); + Log.d(TAG, " contentHeight: " + contentHeight); + Log.d(TAG, " screenHeight: " + screenHeight); + Log.d(TAG, " offset: " + offset); + Log.d(TAG, " buttonBarHeight: " + buttonBarHeight); + Log.d(TAG, " mContent.getPaddingBottom(): " + mContent.getPaddingBottom()); + Log.d(TAG, " mScrollingContainer.getScrollY(): " + mScrollingContainer.getScrollY()); + Log.d(TAG, " translationY: " + translationY); + } + + if (!mHiddenBefore || mButtonBarAnimator == null) { + // Remove previous call to MSG_SHOW_BUTTON_BAR if the user scrolled or something before + // the animation got a chance to play + mHideHandler.removeMessages(MSG_SHOW_BUTTON_BAR); + + if(mButtonBarAnimator != null) { + mButtonBarAnimator.cancel(); // stop current animation if there is one playing + } + + // hasn't hidden the bar yet, just hide now to the right height + generateButtonBarAnimator( + mButtonBarContainer.getTranslationY(), translationY, + mButtonBarFloatingHeight, 0, HIDE_ANIM_DURATION); + } else if (mButtonBarAnimator.isRunning()) { + // we are animating the button bar closing, change to animate to the right place + if (Math.abs(mCurrentTranslation - translationY) > 1e-2f) { + mButtonBarAnimator.cancel(); // stop current animation + + if (Math.abs(mButtonBarContainer.getTranslationY() - translationY) > 1e-2f) { + long duration = Math.max((long) ( + (float) HIDE_ANIM_DURATION + * (translationY - mButtonBarContainer.getTranslationY()) + / mButtonBarContainer.getHeight()), 0); + + generateButtonBarAnimator( + mButtonBarContainer.getTranslationY(), translationY, + mButtonBarFloatingHeight, 0, duration); + } else { + mButtonBarContainer.setTranslationY(translationY); + mButtonBarContainer.setTranslationZ(0); + } + } + } else { + // not currently animating, have already hidden, snap to the right offset + mButtonBarContainer.setTranslationY(translationY); + mButtonBarContainer.setTranslationZ(0); + } + + mHiddenBefore = true; + } + + private void generateButtonBarAnimator( + float startY, float endY, float startZ, float endZ, long duration) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "generateButtonBarAnimator"); + Log.d(TAG, " startY: " + startY); + Log.d(TAG, " endY: " + endY); + Log.d(TAG, " startZ: " + startZ); + Log.d(TAG, " endZ: " + endZ); + Log.d(TAG, " duration: " + duration); + } + + mButtonBarAnimator = + ObjectAnimator.ofPropertyValuesHolder( + mButtonBarContainer, + PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, startY, endY), + PropertyValuesHolder.ofFloat(View.TRANSLATION_Z, startZ, endZ)); + mCurrentTranslation = endY; + mButtonBarAnimator.setDuration(duration); + mButtonBarAnimator.setInterpolator(mInterpolator); + mButtonBarAnimator.start(); + } +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java b/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java new file mode 100644 index 00000000..ef7efb28 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java @@ -0,0 +1,234 @@ +/* + * 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.packageinstaller.permission.ui.wear; + +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.support.v7.widget.RecyclerView; +import android.support.wearable.view.WearableListView; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowInsets; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.android.packageinstaller.permission.ui.wear.settings.ViewUtils; +import com.android.packageinstaller.R; + +/** + * Base settings Fragment that shows a title at the top of the page. + */ +public abstract class TitledSettingsFragment extends Fragment implements + View.OnLayoutChangeListener, WearableListView.ClickListener { + + private static final int ITEM_CHANGE_DURATION_MS = 120; + + private static final String TAG = "TitledSettingsFragment"; + private int mInitialHeaderHeight; + + protected TextView mHeader; + protected WearableListView mWheel; + + private int mCharLimitShortTitle; + private int mCharLimitLine; + private int mChinOffset; + + private TextWatcher mHeaderTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable editable) { + adjustHeaderSize(); + } + }; + + private void adjustHeaderTranslation() { + int translation = 0; + if (mWheel.getChildCount() > 0) { + translation = mWheel.getCentralViewTop() - mWheel.getChildAt(0).getTop(); + } + + float newTranslation = Math.min(Math.max(-mInitialHeaderHeight, -translation), 0); + + int position = mWheel.getChildAdapterPosition(mWheel.getChildAt(0)); + if (position == 0 || newTranslation < 0) { + mHeader.setTranslationY(newTranslation); + } + } + + @Override + public void onTopEmptyRegionClick() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCharLimitShortTitle = getResources().getInteger(R.integer.short_title_length); + mCharLimitLine = getResources().getInteger(R.integer.char_limit_per_line); + } + + @Override + public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, + int oldTop, int oldRight, int oldBottom) { + if (view == mHeader) { + mInitialHeaderHeight = bottom - top; + if (ViewUtils.getIsCircular(getContext())) { + // We are adding more margin on circular screens, so we need to account for it and use + // it for hiding the header. + mInitialHeaderHeight += + ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin; + } + } else if (view == mWheel) { + adjustHeaderTranslation(); + } + } + + protected void initializeLayout(RecyclerView.Adapter adapter) { + View v = getView(); + mWheel = (WearableListView) v.findViewById(R.id.wheel); + + mHeader = (TextView) v.findViewById(R.id.header); + mHeader.addOnLayoutChangeListener(this); + mHeader.addTextChangedListener(mHeaderTextWatcher); + + mWheel.setAdapter(adapter); + mWheel.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + adjustHeaderTranslation(); + } + }); + mWheel.setClickListener(this); + mWheel.addOnLayoutChangeListener(this); + + // Decrease item change animation duration to approximately half of the default duration. + RecyclerView.ItemAnimator itemAnimator = mWheel.getItemAnimator(); + itemAnimator.setChangeDuration(ITEM_CHANGE_DURATION_MS); + + adjustHeaderSize(); + + positionOnCircular(getContext(), mHeader, mWheel); + } + + public void positionOnCircular(Context context, View header, final ViewGroup wheel) { + if (ViewUtils.getIsCircular(context)) { + FrameLayout.LayoutParams params = + (FrameLayout.LayoutParams) header.getLayoutParams(); + params.topMargin = (int) context.getResources().getDimension( + R.dimen.settings_header_top_margin_circular); + // Note that the margins are made symmetrical here. Since they're symmetrical we choose + // the smaller value to maximize usable width. + final int margin = (int) Math.min(context.getResources().getDimension( + R.dimen.round_content_padding_left), context.getResources().getDimension( + R.dimen.round_content_padding_right)); + params.leftMargin = margin; + params.rightMargin = margin; + params.gravity = Gravity.CENTER_HORIZONTAL; + header.setLayoutParams(params); + + if (header instanceof TextView) { + ((TextView) header).setGravity(Gravity.CENTER); + } + + final int leftPadding = (int) context.getResources().getDimension( + R.dimen.round_content_padding_left); + final int rightPadding = (int) context.getResources().getDimension( + R.dimen.round_content_padding_right); + final int topPadding = (int) context.getResources().getDimension( + R.dimen.settings_wearable_list_view_vertical_padding_round); + final int bottomPadding = (int) context.getResources().getDimension( + R.dimen.settings_wearable_list_view_vertical_padding_round); + wheel.setPadding(leftPadding, topPadding, rightPadding, mChinOffset + bottomPadding); + wheel.setClipToPadding(false); + + wheel.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { + mChinOffset = insets.getSystemWindowInsetBottom(); + wheel.setPadding(leftPadding, topPadding, rightPadding, + mChinOffset + bottomPadding); + // This listener is invoked after each time we navigate to SettingsActivity and + // it keeps adding padding. We need to disable it after the first update. + v.setOnApplyWindowInsetsListener(null); + return insets.consumeSystemWindowInsets(); + } + }); + } else { + int leftPadding = (int) context.getResources().getDimension( + R.dimen.content_padding_left); + wheel.setPadding(leftPadding, wheel.getPaddingTop(), wheel.getPaddingRight(), + wheel.getPaddingBottom()); + } + } + + private void adjustHeaderSize() { + int length = mHeader.length(); + + if (length <= mCharLimitShortTitle) { + mHeader.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize( + R.dimen.setting_short_header_text_size)); + } else { + mHeader.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize( + R.dimen.setting_long_header_text_size)); + } + + boolean singleLine = length <= mCharLimitLine; + + float height = getResources().getDimension(R.dimen.settings_header_base_height); + if (!singleLine) { + height += getResources().getDimension(R.dimen.setting_header_extra_line_height); + } + mHeader.setMinHeight((int) height); + + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mHeader.getLayoutParams(); + final Context context = getContext(); + if (!singleLine) { + // Make the top margin a little bit smaller so there is more space for the title. + if (ViewUtils.getIsCircular(context)) { + params.topMargin = getResources().getDimensionPixelSize( + R.dimen.settings_header_top_margin_circular_multiline); + } else { + params.topMargin = getResources().getDimensionPixelSize( + R.dimen.settings_header_top_margin_multiline); + } + } else { + if (ViewUtils.getIsCircular(context)) { + params.topMargin = getResources().getDimensionPixelSize( + R.dimen.settings_header_top_margin_circular); + } else { + params.topMargin = getResources().getDimensionPixelSize( + R.dimen.settings_header_top_margin); + } + } + mHeader.setLayoutParams(params); + } +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/WarningConfirmationActivity.java b/src/com/android/packageinstaller/permission/ui/wear/WarningConfirmationActivity.java new file mode 100644 index 00000000..03713419 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/WarningConfirmationActivity.java @@ -0,0 +1,118 @@ +/* +* 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.packageinstaller.permission.ui.wear; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.os.Bundle; + +import com.android.packageinstaller.R; + +public final class WarningConfirmationActivity extends Activity { + public final static String EXTRA_WARNING_MESSAGE = "EXTRA_WARNING_MESSAGE"; + // Saved index that will be returned in the onActivityResult() callback + public final static String EXTRA_INDEX = "EXTRA_INDEX"; + + private ConfirmationViewHandler mViewHandler; + private String mMessage; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mMessage = getIntent().getStringExtra(EXTRA_WARNING_MESSAGE); + + mViewHandler = new ConfirmationViewHandler(this) { + @Override // ConfirmationViewHandler + public int getButtonBarMode() { + return MODE_VERTICAL_BUTTONS; + } + + @Override + public void onButton1() { + setResultAndFinish(Activity.RESULT_CANCELED); + } + + @Override + public void onButton2() { + setResultAndFinish(Activity.RESULT_OK); + } + + @Override + public void onButton3() { + // no-op + } + + @Override + public CharSequence getVerticalButton1Text() { + return getString(R.string.cancel); + } + + @Override + public CharSequence getVerticalButton2Text() { + return getString(R.string.grant_dialog_button_deny); + } + + @Override + public CharSequence getVerticalButton3Text() { + return null; + } + + @Override + public Drawable getVerticalButton1Icon() { + return getDrawable(R.drawable.cancel_button); + } + + @Override + public Drawable getVerticalButton2Icon() { + return getDrawable(R.drawable.confirm_button); + } + + @Override + public Drawable getVerticalButton3Icon() { + return null; + } + + @Override + public CharSequence getCurrentPageText() { + return null; + } + + @Override + public Icon getPermissionIcon() { + return null; + } + + @Override + public CharSequence getMessage() { + return mMessage; + } + }; + + setContentView(mViewHandler.createView()); + mViewHandler.invalidate(); + } + + private void setResultAndFinish(int result) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_INDEX, getIntent().getIntExtra(EXTRA_INDEX, -1)); + setResult(result, intent); + finish(); + } +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/settings/ExtendedOnCenterProximityListener.java b/src/com/android/packageinstaller/permission/ui/wear/settings/ExtendedOnCenterProximityListener.java new file mode 100644 index 00000000..02c203b3 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/settings/ExtendedOnCenterProximityListener.java @@ -0,0 +1,30 @@ +/* + * 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.packageinstaller.permission.ui.wear.settings; + +import android.support.wearable.view.WearableListView; + +public interface ExtendedOnCenterProximityListener + extends WearableListView.OnCenterProximityListener { + float getProximityMinValue(); + + float getProximityMaxValue(); + + float getCurrentProximityValue(); + + void setScalingAnimatorValue(float value); +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/settings/ExtendedViewHolder.java b/src/com/android/packageinstaller/permission/ui/wear/settings/ExtendedViewHolder.java new file mode 100644 index 00000000..6b725419 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/settings/ExtendedViewHolder.java @@ -0,0 +1,84 @@ +/* + * 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.packageinstaller.permission.ui.wear.settings; + +import android.animation.ObjectAnimator; +import android.support.wearable.view.WearableListView; +import android.view.View; + + +public class ExtendedViewHolder extends WearableListView.ViewHolder { + public static final long DEFAULT_ANIMATION_DURATION = 150; + + private ObjectAnimator mScalingUpAnimator; + + private ObjectAnimator mScalingDownAnimator; + + private float mMinValue; + + private float mMaxValue; + + public ExtendedViewHolder(View itemView) { + super(itemView); + if (itemView instanceof ExtendedOnCenterProximityListener) { + ExtendedOnCenterProximityListener item = + (ExtendedOnCenterProximityListener) itemView; + mMinValue = item.getProximityMinValue(); + item.setScalingAnimatorValue(mMinValue); + mMaxValue = item.getProximityMaxValue(); + mScalingUpAnimator = ObjectAnimator.ofFloat(item, "scalingAnimatorValue", mMinValue, + mMaxValue); + mScalingUpAnimator.setDuration(DEFAULT_ANIMATION_DURATION); + mScalingDownAnimator = ObjectAnimator.ofFloat(item, "scalingAnimatorValue", + mMaxValue, mMinValue); + mScalingDownAnimator.setDuration(DEFAULT_ANIMATION_DURATION); + } + } + + public void onCenterProximity(boolean isCentralItem, boolean animate) { + if (!(itemView instanceof ExtendedOnCenterProximityListener)) { + return; + } + ExtendedOnCenterProximityListener item = (ExtendedOnCenterProximityListener) itemView; + if (isCentralItem) { + if (animate) { + mScalingDownAnimator.cancel(); + if (!mScalingUpAnimator.isRunning()) { + mScalingUpAnimator.setFloatValues(item.getCurrentProximityValue(), + mMaxValue); + mScalingUpAnimator.start(); + } + } else { + mScalingUpAnimator.cancel(); + item.setScalingAnimatorValue(item.getProximityMaxValue()); + } + } else { + mScalingUpAnimator.cancel(); + if (animate) { + if (!mScalingDownAnimator.isRunning()) { + mScalingDownAnimator.setFloatValues(item.getCurrentProximityValue(), + mMinValue); + mScalingDownAnimator.start(); + } + } else { + mScalingDownAnimator.cancel(); + item.setScalingAnimatorValue(item.getProximityMinValue()); + } + } + super.onCenterProximity(isCentralItem, animate); + } +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/settings/PermissionsSettingsAdapter.java b/src/com/android/packageinstaller/permission/ui/wear/settings/PermissionsSettingsAdapter.java new file mode 100644 index 00000000..0e0adcbb --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/settings/PermissionsSettingsAdapter.java @@ -0,0 +1,101 @@ +/* + * 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.packageinstaller.permission.ui.wear.settings; + +import android.content.Context; +import android.content.res.Resources; +import android.support.wearable.view.WearableListView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.model.AppPermissionGroup; + +public final class PermissionsSettingsAdapter extends SettingsAdapter<AppPermissionGroup> { + private Resources mRes; + + public PermissionsSettingsAdapter(Context context) { + super(context, R.layout.permissions_settings_item); + mRes = context.getResources(); + } + + @Override + public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new PermissionsViewHolder(new PermissionsSettingsItem(parent.getContext())); + } + + @Override + public void onBindViewHolder(WearableListView.ViewHolder holder, int position) { + super.onBindViewHolder(holder, position); + PermissionsViewHolder viewHolder = (PermissionsViewHolder) holder; + AppPermissionGroup group = get(position).data; + + if (group.isPolicyFixed()) { + viewHolder.imageView.setEnabled(false); + viewHolder.textView.setEnabled(false); + viewHolder.state.setEnabled(false); + viewHolder.state.setText( + mRes.getString(R.string.permission_summary_enforced_by_policy)); + } else { + viewHolder.imageView.setEnabled(true); + viewHolder.textView.setEnabled(true); + viewHolder.state.setEnabled(true); + + if (group.areRuntimePermissionsGranted()) { + viewHolder.state.setText(R.string.generic_enabled); + } else { + viewHolder.state.setText(R.string.generic_disabled); + } + } + } + + private static final class PermissionsViewHolder extends SettingsAdapter.SettingsItemHolder { + public final TextView state; + + public PermissionsViewHolder(View view) { + super(view); + state = (TextView) view.findViewById(R.id.state); + } + } + + private class PermissionsSettingsItem extends SettingsItem { + private final TextView mState; + private final float mCenteredAlpha = 1.0f; + private final float mNonCenteredAlpha = 0.5f; + + public PermissionsSettingsItem (Context context) { + super(context); + mState = (TextView) findViewById(R.id.state); + } + + @Override + public void onCenterPosition(boolean animate) { + mImage.setAlpha(mImage.isEnabled() ? mCenteredAlpha : mNonCenteredAlpha); + mText.setAlpha(mText.isEnabled() ? mCenteredAlpha : mNonCenteredAlpha); + mState.setAlpha(mState.isEnabled() ? mCenteredAlpha : mNonCenteredAlpha); + } + + @Override + public void onNonCenterPosition(boolean animate) { + mImage.setAlpha(mNonCenteredAlpha); + mText.setAlpha(mNonCenteredAlpha); + mState.setAlpha(mNonCenteredAlpha); + } + } +} + diff --git a/src/com/android/packageinstaller/permission/ui/wear/settings/SettingsAdapter.java b/src/com/android/packageinstaller/permission/ui/wear/settings/SettingsAdapter.java new file mode 100644 index 00000000..baf1a2b4 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/settings/SettingsAdapter.java @@ -0,0 +1,276 @@ +/* + * 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.packageinstaller.permission.ui.wear.settings; + +import android.content.Context; +import android.support.wearable.view.CircledImageView; +import android.support.wearable.view.WearableListView; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.android.packageinstaller.R; + +import java.util.ArrayList; + +/** + * Common adapter for settings views. Maintains a list of 'Settings', consisting of a name, + * icon and optional activity-specific data. + */ +public class SettingsAdapter<T> extends WearableListView.Adapter { + private static final String TAG = "SettingsAdapter"; + private final Context mContext; + + public static final class Setting<S> { + public static final int ID_INVALID = -1; + + public final int id; + public int nameResourceId; + public CharSequence name; + public int iconResource; + public boolean inProgress; + public S data; + + public Setting(CharSequence name, int iconResource, S data) { + this(name, iconResource, data, ID_INVALID); + } + + public Setting(CharSequence name, int iconResource, S data, int id) { + this.name = name; + this.iconResource = iconResource; + this.data = data; + this.inProgress = false; + this.id = id; + } + + public Setting(int nameResource, int iconResource, S data, int id) { + this.nameResourceId = nameResource; + this.iconResource = iconResource; + this.data = data; + this.inProgress = false; + this.id = id; + } + + public Setting(int nameResource, int iconResource, int id) { + this.nameResourceId = nameResource; + this.iconResource = iconResource; + this.data = null; + this.inProgress = false; + this.id = id; + } + + public Setting(CharSequence name, int iconResource, int id) { + this(name, iconResource, null, id); + } + + } + + private final int mItemLayoutId; + private final float mDefaultCircleRadiusPercent; + private final float mSelectedCircleRadiusPercent; + + protected ArrayList<Setting<T>> mSettings = new ArrayList<Setting<T>>(); + + public SettingsAdapter(Context context, int itemLayoutId) { + mContext = context; + mItemLayoutId = itemLayoutId; + mDefaultCircleRadiusPercent = context.getResources().getFraction( + R.dimen.default_settings_circle_radius_percent, 1, 1); + mSelectedCircleRadiusPercent = context.getResources().getFraction( + R.dimen.selected_settings_circle_radius_percent, 1, 1); + } + + @Override + public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new SettingsItemHolder(new SettingsItem(parent.getContext())); + } + + @Override + public void onBindViewHolder(WearableListView.ViewHolder holder, int position) { + Setting<T> setting = mSettings.get(position); + if (setting.iconResource == -1) { + ((SettingsItemHolder) holder).imageView.setVisibility(View.GONE); + } else { + ((SettingsItemHolder) holder).imageView.setVisibility(View.VISIBLE); + ((SettingsItemHolder) holder).imageView.setImageResource( + mSettings.get(position).iconResource); + } + Log.d(TAG, "onBindViewHolder " + setting.name + " " + setting.id + " " + setting + .nameResourceId); + if (setting.name == null && setting.nameResourceId != 0) { + setting.name = mContext.getString(setting.nameResourceId); + } + ((SettingsItemHolder) holder).textView.setText(setting.name); + } + + @Override + public int getItemCount() { + return mSettings.size(); + } + + public void addSetting(CharSequence name, int iconResource) { + addSetting(name, iconResource, null); + } + + public void addSetting(CharSequence name, int iconResource, T intent) { + addSetting(mSettings.size(), name, iconResource, intent); + } + + public void addSetting(int index, CharSequence name, int iconResource, T intent) { + addSetting(Setting.ID_INVALID, index, name, iconResource, intent); + } + + public void addSetting(int id, int index, CharSequence name, int iconResource, T intent) { + mSettings.add(index, new Setting<T>(name, iconResource, intent, id)); + notifyItemInserted(index); + } + + public void addSettingDontNotify(Setting<T> setting) { + mSettings.add(setting); + } + + public void addSetting(Setting<T> setting) { + mSettings.add(setting); + notifyItemInserted(mSettings.size() - 1); + } + + public void addSetting(int index, Setting<T> setting) { + mSettings.add(index, setting); + notifyItemInserted(index); + } + + /** + * Returns the index of the setting in the adapter based on the ID supplied when it was + * originally added. + * @param id the setting's id + * @return index in the adapter of the setting. -1 if not found. + */ + public int findSetting(int id) { + for (int i = mSettings.size() - 1; i >= 0; --i) { + Setting setting = mSettings.get(i); + + if (setting.id == id) { + return i; + } + } + + return -1; + } + + /** + * Removes a setting at the given index. + * @param index the index of the setting to be removed + */ + public void removeSetting(int index) { + mSettings.remove(index); + notifyDataSetChanged(); + } + + public void clearSettings() { + mSettings.clear(); + notifyDataSetChanged(); + } + + /** + * Updates a setting in place. + * @param index the index of the setting + * @param name the updated setting name + * @param iconResource the update setting icon + * @param intent the updated intent for the setting + */ + public void updateSetting(int index, CharSequence name, int iconResource, T intent) { + Setting<T> setting = mSettings.get(index); + setting.iconResource = iconResource; + setting.name = name; + setting.data = intent; + notifyItemChanged(index); + } + + public Setting<T> get(int position) { + return mSettings.get(position); + } + + protected static class SettingsItemHolder extends ExtendedViewHolder { + public final CircledImageView imageView; + public final TextView textView; + + public SettingsItemHolder(View itemView) { + super(itemView); + + imageView = ((CircledImageView) itemView.findViewById(R.id.image)); + textView = ((TextView) itemView.findViewById(R.id.text)); + } + } + + protected class SettingsItem extends FrameLayout implements ExtendedOnCenterProximityListener { + + protected final CircledImageView mImage; + protected final TextView mText; + + public SettingsItem(Context context) { + super(context); + View view = View.inflate(context, mItemLayoutId, null); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT); + params.gravity = Gravity.CENTER_VERTICAL; + addView(view, params); + mImage = (CircledImageView) findViewById(R.id.image); + mText = (TextView) findViewById(R.id.text); + } + + @Override + public float getProximityMinValue() { + return mDefaultCircleRadiusPercent; + } + + @Override + public float getProximityMaxValue() { + return mSelectedCircleRadiusPercent; + } + + @Override + public float getCurrentProximityValue() { + return mImage.getCircleRadiusPressedPercent(); + } + + @Override + public void setScalingAnimatorValue(float value) { + mImage.setCircleRadiusPercent(value); + mImage.setCircleRadiusPressedPercent(value); + } + + @Override + public void onCenterPosition(boolean animate) { + mImage.setAlpha(1f); + mText.setAlpha(1f); + } + + @Override + public void onNonCenterPosition(boolean animate) { + mImage.setAlpha(0.5f); + mText.setAlpha(0.5f); + } + + TextView getTextView() { + return mText; + } + } +} diff --git a/src/com/android/packageinstaller/permission/ui/wear/settings/ViewUtils.java b/src/com/android/packageinstaller/permission/ui/wear/settings/ViewUtils.java new file mode 100644 index 00000000..cf1c0fd0 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/settings/ViewUtils.java @@ -0,0 +1,48 @@ +/* + * 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.packageinstaller.permission.ui.wear.settings; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +/** + * Utility to determine screen shape + */ +public class ViewUtils { + + public static boolean getIsCircular(Context context) { + return context.getResources().getConfiguration().isScreenRound(); + } + + /** + * Set the given {@code view} and all descendants to the given {@code enabled} state. + * + * @param view the parent view of a subtree of components whose enabled state must be set + * @param enabled the new enabled state of the subtree of components + */ + public static void setEnabled(View view, boolean enabled) { + view.setEnabled(enabled); + + if (view instanceof ViewGroup) { + final ViewGroup viewGroup = (ViewGroup) view; + for (int i = 0; i < viewGroup.getChildCount(); i++) { + setEnabled(viewGroup.getChildAt(i), enabled); + } + } + } +} diff --git a/src/com/android/packageinstaller/permission/utils/Utils.java b/src/com/android/packageinstaller/permission/utils/Utils.java index 2940a729..21830378 100644 --- a/src/com/android/packageinstaller/permission/utils/Utils.java +++ b/src/com/android/packageinstaller/permission/utils/Utils.java @@ -31,8 +31,11 @@ import android.util.Log; import android.util.TypedValue; import com.android.packageinstaller.permission.model.AppPermissionGroup; +import com.android.packageinstaller.permission.model.AppPermissions; import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; +import java.util.List; + public class Utils { private static final String LOG_TAG = "Utils"; @@ -127,14 +130,20 @@ public class Utils { return launcherPkgs; } + public static List<ApplicationInfo> getAllInstalledApplications(Context context) { + return context.getPackageManager().getInstalledApplications(0); + } + public static boolean isSystem(PermissionApp app, ArraySet<String> launcherPkgs) { - ApplicationInfo info = app.getAppInfo(); - return info.isSystemApp() && (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0 - && !launcherPkgs.contains(info.packageName); + return isSystem(app.getAppInfo(), launcherPkgs); } - public static boolean isTelevision(Context context) { - int uiMode = context.getResources().getConfiguration().uiMode; - return (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION; + public static boolean isSystem(AppPermissions app, ArraySet<String> launcherPkgs) { + return isSystem(app.getPackageInfo().applicationInfo, launcherPkgs); + } + + public static boolean isSystem(ApplicationInfo info, ArraySet<String> launcherPkgs) { + return info.isSystemApp() && (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0 + && !launcherPkgs.contains(info.packageName); } } diff --git a/src/com/android/packageinstaller/wear/WearPackageIconProvider.java b/src/com/android/packageinstaller/wear/WearPackageIconProvider.java new file mode 100644 index 00000000..02b9d298 --- /dev/null +++ b/src/com/android/packageinstaller/wear/WearPackageIconProvider.java @@ -0,0 +1,202 @@ +/* + * 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.packageinstaller.wear; + +import android.annotation.TargetApi; +import android.app.ActivityManager; +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.net.Uri; +import android.os.Binder; +import android.os.Build; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; + +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +public class WearPackageIconProvider extends ContentProvider { + private static final String TAG = "WearPackageIconProvider"; + public static final String AUTHORITY = "com.google.android.packageinstaller.wear.provider"; + + private static final String REQUIRED_PERMISSION = + "com.google.android.permission.INSTALL_WEARABLE_PACKAGES"; + + /** MIME types. */ + public static final String ICON_TYPE = "vnd.android.cursor.item/cw_package_icon"; + + @Override + public boolean onCreate() { + return true; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + throw new UnsupportedOperationException("Query is not supported."); + } + + @Override + public String getType(Uri uri) { + if (uri == null) { + throw new IllegalArgumentException("URI passed in is null."); + } + + if (AUTHORITY.equals(uri.getEncodedAuthority())) { + return ICON_TYPE; + } + return null; + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException("Insert is not supported."); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + if (uri == null) { + throw new IllegalArgumentException("URI passed in is null."); + } + + enforcePermissions(uri); + + if (ICON_TYPE.equals(getType(uri))) { + final File file = WearPackageUtil.getIconFile( + this.getContext().getApplicationContext(), getPackageNameFromUri(uri)); + if (file != null) { + file.delete(); + } + } + + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException("Update is not supported."); + } + + @Override + public ParcelFileDescriptor openFile( + Uri uri, @SuppressWarnings("unused") String mode) throws FileNotFoundException { + if (uri == null) { + throw new IllegalArgumentException("URI passed in is null."); + } + + enforcePermissions(uri); + + if (ICON_TYPE.equals(getType(uri))) { + final File file = WearPackageUtil.getIconFile( + this.getContext().getApplicationContext(), getPackageNameFromUri(uri)); + if (file != null) { + return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); + } + } + return null; + } + + public static Uri getUriForPackage(final String packageName) { + return Uri.parse("content://" + AUTHORITY + "/icons/" + packageName + ".icon"); + } + + private String getPackageNameFromUri(Uri uri) { + if (uri == null) { + return null; + } + List<String> pathSegments = uri.getPathSegments(); + String packageName = pathSegments.get(pathSegments.size() - 1); + + if (packageName.endsWith(".icon")) { + packageName = packageName.substring(0, packageName.lastIndexOf(".")); + } + return packageName; + } + + /** + * Make sure the calling app is either a system app or the same app or has the right permission. + * @throws SecurityException if the caller has insufficient permissions. + */ + @TargetApi(Build.VERSION_CODES.BASE_1_1) + private void enforcePermissions(Uri uri) { + // Redo some of the permission check in {@link ContentProvider}. Just add an extra check to + // allow System process to access this provider. + Context context = getContext(); + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final int myUid = android.os.Process.myUid(); + + if (uid == myUid || isSystemApp(context, pid)) { + return; + } + + if (context.checkPermission(REQUIRED_PERMISSION, pid, uid) == PERMISSION_GRANTED) { + return; + } + + // last chance, check against any uri grants + if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) + == PERMISSION_GRANTED) { + return; + } + + throw new SecurityException("Permission Denial: reading " + + getClass().getName() + " uri " + uri + " from pid=" + pid + + ", uid=" + uid); + } + + /** + * From the pid of the calling process, figure out whether this is a system app or not. We do + * this by checking the application information corresponding to the pid and then checking if + * FLAG_SYSTEM is set. + */ + @TargetApi(Build.VERSION_CODES.CUPCAKE) + private boolean isSystemApp(Context context, int pid) { + // Get the Activity Manager Object + ActivityManager aManager = + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + // Get the list of running Applications + List<ActivityManager.RunningAppProcessInfo> rapInfoList = + aManager.getRunningAppProcesses(); + for (ActivityManager.RunningAppProcessInfo rapInfo : rapInfoList) { + if (rapInfo.pid == pid) { + try { + PackageInfo pkgInfo = context.getPackageManager().getPackageInfo( + rapInfo.pkgList[0], 0); + if (pkgInfo != null && pkgInfo.applicationInfo != null && + (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + Log.d(TAG, pid + " is a system app."); + return true; + } + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Could not find package information.", e); + return false; + } + } + } + return false; + } +} diff --git a/src/com/android/packageinstaller/wear/WearPackageInstallerService.java b/src/com/android/packageinstaller/wear/WearPackageInstallerService.java new file mode 100644 index 00000000..6dc5aa70 --- /dev/null +++ b/src/com/android/packageinstaller/wear/WearPackageInstallerService.java @@ -0,0 +1,636 @@ +/* + * 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.packageinstaller.wear; + +import android.annotation.Nullable; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.FeatureInfo; +import android.content.pm.IPackageDeleteObserver; +import android.content.pm.IPackageInstallObserver; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.os.PowerManager; +import android.os.Process; +import android.text.TextUtils; +import android.util.Log; + +import com.android.packageinstaller.DeviceUtils; +import com.android.packageinstaller.PackageUtil; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Service that will install/uninstall packages. It will check for permissions and features as well. + * + * ----------- + * + * Debugging information: + * + * Install Action example: + * adb shell am startservice -a com.android.packageinstaller.wear.INSTALL_PACKAGE \ + * -t vnd.android.cursor.item/wearable_apk \ + * -d content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/wearable/com.google.android.gms/apk \ + * --es android.intent.extra.INSTALLER_PACKAGE_NAME com.google.android.gms \ + * --ez com.google.android.clockwork.EXTRA_CHECK_PERMS false \ + * --eu com.google.android.clockwork.EXTRA_PERM_URI content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/permissions \ + * com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService + * + * Retry GMS: + * adb shell am startservice -a com.android.packageinstaller.wear.RETRY_GMS \ + * com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService + */ +public class WearPackageInstallerService extends Service { + private static final String TAG = "WearPkgInstallerService"; + + private static final String KEY_PERM_URI = + "com.google.android.clockwork.EXTRA_PERM_URI"; + private static final String KEY_CHECK_PERMS = + "com.google.android.clockwork.EXTRA_CHECK_PERMS"; + private static final String KEY_SKIP_IF_SAME_VERSION = + "com.google.android.clockwork.EXTRA_SKIP_IF_SAME_VERSION"; + private static final String KEY_COMPRESSION_ALG = + "com.google.android.clockwork.EXTRA_KEY_COMPRESSION_ALG"; + private static final String KEY_COMPANION_SDK_VERSION = + "com.google.android.clockwork.EXTRA_KEY_COMPANION_SDK_VERSION"; + private static final String KEY_COMPANION_DEVICE_VERSION = + "com.google.android.clockwork.EXTRA_KEY_COMPANION_DEVICE_VERSION"; + + private static final String KEY_PACKAGE_NAME = + "com.google.android.clockwork.EXTRA_PACKAGE_NAME"; + private static final String KEY_APP_LABEL = "com.google.android.clockwork.EXTRA_APP_LABEL"; + private static final String KEY_APP_ICON_URI = + "com.google.android.clockwork.EXTRA_APP_ICON_URI"; + private static final String KEY_PERMS_LIST = "com.google.android.clockwork.EXTRA_PERMS_LIST"; + private static final String KEY_HAS_LAUNCHER = + "com.google.android.clockwork.EXTRA_HAS_LAUNCHER"; + + private static final String HOME_APP_PACKAGE_NAME = "com.google.android.wearable.app"; + private static final String SHOW_PERMS_SERVICE_CLASS = + "com.google.android.clockwork.packagemanager.ShowPermsService"; + + private static final String ASSET_URI_ARG = "assetUri"; + private static final String PACKAGE_NAME_ARG = "packageName"; + private static final String PERM_URI_ARG = "permUri"; + private static final String START_ID_ARG = "startId"; + private static final String CHECK_PERMS_ARG = "checkPerms"; + private static final String SKIP_IF_SAME_VERSION_ARG = "skipIfSameVersion"; + private static final String COMPRESSION_ALG = "compressionAlg"; + private static final String COMPANION_SDK_VERSION = "companionSdkVersion"; + private static final String COMPANION_DEVICE_VERSION = "companionDeviceVersion"; + + /** + * Normally sent by the Play store (See http://go/playstore-gms_updated), we instead + * broadcast, ourselves. http://b/17387718 + */ + private static final String GMS_UPDATED_BROADCAST = "com.google.android.gms.GMS_UPDATED"; + public static final String GMS_PACKAGE_NAME = "com.google.android.gms"; + + private final int START_INSTALL = 1; + private final int START_UNINSTALL = 2; + + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + + public void handleMessage(Message msg) { + switch (msg.what) { + case START_INSTALL: + installPackage(msg.getData().getString(PACKAGE_NAME_ARG), + (Uri) msg.getData().getParcelable(ASSET_URI_ARG), + (Uri) msg.getData().getParcelable(PERM_URI_ARG), + msg.getData().getInt(START_ID_ARG), + msg.getData().getBoolean(CHECK_PERMS_ARG), + msg.getData().getBoolean(SKIP_IF_SAME_VERSION_ARG), + msg.getData().getString(COMPRESSION_ALG), + msg.getData().getInt(COMPANION_SDK_VERSION), + msg.getData().getInt(COMPANION_DEVICE_VERSION)); + break; + case START_UNINSTALL: + uninstallPackage(msg.getData().getString(PACKAGE_NAME_ARG), + msg.getData().getInt(START_ID_ARG)); + break; + } + } + } + private ServiceHandler mServiceHandler; + + private static volatile PowerManager.WakeLock lockStatic = null; + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + HandlerThread thread = new HandlerThread("PackageInstallerThread", + Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + + mServiceHandler = new ServiceHandler(thread.getLooper()); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (!DeviceUtils.isWear(this)) { + Log.w(TAG, "Not running on wearable"); + return START_NOT_STICKY; + } + PowerManager.WakeLock lock = getLock(this.getApplicationContext()); + if (!lock.isHeld()) { + lock.acquire(); + } + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Got install/uninstall request " + intent); + } + if (intent != null) { + if (Intent.ACTION_INSTALL_PACKAGE.equals(intent.getAction())) { + final Message msg = mServiceHandler.obtainMessage(START_INSTALL); + final Bundle startInstallArgs = new Bundle(); + startInstallArgs.putParcelable(ASSET_URI_ARG, intent.getData()); + startInstallArgs.putString(PACKAGE_NAME_ARG, intent.getStringExtra( + Intent.EXTRA_INSTALLER_PACKAGE_NAME)); + startInstallArgs.putInt(START_ID_ARG, startId); + Uri permUri = intent.getParcelableExtra(KEY_PERM_URI); + startInstallArgs.putParcelable(PERM_URI_ARG, permUri); + startInstallArgs.putBoolean(CHECK_PERMS_ARG, + intent.getBooleanExtra(KEY_CHECK_PERMS, true)); + startInstallArgs.putBoolean(SKIP_IF_SAME_VERSION_ARG, + intent.getBooleanExtra(KEY_SKIP_IF_SAME_VERSION, false)); + startInstallArgs.putString(COMPRESSION_ALG, + intent.getStringExtra(KEY_COMPRESSION_ALG)); + startInstallArgs.putInt(COMPANION_SDK_VERSION, + intent.getIntExtra(KEY_COMPANION_SDK_VERSION, 0)); + startInstallArgs.putInt(COMPANION_DEVICE_VERSION, + intent.getIntExtra(KEY_COMPANION_DEVICE_VERSION, 0)); + msg.setData(startInstallArgs); + mServiceHandler.sendMessage(msg); + } else if (Intent.ACTION_UNINSTALL_PACKAGE.equals(intent.getAction())) { + Message msg = mServiceHandler.obtainMessage(START_UNINSTALL); + Bundle startUninstallArgs = new Bundle(); + startUninstallArgs.putString(PACKAGE_NAME_ARG, intent.getStringExtra( + Intent.EXTRA_INSTALLER_PACKAGE_NAME)); + startUninstallArgs.putInt(START_ID_ARG, startId); + msg.setData(startUninstallArgs); + mServiceHandler.sendMessage(msg); + } + } + return START_NOT_STICKY; + } + + private void installPackage(String packageName, Uri packageUri, Uri permUri, int startId, + boolean checkPerms, boolean skipIfSameVersion, @Nullable String compressionAlg, + int companionSdkVersion, int companionDeviceVersion) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Installing package: " + packageName + ", packageUri: " + packageUri + + ",permUri: " + permUri + ", startId: " + startId + ", checkPerms: " + + checkPerms + ", skipIfSameVersion: " + skipIfSameVersion + + ", compressionAlg: " + compressionAlg + ", companionSdkVersion: " + + companionSdkVersion + ", companionDeviceVersion: " + companionDeviceVersion); + } + final PackageManager pm = getPackageManager(); + File tempFile = null; + int installFlags = 0; + PowerManager.WakeLock lock = getLock(this.getApplicationContext()); + boolean messageSent = false; + try { + PackageInfo existingPkgInfo = null; + try { + existingPkgInfo = pm.getPackageInfo(packageName, + PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS); + if(existingPkgInfo != null) { + installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; + } + } catch (PackageManager.NameNotFoundException e) { + // Ignore this exception. We could not find the package, will treat as a new + // installation. + } + if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Replacing package:" + packageName); + } + } + ParcelFileDescriptor parcelFd = getContentResolver() + .openFileDescriptor(packageUri, "r"); + tempFile = WearPackageUtil.getFileFromFd(WearPackageInstallerService.this, + parcelFd, packageName, compressionAlg); + if (tempFile == null) { + Log.e(TAG, "Could not create a temp file from FD for " + packageName); + return; + } + PackageParser.Package pkg = PackageUtil.getPackageInfo(tempFile); + if (pkg == null) { + Log.e(TAG, "Could not parse apk information for " + packageName); + return; + } + + if (!pkg.packageName.equals(packageName)) { + Log.e(TAG, "Wearable Package Name has to match what is provided for " + + packageName); + return; + } + + List<String> wearablePerms = pkg.requestedPermissions; + + // Log if the installed pkg has a higher version number. + if (existingPkgInfo != null) { + if (existingPkgInfo.versionCode == pkg.mVersionCode) { + if (skipIfSameVersion) { + Log.w(TAG, "Version number (" + pkg.mVersionCode + + ") of new app is equal to existing app for " + packageName + + "; not installing due to versionCheck"); + return; + } else { + Log.w(TAG, "Version number of new app (" + pkg.mVersionCode + + ") is equal to existing app for " + packageName); + } + } else if (existingPkgInfo.versionCode > pkg.mVersionCode) { + Log.w(TAG, "Version number of new app (" + pkg.mVersionCode + + ") is lower than existing app ( " + existingPkgInfo.versionCode + + ") for " + packageName); + } + + // Following the Android Phone model, we should only check for permissions for any + // newly defined perms. + if (existingPkgInfo.requestedPermissions != null) { + for (int i = 0; i < existingPkgInfo.requestedPermissions.length; ++i) { + // If the permission is granted, then we will not ask to request it again. + if ((existingPkgInfo.requestedPermissionsFlags[i] & + PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, existingPkgInfo.requestedPermissions[i] + + " is already granted for " + packageName); + } + wearablePerms.remove(existingPkgInfo.requestedPermissions[i]); + } + } + } + } + + // Check permissions on both the new wearable package and also on the already installed + // wearable package. + // If the app is targeting API level 23, we will also start a service in ClockworkHome + // which will ultimately prompt the user to accept/reject permissions. + if (checkPerms && !checkPermissions(pkg, companionSdkVersion, companionDeviceVersion, + permUri, wearablePerms, tempFile)) { + Log.w(TAG, "Wearable does not have enough permissions."); + return; + } + + // Check that the wearable has all the features. + boolean hasAllFeatures = true; + if (pkg.reqFeatures != null) { + for (FeatureInfo feature : pkg.reqFeatures) { + if (feature.name != null && !pm.hasSystemFeature(feature.name) && + (feature.flags & FeatureInfo.FLAG_REQUIRED) != 0) { + Log.e(TAG, "Wearable does not have required feature: " + feature + + " for " + packageName); + hasAllFeatures = false; + } + } + } + + if (!hasAllFeatures) { + return; + } + + // Finally install the package. + pm.installPackage(Uri.fromFile(tempFile), + new PackageInstallObserver(this, lock, startId, packageName), + installFlags, packageName); + messageSent = true; + Log.i(TAG, "Sent installation request for " + packageName); + } catch (FileNotFoundException e) { + Log.e(TAG, "Could not find the file with URI " + packageUri, e); + } finally { + if (!messageSent) { + // Some error happened. If the message has been sent, we can wait for the observer + // which will finish the service. + if (tempFile != null) { + tempFile.delete(); + } + finishService(lock, startId); + } + } + } + + private void uninstallPackage(String packageName, int startId) { + final PackageManager pm = getPackageManager(); + PowerManager.WakeLock lock = getLock(this.getApplicationContext()); + pm.deletePackage(packageName, new PackageDeleteObserver(lock, startId), + PackageManager.DELETE_ALL_USERS); + startPermsServiceForUninstall(packageName); + Log.i(TAG, "Sent delete request for " + packageName); + } + + private boolean checkPermissions(PackageParser.Package pkg, int companionSdkVersion, + int companionDeviceVersion, Uri permUri, List<String> wearablePermissions, + File apkFile) { + // If the Wear App is targeted for M-release, since the permission model has been changed, + // permissions may not be granted on the phone yet. We need a different flow for user to + // accept these permissions. + // + // Assumption: Code is running on E-release, so Wear is always running M. + // - Case 1: If the Wear App(WA) is targeting 23, always choose the M model (4 cases) + // - Case 2: Else if the Phone App(PA) is targeting 23 and Phone App(P) is running on M, + // show a Dialog so that the user can accept all perms (1 case) + // - Also show a warning to the developer if the watch is targeting M + // - Case 3: If Case 2 is false, then the behavior on the phone is pre-M. Stick to pre-M + // behavior on watch (as long as we don't hit case 1). + // - 3a: WA(22) PA(22) P(22) -> watch app is not targeting 23 + // - 3b: WA(22) PA(22) P(23) -> watch app is not targeting 23 + // - 3c: WA(22) PA(23) P(22) -> watch app is not targeting 23 + // - Case 4: We did not get Companion App's/Device's version, always show dialog to user to + // accept permissions. (This happens if the AndroidWear Companion App is really old). + boolean isWearTargetingM = + pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1; + if (isWearTargetingM) { // Case 1 + // Install the app if Wear App is ready for the new perms model. + return true; + } + + List<String> unavailableWearablePerms = getWearPermsNotGrantedOnPhone(pkg.packageName, + permUri, wearablePermissions); + if (unavailableWearablePerms == null) { + return false; + } + + if (unavailableWearablePerms.size() == 0) { + // All permissions requested by the watch are already granted on the phone, no need + // to do anything. + return true; + } + + // Cases 2 and 4. + boolean isCompanionTargetingM = companionSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1; + boolean isCompanionRunningM = companionDeviceVersion > Build.VERSION_CODES.LOLLIPOP_MR1; + if (isCompanionTargetingM) { // Case 2 Warning + Log.w(TAG, "MNC: Wear app's targetSdkVersion should be at least 23, if " + + "phone app is targeting at least 23, will continue."); + } + if ((isCompanionTargetingM && isCompanionRunningM) || // Case 2 + companionSdkVersion == 0 || companionDeviceVersion == 0) { // Case 4 + startPermsServiceForInstall(pkg, apkFile, unavailableWearablePerms); + } + + // Case 3a-3c. + return false; + } + + /** + * Given a {@string packageName} corresponding to a phone app, query the provider for all the + * perms that are granted. + * @return null if there is an error retrieving this info + * else, a list of all the wearable perms that are not in the list of granted perms of + * the phone. + */ + private List<String> getWearPermsNotGrantedOnPhone(String packageName, Uri permUri, + List<String> wearablePermissions) { + if (permUri == null) { + Log.e(TAG, "Permission URI is null"); + return null; + } + Cursor permCursor = getContentResolver().query(permUri, null, null, null, null); + if (permCursor == null) { + Log.e(TAG, "Could not get the cursor for the permissions"); + return null; + } + + Set<String> grantedPerms = new HashSet<>(); + Set<String> ungrantedPerms = new HashSet<>(); + while(permCursor.moveToNext()) { + // Make sure that the MatrixCursor returned by the ContentProvider has 2 columns and + // verify their types. + if (permCursor.getColumnCount() == 2 + && Cursor.FIELD_TYPE_STRING == permCursor.getType(0) + && Cursor.FIELD_TYPE_INTEGER == permCursor.getType(1)) { + String perm = permCursor.getString(0); + Integer granted = permCursor.getInt(1); + if (granted == 1) { + grantedPerms.add(perm); + } else { + ungrantedPerms.add(perm); + } + } + } + permCursor.close(); + + ArrayList<String> unavailableWearablePerms = new ArrayList<>(); + for (String wearablePerm : wearablePermissions) { + if (!grantedPerms.contains(wearablePerm)) { + unavailableWearablePerms.add(wearablePerm); + if (!ungrantedPerms.contains(wearablePerm)) { + // This is an error condition. This means that the wearable has permissions that + // are not even declared in its host app. This is a developer error. + Log.e(TAG, "Wearable " + packageName + " has a permission \"" + wearablePerm + + "\" that is not defined in the host application's manifest."); + } else { + Log.w(TAG, "Wearable " + packageName + " has a permission \"" + wearablePerm + + "\" that is not granted in the host application."); + } + } + } + return unavailableWearablePerms; + } + + private void finishService(PowerManager.WakeLock lock, int startId) { + if (lock.isHeld()) { + lock.release(); + } + stopSelf(startId); + } + + private synchronized PowerManager.WakeLock getLock(Context context) { + if (lockStatic == null) { + PowerManager mgr = + (PowerManager) context.getSystemService(Context.POWER_SERVICE); + lockStatic = mgr.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, context.getClass().getSimpleName()); + lockStatic.setReferenceCounted(true); + } + return lockStatic; + } + + private void startPermsServiceForInstall(final PackageParser.Package pkg, final File apkFile, + List<String> unavailableWearablePerms) { + final String packageName = pkg.packageName; + + Intent showPermsIntent = new Intent() + .setComponent(new ComponentName(HOME_APP_PACKAGE_NAME, SHOW_PERMS_SERVICE_CLASS)) + .setAction(Intent.ACTION_INSTALL_PACKAGE); + final PackageManager pm = getPackageManager(); + pkg.applicationInfo.publicSourceDir = apkFile.getPath(); + final CharSequence label = pkg.applicationInfo.loadLabel(pm); + final Uri iconUri = getIconFileUri(packageName, pkg.applicationInfo.loadIcon(pm)); + if (TextUtils.isEmpty(label) || iconUri == null) { + Log.e(TAG, "MNC: Could not launch service since either label " + label + + ", or icon Uri " + iconUri + " is invalid."); + } else { + showPermsIntent.putExtra(KEY_APP_LABEL, label); + showPermsIntent.putExtra(KEY_APP_ICON_URI, iconUri); + showPermsIntent.putExtra(KEY_PACKAGE_NAME, packageName); + showPermsIntent.putExtra(KEY_PERMS_LIST, + unavailableWearablePerms.toArray(new String[0])); + showPermsIntent.putExtra(KEY_HAS_LAUNCHER, WearPackageUtil.hasLauncherActivity(pkg)); + + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "MNC: Launching Intent " + showPermsIntent + " for " + packageName + + " with name " + label); + } + startService(showPermsIntent); + } + } + + private void startPermsServiceForUninstall(final String packageName) { + Intent showPermsIntent = new Intent() + .setComponent(new ComponentName(HOME_APP_PACKAGE_NAME, SHOW_PERMS_SERVICE_CLASS)) + .setAction(Intent.ACTION_UNINSTALL_PACKAGE); + showPermsIntent.putExtra(KEY_PACKAGE_NAME, packageName); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Launching Intent " + showPermsIntent + " for " + packageName); + } + startService(showPermsIntent); + } + + private Uri getIconFileUri(final String packageName, final Drawable d) { + if (d == null || !(d instanceof BitmapDrawable)) { + Log.e(TAG, "Drawable is not a BitmapDrawable for " + packageName); + return null; + } + File iconFile = WearPackageUtil.getIconFile(this, packageName); + + if (iconFile == null) { + Log.e(TAG, "Could not get icon file for " + packageName); + return null; + } + + FileOutputStream fos = null; + try { + // Convert bitmap to byte array + Bitmap bitmap = ((BitmapDrawable) d).getBitmap(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos); + + // Write the bytes into the file + fos = new FileOutputStream(iconFile); + fos.write(bos.toByteArray()); + fos.flush(); + + return WearPackageIconProvider.getUriForPackage(packageName); + } catch (IOException e) { + Log.e(TAG, "Could not convert drawable to icon file for package " + packageName, e); + return null; + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + private class PackageInstallObserver extends IPackageInstallObserver.Stub { + private Context mContext; + private PowerManager.WakeLock mWakeLock; + private int mStartId; + private String mApplicationPackageName; + private PackageInstallObserver(Context context, PowerManager.WakeLock wakeLock, + int startId, String applicationPackageName) { + mContext = context; + mWakeLock = wakeLock; + mStartId = startId; + mApplicationPackageName = applicationPackageName; + } + + public void packageInstalled(String packageName, int returnCode) { + // If installation failed, bail out and remove the ShowPermsStore entry + if (returnCode < 0) { + Log.e(TAG, "Package install failed " + mApplicationPackageName + + ", returnCode " + returnCode); + WearPackageUtil.removeFromPermStore(mContext, mApplicationPackageName); + return; + } + + Log.i(TAG, "Package " + packageName + " was installed."); + + // Delete tempFile from the file system. + File tempFile = WearPackageUtil.getTemporaryFile(mContext, packageName); + if (tempFile != null) { + tempFile.delete(); + } + + // Broadcast the "UPDATED" gmscore intent, normally sent by play store. + // TODO: Remove this broadcast if/when we get the play store to do this for us. + if (GMS_PACKAGE_NAME.equals(packageName)) { + Intent gmsInstalledIntent = new Intent(GMS_UPDATED_BROADCAST); + gmsInstalledIntent.setPackage(GMS_PACKAGE_NAME); + mContext.sendBroadcast(gmsInstalledIntent); + } + + finishService(mWakeLock, mStartId); + } + } + + private class PackageDeleteObserver extends IPackageDeleteObserver.Stub { + private PowerManager.WakeLock mWakeLock; + private int mStartId; + + private PackageDeleteObserver(PowerManager.WakeLock wakeLock, int startId) { + mWakeLock = wakeLock; + mStartId = startId; + } + + public void packageDeleted(String packageName, int returnCode) { + if (returnCode >= 0) { + Log.i(TAG, "Package " + packageName + " was uninstalled."); + } else { + Log.e(TAG, "Package uninstall failed " + packageName + ", returnCode " + + returnCode); + } + finishService(mWakeLock, mStartId); + } + } +} diff --git a/src/com/android/packageinstaller/wear/WearPackageUtil.java b/src/com/android/packageinstaller/wear/WearPackageUtil.java new file mode 100644 index 00000000..688d6167 --- /dev/null +++ b/src/com/android/packageinstaller/wear/WearPackageUtil.java @@ -0,0 +1,167 @@ +/* + * 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.packageinstaller.wear; + +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageParser; +import android.os.ParcelFileDescriptor; +import android.system.ErrnoException; +import android.system.Os; +import android.text.TextUtils; +import android.util.Log; + +import org.tukaani.xz.LZMAInputStream; +import org.tukaani.xz.XZInputStream; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +public class WearPackageUtil { + private static final String TAG = "WearablePkgInstaller"; + + private static final String COMPRESSION_LZMA = "lzma"; + private static final String COMPRESSION_XZ = "xz"; + + private static final String SHOW_PERMS_SERVICE_PKG_NAME = "com.google.android.wearable.app"; + private static final String SHOW_PERMS_SERVICE_CLASS_NAME = + "com.google.android.clockwork.packagemanager.ShowPermsService"; + private static final String EXTRA_PACKAGE_NAME + = "com.google.android.clockwork.EXTRA_PACKAGE_NAME"; + + public static File getTemporaryFile(Context context, String packageName) { + try { + File newFileDir = new File(context.getFilesDir(), "tmp"); + newFileDir.mkdirs(); + Os.chmod(newFileDir.getAbsolutePath(), 0771); + File newFile = new File(newFileDir, packageName + ".apk"); + return newFile; + } catch (ErrnoException e) { + Log.e(TAG, "Failed to open.", e); + return null; + } + } + + public static File getIconFile(final Context context, final String packageName) { + try { + File newFileDir = new File(context.getFilesDir(), "images/icons"); + newFileDir.mkdirs(); + Os.chmod(newFileDir.getAbsolutePath(), 0771); + return new File(newFileDir, packageName + ".icon"); + } catch (ErrnoException e) { + Log.e(TAG, "Failed to open.", e); + return null; + } + } + + /** + * In order to make sure that the Wearable Asset Manager has a reasonable apk that can be used + * by the PackageManager, we will parse it before sending it to the PackageManager. + * Unfortunately, PackageParser needs a file to parse. So, we have to temporarily convert the fd + * to a File. + * + * @param context + * @param fd FileDescriptor to convert to File + * @param packageName Name of package, will define the name of the file + * @param compressionAlg Can be null. For ALT mode the APK will be compressed. We will + * decompress it here + */ + public static File getFileFromFd(Context context, ParcelFileDescriptor fd, + String packageName, @Nullable String compressionAlg) { + File newFile = getTemporaryFile(context, packageName); + if (fd == null || fd.getFileDescriptor() == null) { + return null; + } + InputStream fr = new ParcelFileDescriptor.AutoCloseInputStream(fd); + try { + if (TextUtils.equals(compressionAlg, COMPRESSION_XZ)) { + fr = new XZInputStream(fr); + } else if (TextUtils.equals(compressionAlg, COMPRESSION_LZMA)) { + fr = new LZMAInputStream(fr); + } + } catch (IOException e) { + Log.e(TAG, "Compression was set to " + compressionAlg + ", but could not decode ", e); + return null; + } + + int nRead; + byte[] data = new byte[1024]; + try { + final FileOutputStream fo = new FileOutputStream(newFile); + while ((nRead = fr.read(data, 0, data.length)) != -1) { + fo.write(data, 0, nRead); + } + fo.flush(); + fo.close(); + Os.chmod(newFile.getAbsolutePath(), 0644); + return newFile; + } catch (IOException e) { + Log.e(TAG, "Reading from Asset FD or writing to temp file failed ", e); + return null; + } catch (ErrnoException e) { + Log.e(TAG, "Could not set permissions on file ", e); + return null; + } finally { + try { + fr.close(); + } catch (IOException e) { + Log.e(TAG, "Failed to close the file from FD ", e); + } + } + } + + public static boolean hasLauncherActivity(PackageParser.Package pkg) { + if (pkg == null || pkg.activities == null) { + return false; + } + + final int activityCount = pkg.activities.size(); + for (int i = 0; i < activityCount; ++i) { + if (pkg.activities.get(i).intents != null) { + ArrayList<PackageParser.ActivityIntentInfo> intents = + pkg.activities.get(i).intents; + final int intentsCount = intents.size(); + for (int j = 0; j < intentsCount; ++j) { + final PackageParser.ActivityIntentInfo intentInfo = intents.get(j); + if (intentInfo.hasAction(Intent.ACTION_MAIN)) { + if (intentInfo.hasCategory(Intent.CATEGORY_INFO) || + intentInfo .hasCategory(Intent.CATEGORY_LAUNCHER)) { + return true; + } + } + } + } + } + return false; + } + + public static void removeFromPermStore(Context context, String wearablePackageName) { + Intent newIntent = new Intent() + .setComponent(new ComponentName( + SHOW_PERMS_SERVICE_PKG_NAME, SHOW_PERMS_SERVICE_CLASS_NAME)) + .setAction(Intent.ACTION_UNINSTALL_PACKAGE); + newIntent.putExtra(EXTRA_PACKAGE_NAME, wearablePackageName); + Log.i(TAG, "Sending removeFromPermStore to ShowPermsService " + newIntent + + " for " + wearablePackageName); + context.startService(newIntent); + } +} |