summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml6
-rw-r--r--docs/index.html1
-rw-r--r--res/values-ar/strings.xml62
-rw-r--r--res/values-bg/strings.xml62
-rw-r--r--res/values-ca/strings.xml62
-rw-r--r--res/values-en-rGB/strings.xml62
-rw-r--r--res/values-fa/strings.xml62
-rw-r--r--res/values-fi/strings.xml62
-rw-r--r--res/values-hr/strings.xml62
-rw-r--r--res/values-hu/strings.xml62
-rw-r--r--res/values-in/strings.xml62
-rw-r--r--res/values-iw/strings.xml62
-rw-r--r--res/values-lt/strings.xml62
-rw-r--r--res/values-lv/strings.xml62
-rw-r--r--res/values-ro/strings.xml62
-rw-r--r--res/values-sk/strings.xml62
-rw-r--r--res/values-sl/strings.xml62
-rw-r--r--res/values-sr/strings.xml62
-rw-r--r--res/values-th/strings.xml62
-rw-r--r--res/values-tl/strings.xml62
-rw-r--r--res/values-uk/strings.xml62
-rw-r--r--res/values-vi/strings.xml62
-rw-r--r--src/com/android/providers/downloads/Constants.java8
-rw-r--r--src/com/android/providers/downloads/DownloadInfo.java65
-rw-r--r--src/com/android/providers/downloads/DownloadNotification.java4
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java79
-rw-r--r--src/com/android/providers/downloads/DownloadReceiver.java13
-rw-r--r--src/com/android/providers/downloads/DownloadService.java121
-rw-r--r--src/com/android/providers/downloads/DownloadThread.java25
-rw-r--r--src/com/android/providers/downloads/Helpers.java38
-rw-r--r--tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java2
-rw-r--r--tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java29
-rw-r--r--tests/src/com/android/providers/downloads/AbstractPublicApiTest.java75
-rw-r--r--tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java30
-rw-r--r--tests/src/com/android/providers/downloads/FakeSystemFacade.java19
-rw-r--r--tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java55
-rw-r--r--tests/src/tests/http/MockResponse.java11
-rw-r--r--tests/src/tests/http/MockWebServer.java53
-rw-r--r--ui/AndroidManifest.xml2
-rw-r--r--ui/res/mipmap-hdpi/ic_launcher_download.png (renamed from ui/res/drawable-hdpi/ic_launcher_download.png)bin2561 -> 2561 bytes
-rw-r--r--ui/res/mipmap-mdpi/ic_launcher_download.png (renamed from ui/res/drawable-mdpi/ic_launcher_download.png)bin1818 -> 1818 bytes
-rw-r--r--ui/src/com/android/providers/downloads/ui/DownloadList.java30
42 files changed, 1651 insertions, 255 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0db696b7..2e6a5234 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -56,12 +56,14 @@
<application android:process="android.process.media"
android:label="@string/app_label">
<provider android:name=".DownloadProvider"
- android:authorities="downloads"
- android:permission="android.permission.ACCESS_ALL_DOWNLOADS">
+ android:authorities="downloads">
<!-- Anyone can access /my_downloads, the provider internally restricts access by UID for
these URIs -->
<path-permission android:pathPrefix="/my_downloads"
android:permission="android.permission.INTERNET"/>
+ <!-- to access /all_downloads, ACCESS_ALL_DOWNLOADS permission is required -->
+ <path-permission android:pathPrefix="/all_downloads"
+ android:permission="android.permission.ACCESS_ALL_DOWNLOADS"/>
<!-- Temporary, for backwards compatibility -->
<path-permission android:pathPrefix="/download"
android:permission="android.permission.INTERNET"/>
diff --git a/docs/index.html b/docs/index.html
index 9bd6a51f..0004b729 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,4 +1,5 @@
<html>
+
<head>
<title>Download Provider</title>
</head>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
new file mode 100644
index 00000000..bae8df61
--- /dev/null
+++ b/res/values-ar/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"إدارة التنزيل"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"الدخول إلى إدارة التنزيل."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"للسماح للتطبيق بالدخول إلى إدارة التنزيل واستخدامها لتنزيل ملفات. يمكن للتطبيقات الضارة استخدام هذا لتعطيل التنزيلات والدخول إلى المعلومات الخاصة."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"وظائف إدارة التنزيل المتقدمة."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"للسماح للتطبيق بالدخول إلى وظائف إدارة التنزيل المتقدمة. يمكن للتطبيقات الضارة استخدام هذا لتعطيل التنزيلات والدخول إلى المعلومات الخاصة."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"إرسال تنبيهات بالتنزيل."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"للسماح للتطبيق بإرسال تنبيهات عن التنزيلات المكتملة. يمكن للتطبيقات الضارة استخدام هذا لإرباك التطبيقات الأخرى التي تنزل الملفات."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"مشاهدة جميع التنزيلات على بطاقة SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"مشاهدة جميع التنزيلات على بطاقة SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"للسماح للتطبيقات بمشاهدة جميع التنزيلات على بطاقة SD، بغض النظر عن التطبيق الذي نزلها."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;بلا عنوان&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">"، "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" و<xliff:g id="NUMBER">%d</xliff:g> أخرى"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"اكتمل التنزيل"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"أخفق التنزيل"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
new file mode 100644
index 00000000..cf2767b9
--- /dev/null
+++ b/res/values-bg/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Download Manager"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Достъп до диспечера за изтегляне."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Дава на приложението достъп до диспечера за изтегляне и му позволява да го използва за изтегляне на файлове. Злонамерен софтуер може да използва това за прекъсване на изтеглянията и за достъп до лична информация."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Разширени функции на диспечера за изтегляне."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Дава достъп на приложението до разширените функции на диспечера за изтегляне. Злонамерен софтуер може да използва това за прекъсване на изтеглянията и за достъп до лична информация."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Изпращане на известия за изтегляне."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Позволява на приложението да изпраща известия за завършени изтегляния. Злонамерен софтуер може да използва това, за да обърка други приложения, изтеглящи файлове."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Вижте всичко изтеглено на SD картата"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Вижте всичко изтеглено на SD картата"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Позволява на приложението да вижда всичко изтеглено на SD картата, независимо кое приложение го е изтеглило."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Без заглавие&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" и още <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Изтеглянето завърши"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Изтеглянето не е успешно"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
new file mode 100644
index 00000000..41ba52e2
--- /dev/null
+++ b/res/values-ca/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Gestor de baixades"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Accediu al gestor de baixades."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Permet a l\'aplicació accedir al gestor de baixades i utilitzar-lo per baixar fitxers. Les aplicacions malicioses poden utilitzar aquest paràmetre per interrompre les baixades i accedir a informació privada."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Funcions avançades del gestor de baixades."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Permet a l\'aplicació accedir a les funcions avançades del gestor de baixades. Les aplicacions malicioses poden utilitzar aquest paràmetre per interrompre les baixades i accedir a informació privada."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Envia notificacions de baixades."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Permet a l\'aplicació enviar notificacions sobre baixades completades. Les aplicacions malicioses poden utilitzar aquest paràmetre per confondre altres aplicacions que baixen fitxers."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Visualitza totes les baixades a la targeta SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Visualitza totes les baixades a la targeta SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Permet a l\'aplicació visualitzar totes les baixades a la targeta SD, independentment de l\'aplicació que les hagi baixat."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Sense títol&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" i <xliff:g id="NUMBER">%d</xliff:g> més"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Baixada completada"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Baixada incorrecta"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
new file mode 100644
index 00000000..ceace5df
--- /dev/null
+++ b/res/values-en-rGB/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Download Manager"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Access download manager."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Allows the application to access the download manager and to use it to download files. Malicious applications can use this to disrupt downloads and access private information."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Advanced download manager functions."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Allows the application to access the download manager\'s advanced functions. Malicious applications can use this to disrupt downloads and access private information."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Send download notifications."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Allows the application to send notifications about completed downloads. Malicious applications can use this to confuse other applications that download files."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"See all downloads to SD card"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"See all downloads to SD card"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Allows the application to see all downloads to the SD card, regardless of which application downloaded them."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Untitled&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" and <xliff:g id="NUMBER">%d</xliff:g> more"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Download complete"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Download unsuccessful"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
new file mode 100644
index 00000000..07d79a7b
--- /dev/null
+++ b/res/values-fa/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Download Manager"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"دسترسی به Download Manager."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"به برنامه کاربردی اجازه می دهد به Download Manager برای استفاده از آن جهت دانلود فایل ها دسترسی پیدا کند. برنامه های مخرب می توانند از این ویژگی برای ایجاد اختلال در دانلود و دسترسی به اطلاعات خصوصی استفاده کنند."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"عملکرد Download Manager پیشرفته."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"به برنامه کاربردی اجازه می دهد به عملکرد Download Manager دسترسی پیدا کند. برنامه های مخرب می توانند از این ویژگی برای ایجاد اختلال در دانلودها و دسترسی به اطلاعات خصوصی استفاده کنند."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"اعلان های دانلود ارسال شود."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"به برنامه کاربردی اجازه می دهد درباره دانلودهای کامل شده اعلان هایی ارسال کند. برنامه های مخرب می توانند از این ویژگی برای گمراه کردن سایر برنامه هایی که فایل ها را دانلود می کنند، استفاده نمایند."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"مشاهده همه دانلودها در کارت SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"مشاهده همه دانلودها در کارت SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"به برنامه کاربردی اجازه می دهد همه موارد دانلود شده در کارت SD را صرفنظر از برنامه مورد استفاده برای دانلود آنها مشاهده کند."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;بدون عنوان&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">"، "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" و <xliff:g id="NUMBER">%d</xliff:g> بیشتر"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"دانلود انجام شد"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"دانلود ناموفق"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
new file mode 100644
index 00000000..d3287fcd
--- /dev/null
+++ b/res/values-fi/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Lataustenhallinta"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Lataustenhallinnan käyttö."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Sallii sovelluksen käyttää lataustenhallintaa tiedostojen lataamiseen. Haittasovellukset voivat häiritä latauksia ja käyttää yksityisiä tietoja tällä toiminnolla."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Lataustenhallinnan lisätoiminnot."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Sallii sovelluksen käyttää lataustenhallinnan lisätoimintoja. Haittaohjelmat voivat häiritä latauksia ja käyttää yksityisiä tietoja tällä toiminnolla."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Latausilmoitusten lähetys."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Sallii sovelluksen lähettää ilmoituksia suoritetuista latauksista. Haittasovellukset voivat sekoittaa tällä toiminnolla muita sovelluksia, jotka lataavat tiedostoja."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"SD-kortin kaikkien latausten tarkastelu."</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"SD-kortin kaikkien latausten tarkastelu."</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Sallii sovelluksen nähdä SD-kortin kaikki lataukset riippumatta siitä, mikä sovellus tiedostot on ladannut."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Nimetön&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" ja <xliff:g id="NUMBER">%d</xliff:g> muuta"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Lataus valmis"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Lataus epäonnistui"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
new file mode 100644
index 00000000..5c6d75ba
--- /dev/null
+++ b/res/values-hr/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Upravitelj za preuzimanje"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Pristupite upravitelju za preuzimanje."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Omogućuje aplikaciji pristup upravitelju za preuzimanje i njegovo korištenje za preuzimanje datoteka. Zlonamjerne aplikacije to mogu iskoristiti za ometanje preuzimanja i pristup osobnim podacima."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Napredne funkcije upravitelja za preuzimanje."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Omogućuje aplikaciji pristup naprednim funkcijama upravitelja za preuzimanje. Zlonamjerne aplikacije to mogu iskoristiti za ometanje preuzimanja i pristup osobnim podacima."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Pošaljite obavijesti o preuzimanju."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Omogućuje aplikaciji slanje obavijesti o dovršenim preuzimanjima. Zlonamjerne aplikacije to mogu koristiti da bi zbunile druge aplikacije koje preuzimaju datoteke."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Pogledajte sva preuzimanja na SD kartici"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Pogledajte sva preuzimanja na SD kartici"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Omogućuje aplikaciji da \"vidi\" sva preuzimanja na SD kartici, bez obzira na aplikaciju kojom je preuzimanje obavljeno."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Bez naslova&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" i još <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Preuzimanje je dovršeno"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Preuzimanje nije uspjelo"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
new file mode 100644
index 00000000..d06d372c
--- /dev/null
+++ b/res/values-hu/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Letöltéskezelő"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Hozzáférés a letöltéskezelőhöz."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Lehetővé teszi az alkalmazás számára a letöltéskezelő elérését és fájlok letöltésére való felhasználását. A rosszindulatú alkalmazások ezt a letöltés megzavarására és a személyes adatokhoz való hozzáféréshez használhatják fel."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Speciális letöltéskezelő-funkciók."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Lehetővé teszi az alkalmazás számára a letöltéskezelő speciális funkcióihoz való hozzáférést. A rosszindulatú alkalmazások ezt a letöltés megzavarására és a személyes adatokhoz való hozzáféréshez használhatják fel."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Letöltési értesítések küldése."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Lehetővé teszi az alkalmazás számára, hogy értesítéseket küldjön a befejezett letöltésekről. A rosszindulatú alkalmazások arra használhatják ezt, hogy megzavarjanak más, fájlokat letöltő alkalmazásokat."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"SD-kártyára irányuló összes letöltés megtekintése"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"SD-kártyára irányuló összes letöltés megtekintése"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Lehetővé teszi az alkalmazás számára az SD-kártyán levő összes letöltés megtekintését, függetlenül attól, hogy melyik alkalmazás töltötte le azokat."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Névtelen&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" és további <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"A letöltés befejeződött."</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"A letöltés nem sikerült"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
new file mode 100644
index 00000000..903da5f8
--- /dev/null
+++ b/res/values-in/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Pengelola Unduhan"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Akses pengelola unduhan."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Izinkan aplikasi mengakses pengelola unduhan dan menggunakannya untuk mengunduh berkas. Aplikasi hasad dapat menggunakan ini untuk mengacaukan unduhan dan mengakses informasi pribadi."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Fungsi pengelola unduhan lanjutan"</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Izinkan aplikasi mengakses fungsi lanjutan pengelola unduhan. Aplikasi hasad dapat menggunakan ini untuk mengacaukan unduhan dan mengakses informasi pribadi."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Kirim pemberitahuan unduhan."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Izinkan aplikasi mengirimkan pemberitahuan tentang unduhan yang telah diselesaikan. Aplikasi hasad dapat menggunakan ini untuk mengacau aplikasi lain yang mengunduh berkas."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Melihat semua unduhan pada kartu SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Melihat semua unduhan pada kartu SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Izinkan aplikasi melihat semua unduhan pada kartu SD, apa pun aplikasi yang mengunduhnya."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Tanpa judul&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" dan <xliff:g id="NUMBER">%d</xliff:g> lainnya"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Unduhan selesai"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Unduh gagal"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
new file mode 100644
index 00000000..d1c4b019
--- /dev/null
+++ b/res/values-iw/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"מנהל ההורדות"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"גש למנהל ההורדות."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"מאפשר ליישום לגשת למנהל ההורדות ולהשתמש בו כדי להוריד קבצים. יישומים זדוניים עלולים להשתמש בו כדי להפריע להורדות וכדי לגשת למידע פרטי."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"פונקציות מתקדמות של מנהל ההורדות."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"מאפשר ליישום לגשת לפונקציות המתקדמות של מנהל ההורדות. יישומים זדוניים עלולים להשתמש בו כדי להפריע להורדות וכדי לגשת למידע פרטי."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"שלח התראות על הורדות."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"מאפשר ליישום לשלוח התראות לגבי הורדות שהושלמו. יישומים זדוניים עלולים להשתמש בו כדי לבלבל יישומים אחרים המורידים קבצים."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"הצג את כל ההורדות לכרטיס ה-SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"הצג את כל ההורדות לכרטיס ה-SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"מאפשר ליישום לראות את כל ההורדות לכרטיס ה-SD, ללא קשר ליישום שהוריד אותן."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;ללא כותרת&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" ועוד <xliff:g id="NUMBER">%d</xliff:g> נוספים"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"ההורדה הושלמה"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"ההורדה נכשלה"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
new file mode 100644
index 00000000..27fd9e7b
--- /dev/null
+++ b/res/values-lt/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Atsisiuntimo tvarkyklė"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Pasiekti atsisiuntimo tvarkyklę."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Leidžia programai pasiekti atsisiuntimo tvarkyklę ir naudoti ją failams atsisiųsti. Kenkėjiškos programos gali naudoti tai ir trikdyti atsisiuntimus bei pasiekti asmeninę informaciją."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Išplėstinės atsisiuntimo tvarkyklės funkcijos."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Leidžia programai pasiekti išplėstines atsisiuntimo tvarkyklės funkcijas. Kenkėjiškos programos gali naudoti tai ir trikdyti atsisiuntimus bei pasiekti asmeninę informaciją."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Siųsti atsisiuntimo pranešimus."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Leidžia programai siųsti pranešimus apie užbaigtus atsisiuntimus. Kenkėjiškos programos gali naudoti tai, kad suklaidintų kitas programas, kurios atsisiunčia failus."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Žiūrėti visus atsisiuntimus į SD kortelę"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Žiūrėti visus atsisiuntimus į SD kortelę"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Leidžia programai žiūrėti visus atsisiuntimus į SD kortelę, nepriklausomai nuo to, kuri programa juos atsisiuntė."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Be pavadinimo&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" ir dar <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Atsisiuntimas baigtas"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Atsisiuntimas nesėkmingas"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
new file mode 100644
index 00000000..01c9cbab
--- /dev/null
+++ b/res/values-lv/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Download Manager"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Piekļuve lietojumprogrammai Download Manager."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Ļauj lietojumprogrammai piekļūt programmai Download Manager un izmantot to failu lejupielādēšanai. Ļaunprātīgas lietojumprogrammas var izmantot šo funkciju, lai pārtrauktu lejupielādes un piekļūtu privātai informācijai."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Izvērstas Download Manager funkcijas."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Ļauj šai lietojumprogrammai piekļūt programmas Download Manager izvērstajām funkcijām. Ļaunprātīgas lietojumprogrammas var izmantot šo funkciju, lai pārtrauktu lejupielādes un piekļūtu privātai informācijai."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Lejupielāžu paziņojumu sūtīšana."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Ļauj lietojumprogrammai sūtīt paziņojumus par pabeigtajām lejupielādēm. Ļaunprātīgas lietojumprogrammas var izmantot šo funkciju, lai maldinātu citas lietojumprogrammas, kas lejupielādē failus."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Skatīt visus SD kartē lejupielādētos failus"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Skatīt visus SD kartē lejupielādētos failus"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Ļauj lietojumprogrammai skatīt visus SD kartē lejupielādētos datus neatkarīgi no lietojumprogrammas, kas veica lejupielādi."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Bez nosaukuma&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" un vēl <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Lejupielāde ir pabeigta"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Lejupielāde nebija veiksmīga."</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
new file mode 100644
index 00000000..5ebd3fac
--- /dev/null
+++ b/res/values-ro/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Managerul de descărcare"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Accesaţi managerul de descărcare."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Permite aplicaţiei accesul la funcţiile managerului de descărcare în scopul descărcării fişierelor. Unele aplicaţii rău intenţionate se pot folosi de această funcţie pentru a întrerupe descărcările şi a accesa informaţiile private."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Funcţii avansate ale managerului de descărcare."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Permite aplicaţiei accesul la funcţiile avansate ale managerului de descărcare. Unele aplicaţii rău intenţionate se pot folosi de această funcţie pentru a întrerupe descărcările şi a accesa informaţiile private."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Trimiteţi notificările descărcării."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Permite aplicaţiei să trimită notificări despre descărcările efectuate. Unele aplicaţii rău intenţionate se pot folosi de această funcţie pentru a genera confuzie în rândul altor aplicaţii care descarcă fişiere."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Vizualizaţi toate descărcările pe cardul SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Vizualizaţi toate descărcările pe cardul SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Permite aplicaţiei să vadă toate descărcările de pe cardul SD, independent de cele pe care le-a realizat chiar aplicaţia."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Fără titlu&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" şi încă <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Descărcare completă"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Descărcare nereuşită"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
new file mode 100644
index 00000000..ca6e4881
--- /dev/null
+++ b/res/values-sk/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Správca preberania"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Získať prístup k správcovi preberania."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Povoľuje aplikácii získať prístup k správcovi preberania a prevziať pomocou neho súbory. Škodlivé aplikácie môžu pomocou tohto nastavenia narušiť preberanie a získať prístup k súkromným informáciám."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Rozšírené funkcie správcu preberania."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Povoľuje aplikácii prístup k rozšíreným funkciám správcu preberania. Škodlivé aplikácie to môžu využiť a narušiť preberanie alebo získať prístup k súkromným informáciám."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Odoslať upozornenie o prevzatí."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Povoľuje aplikácii odoslať upozornenia o dokončení preberania. Škodlivé aplikácie môžu pomocou tohto nastavenia zmiasť iné aplikácie, ktoré preberajú súbory."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Zobrazenie všetkých položiek prevzatých na kartu SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Zobrazenie všetkých položiek prevzatých na kartu SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Umožňuje aplikácii zobraziť všetky položky prevzaté na kartu SD bez ohľadu na to, ktorá aplikácia ich prevzala."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Bez názvu&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" a ďalšie (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Preberanie bolo dokončené"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Prevzatie zlyhalo"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
new file mode 100644
index 00000000..4ee4307e
--- /dev/null
+++ b/res/values-sl/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Upravitelj prenosov"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Dostop do upravitelja prenosov."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Omogoča aplikaciji, da dostopa do upravitelja prenosov in ga uporabi za prenos datotek. Zlonamerne aplikacije lahko uporabijo to funkcijo, da prekinejo prenose in dostopajo do zasebnih podatkov."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Dodatne funkcije upravitelja prenosov."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Omogoča aplikaciji, da dostopa do dodatnih funkcij upravitelja prenosov. Zlonamerne aplikacije lahko uporabijo to funkcijo, da prekinejo prenose in dostopajo do zasebnih podatkov."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Pošlji obvestila o prenosih."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Omogoči aplikaciji, da pošlje obvestila o dokončanih prenosih. Zlonamerne aplikacije lahko uporabijo to funkcijo, da zavedejo aplikacije, ki prenašajo datoteke."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Prikaži vse prenose na kartico SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Prikaži vse prenose na kartico SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Omogoči aplikaciji, da vidi vse prenose na kartico SD, ne glede na to, s katero aplikacijo so bile datoteke prenesene."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Brez naslova&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" in dodatnih <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Prenos dokončan"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Prenos neuspešen"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
new file mode 100644
index 00000000..cf45596b
--- /dev/null
+++ b/res/values-sr/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Менаџер преузимања"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Приступ менаџеру преузимања."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Омогућава апликацији да приступи менаџеру преузимања и да помоћу њега преузме датотеке. Злонамерне апликације то могу да искористе за ометање преузимања и приступ приватним информацијама."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Напредне функције менаџера преузимања."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Омогућава апликацији да приступи напредним функцијама менаџера преузимања. Злонамерне апликације то могу да искористе за ометање преузимања и приступ приватним информацијама."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Шаљите обавештења о преузимањима."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Омогућава апликацији да шаље обавештења о довршеним преузимањима. Злонамерне апликације то могу да искористе да наведу друге апликације да преузму датотеке."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Сва преузимања на SD картицу"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Сва преузимања на SD картицу"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Омогућава апликацији да види све што је преузето на SD картицу, без обзира на то помоћу којих апликација је то урађено."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Без наслова&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" и још <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Преузимање је довршено"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Преузимање није успело"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
new file mode 100644
index 00000000..f4cccf80
--- /dev/null
+++ b/res/values-th/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"ตัวจัดการการดาวน์โหลด"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"การเข้าถึงโปรแกรมการดาวน์โหลด"</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"อนุญาตให้แอปพลิเคชันเข้าถึงโปรแกรมจัดการการดาวน์โหลดและใช้งานโปรแกรมเพื่อดาวน์โหลดไฟล์ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้รบกวนการดาวน์โหลดและเข้าถึงข้อมูลส่วนบุคคล"</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"ฟังก์ชันโปรแกรมจัดการการดาวน์โหลดขั้นสูง"</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"อนุญาตให้แอปพลิเคชันเข้าถึงฟังก์ชันโปรแกรมจัดการการดาวน์โหลดขั้นสูง แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้รบกวนการดาวน์โหลดและเข้าถึงข้อมูลส่วนบุคคล"</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"ส่งการแจ้งเตือนการดาวน์โหลด"</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"อนุญาตให้แอปพลิเคชันส่งการแจ้งเตือนเกี่ยวกับ การดาวน์โหลดที่เสร็จสมบูรณ์ แอปพลิเคชันที่เป็นอันตรายสามารถใช้วิธีนี้สร้างความสับสนให้แอปพลิเคชันอื่นที่ดาวน์โหลดไฟล์"</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"ดูการดาวน์โหลดลงการ์ด SD ทั้งหมด"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"ดูการดาวน์โหลดลงการ์ด SD ทั้งหมด"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"อนุญาตให้แอปพลิเคชันดูการดาวน์โหลดลงการ์ด SD ทั้งหมด ไม่ว่าจะดาวน์โหลดจากแอปพลิเคชันหรือไม่ก็ตาม"</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;ไม่มีชื่อ&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" และอีก <xliff:g id="NUMBER">%d</xliff:g> รายการ"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"การดาวน์โหลดเสร็จสมบูรณ์"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"การดาวน์โหลดไม่สำเร็จ"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
new file mode 100644
index 00000000..5f4a10e5
--- /dev/null
+++ b/res/values-tl/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Tagapamahala ng Pag-download"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"I-access ang tagapamahala ng pag-download."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Pinapayagan ang application na ma-access ang tagapamahala ng pag-download at gamitin ito upang mag-download ng mga file. Maaaring gamitin ito ng mga nakakahamak na application upang guluhin ang mga pag-download at ma-access ang pribadong impormasyon."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Mga advanced na pag-andar ng tagapamahala ng pag-download."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Pinapayagan ang application na ma-access ang mga advanced na pag-andar ng tagapamahala ng pag-download. Maaaring gamitin ito ng mga nakakahamak na application upang guluhin ang mga pag-download at ma-access ang pribadong impormasyon."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Magpadala ng mga notification sa pag-download."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Pinapayagan ang application na magpadala ng mga notification tungkol sa mga nakumpletong pag-download. Maaaring gamitin ito ng mga nakahahamak na application upang magulo ang ibang mga application na nagda-download ng mga file."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Tingnan ang lahat ng mga pag-download sa SD card"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Tingnan ang lahat ng mga pag-download sa SD card"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Pinapayagan ang application na makita ang lahat ng mga pag-download sa SD card, ano pa man ang application na nag-download sa mga ito."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Walang pamagat&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" at <xliff:g id="NUMBER">%d</xliff:g> pa"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Kumpleto na ang pag-download"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Hindi matagumpay ang pag-download"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
new file mode 100644
index 00000000..cbbd5b40
--- /dev/null
+++ b/res/values-uk/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Менеджер завантаж."</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Доступ до менедж. завантаж."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Дозволяє програмі отрим. доступ до менеджера завантаж. і викор. його для завантаж. файлів. Шкідливі прогр. можуть викор. цей дозвіл для перерив. завантаж. і доступу до особ. інф."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Розширені функції менеджера завантаж."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Дозволяє програмі отрим. доступ до розширених функцій менеджера завантаж. Шкідливі прогр. можуть викор. цей дозвіл для перерив. завантаж. і доступу до особистої інфор."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Надсилати сповіщ. про завантаж."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Дозволяє програмі надсилати сповіщення про завершені завантаж. Шкідливі програми можуть викор. цей дозвіл, щоб заважати роботі ін. програм, які завантаж. файли."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Див. всі завантаж. на карту SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Див. всі завантаж. на карту SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Дозволяє програмі бачити всі завантаження на карту SD, незалежно від програми, яка їх завантажила."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Без назви&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" і ще <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Завантажено"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Завантаж. не здійснено"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
new file mode 100644
index 00000000..87277042
--- /dev/null
+++ b/res/values-vi/strings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="3658948994665187911">"Trình quản lý Tải xuống"</string>
+ <string name="permlab_downloadManager" msgid="7779544811202855500">"Truy cập trình quản lý tải xuống."</string>
+ <string name="permdesc_downloadManager" msgid="4240298564918160337">"Cho phép ứng dụng truy cập trình quản lý tải xuống và sử dụng trình quản lý này để tải tệp xuống. Các ứng dụng độc hại có thể sử dụng quyền này để làm hỏng nội dung tải xuống và truy cập thông tin cá nhân."</string>
+ <string name="permlab_downloadManagerAdvanced" msgid="7103642833308809655">"Chức năng nâng cao của trình quản lý tải xuống."</string>
+ <string name="permdesc_downloadManagerAdvanced" msgid="6985743912436565114">"Cho phép ứng dụng truy cập chức năng nâng cao của trình quản lý tải xuống. Các ứng dụng độc hại có thể sử dụng quyền này để làm hỏng nội dung tải xuống và truy cập thông tin cá nhân."</string>
+ <string name="permlab_downloadCompletedIntent" msgid="945913803765675685">"Gửi thông báo tải xuống."</string>
+ <string name="permdesc_downloadCompletedIntent" msgid="8672701687104399228">"Cho phép ứng dụng gửi thông báo về nội dung tải xuống đã hoàn tất. Các ứng dụng độc hại có thể sử dụng quyền này để gây nhầm lẫn cho các ứng dụng khác tải xuống tệp."</string>
+ <!-- outdated translation 140058400609165726 --> <string name="permlab_seeAllExternal" product="nosdcard" msgid="4084575448409212628">"Xem tất cả nội dung tải xuống về thẻ SD"</string>
+ <string name="permlab_seeAllExternal" product="default" msgid="140058400609165726">"Xem tất cả nội dung tải xuống về thẻ SD"</string>
+ <string name="permdesc_seeAllExternal" msgid="3298948060016417104">"Cho phép ứng dụng xem tất cả nội dung tải xuống trên thẻ SD, bất kể ứng dụng nào đã tải xuống nội dung đó."</string>
+ <!-- no translation found for permlab_downloadCacheNonPurgeable (3069534308882047412) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadCacheNonPurgeable (1089583021652571424) -->
+ <skip />
+ <!-- no translation found for permlab_downloadWithoutNotification (8837971946078327262) -->
+ <skip />
+ <!-- no translation found for permdesc_downloadWithoutNotification (5174806530123417020) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllDownloads (2436240495424393717) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllDownloads (4575801130424505112) -->
+ <skip />
+ <string name="download_unknown_title" msgid="7015124071247271585">"&lt;Không có tiêu đề&gt;"</string>
+ <string name="notification_filename_separator" msgid="7147189522857807618">", "</string>
+ <string name="notification_filename_extras" msgid="5549729917695688191">" và <xliff:g id="NUMBER">%d</xliff:g> mục khác"</string>
+ <string name="notification_download_complete" msgid="840713937779273632">"Tải xuống hoàn tất"</string>
+ <string name="notification_download_failed" msgid="5343637375905111462">"Tải xuống không thành công"</string>
+ <!-- no translation found for notification_need_wifi_for_size (5973127997598540499) -->
+ <skip />
+ <!-- no translation found for wifi_required_title (1995971416871498179) -->
+ <skip />
+ <!-- no translation found for wifi_required_body (1675692697446715831) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_title (7441589306734687400) -->
+ <skip />
+ <!-- no translation found for wifi_recommended_body (7574517147645381271) -->
+ <skip />
+ <!-- no translation found for button_queue_for_wifi (422576726189179221) -->
+ <skip />
+ <!-- no translation found for button_cancel_download (2430166148737975604) -->
+ <skip />
+ <!-- no translation found for button_start_now (792123674007840864) -->
+ <skip />
+</resources>
diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java
index 5cf13531..da2c2fd9 100644
--- a/src/com/android/providers/downloads/Constants.java
+++ b/src/com/android/providers/downloads/Constants.java
@@ -16,7 +16,6 @@
package com.android.providers.downloads;
-import android.util.Config;
import android.util.Log;
/**
@@ -144,11 +143,10 @@ public class Constants {
static final boolean LOGX = false;
/** Enable verbose logging - use with "setprop log.tag.DownloadManager VERBOSE" */
- private static final boolean LOCAL_LOGV = false;
- public static final boolean LOGV = Config.LOGV
- || (Config.LOGD && LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE));
+ private static final boolean LOCAL_LOGV = true; // STOPSHIP change this to false before shipping
+ public static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);
/** Enable super-verbose logging */
- private static final boolean LOCAL_LOGVV = false;
+ private static final boolean LOCAL_LOGVV = true; // STOPSHIP change this to false before shipping
public static final boolean LOGVV = LOCAL_LOGVV && LOGV;
}
diff --git a/src/com/android/providers/downloads/DownloadInfo.java b/src/com/android/providers/downloads/DownloadInfo.java
index 36816b59..363b68cd 100644
--- a/src/com/android/providers/downloads/DownloadInfo.java
+++ b/src/com/android/providers/downloads/DownloadInfo.java
@@ -45,8 +45,6 @@ public class DownloadInfo {
public static class Reader {
private ContentResolver mResolver;
private Cursor mCursor;
- private CharArrayBuffer mOldChars;
- private CharArrayBuffer mNewChars;
public Reader(ContentResolver resolver, Cursor cursor) {
mResolver = resolver;
@@ -62,11 +60,11 @@ public class DownloadInfo {
public void updateFromDatabase(DownloadInfo info) {
info.mId = getLong(Downloads.Impl._ID);
- info.mUri = getString(info.mUri, Downloads.Impl.COLUMN_URI);
+ info.mUri = getString(Downloads.Impl.COLUMN_URI);
info.mNoIntegrity = getInt(Downloads.Impl.COLUMN_NO_INTEGRITY) == 1;
- info.mHint = getString(info.mHint, Downloads.Impl.COLUMN_FILE_NAME_HINT);
- info.mFileName = getString(info.mFileName, Downloads.Impl._DATA);
- info.mMimeType = getString(info.mMimeType, Downloads.Impl.COLUMN_MIME_TYPE);
+ info.mHint = getString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
+ info.mFileName = getString(Downloads.Impl._DATA);
+ info.mMimeType = getString(Downloads.Impl.COLUMN_MIME_TYPE);
info.mDestination = getInt(Downloads.Impl.COLUMN_DESTINATION);
info.mVisibility = getInt(Downloads.Impl.COLUMN_VISIBILITY);
info.mStatus = getInt(Downloads.Impl.COLUMN_STATUS);
@@ -75,24 +73,23 @@ public class DownloadInfo {
info.mRetryAfter = retryRedirect & 0xfffffff;
info.mRedirectCount = retryRedirect >> 28;
info.mLastMod = getLong(Downloads.Impl.COLUMN_LAST_MODIFICATION);
- info.mPackage = getString(info.mPackage, Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
- info.mClass = getString(info.mClass, Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
- info.mExtras = getString(info.mExtras, Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS);
- info.mCookies = getString(info.mCookies, Downloads.Impl.COLUMN_COOKIE_DATA);
- info.mUserAgent = getString(info.mUserAgent, Downloads.Impl.COLUMN_USER_AGENT);
- info.mReferer = getString(info.mReferer, Downloads.Impl.COLUMN_REFERER);
+ info.mPackage = getString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
+ info.mClass = getString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
+ info.mExtras = getString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS);
+ info.mCookies = getString(Downloads.Impl.COLUMN_COOKIE_DATA);
+ info.mUserAgent = getString(Downloads.Impl.COLUMN_USER_AGENT);
+ info.mReferer = getString(Downloads.Impl.COLUMN_REFERER);
info.mTotalBytes = getLong(Downloads.Impl.COLUMN_TOTAL_BYTES);
info.mCurrentBytes = getLong(Downloads.Impl.COLUMN_CURRENT_BYTES);
- info.mETag = getString(info.mETag, Constants.ETAG);
+ info.mETag = getString(Constants.ETAG);
info.mMediaScanned = getInt(Constants.MEDIA_SCANNED) == 1;
info.mDeleted = getInt(Downloads.Impl.COLUMN_DELETED) == 1;
- info.mMediaProviderUri = getString(info.mMediaProviderUri,
- Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
+ info.mMediaProviderUri = getString(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
info.mIsPublicApi = getInt(Downloads.Impl.COLUMN_IS_PUBLIC_API) != 0;
info.mAllowedNetworkTypes = getInt(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES);
info.mAllowRoaming = getInt(Downloads.Impl.COLUMN_ALLOW_ROAMING) != 0;
- info.mTitle = getString(info.mTitle, Downloads.Impl.COLUMN_TITLE);
- info.mDescription = getString(info.mDescription, Downloads.Impl.COLUMN_DESCRIPTION);
+ info.mTitle = getString(Downloads.Impl.COLUMN_TITLE);
+ info.mDescription = getString(Downloads.Impl.COLUMN_DESCRIPTION);
info.mBypassRecommendedSizeLimit =
getInt(Downloads.Impl.COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT);
@@ -130,35 +127,10 @@ public class DownloadInfo {
info.mRequestHeaders.add(Pair.create(header, value));
}
- /**
- * Returns a String that holds the current value of the column, optimizing for the case
- * where the value hasn't changed.
- */
- private String getString(String old, String column) {
+ private String getString(String column) {
int index = mCursor.getColumnIndexOrThrow(column);
- if (old == null) {
- return mCursor.getString(index);
- }
- if (mNewChars == null) {
- mNewChars = new CharArrayBuffer(128);
- }
- mCursor.copyStringToBuffer(index, mNewChars);
- int length = mNewChars.sizeCopied;
- if (length != old.length()) {
- return new String(mNewChars.data, 0, length);
- }
- if (mOldChars == null || mOldChars.sizeCopied < length) {
- mOldChars = new CharArrayBuffer(length);
- }
- char[] oldArray = mOldChars.data;
- char[] newArray = mNewChars.data;
- old.getChars(0, length, oldArray, 0);
- for (int i = length - 1; i >= 0; --i) {
- if (oldArray[i] != newArray[i]) {
- return new String(newArray, 0, length);
- }
- }
- return old;
+ String s = mCursor.getString(index);
+ return (TextUtils.isEmpty(s)) ? null : s;
}
private Integer getInt(String column) {
@@ -547,7 +519,8 @@ public class DownloadInfo {
*/
boolean shouldScanFile() {
return !mMediaScanned
- && mDestination == Downloads.Impl.DESTINATION_EXTERNAL
+ && (mDestination == Downloads.Impl.DESTINATION_EXTERNAL ||
+ mDestination == Downloads.Impl.DESTINATION_FILE_URI)
&& Downloads.Impl.isStatusSuccess(mStatus)
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(mMimeType);
}
diff --git a/src/com/android/providers/downloads/DownloadNotification.java b/src/com/android/providers/downloads/DownloadNotification.java
index 4d615df7..4002a97a 100644
--- a/src/com/android/providers/downloads/DownloadNotification.java
+++ b/src/com/android/providers/downloads/DownloadNotification.java
@@ -259,12 +259,12 @@ class DownloadNotification {
private boolean isActiveAndVisible(DownloadInfo download) {
return 100 <= download.mStatus && download.mStatus < 200
- && download.mVisibility != Downloads.VISIBILITY_HIDDEN;
+ && download.mVisibility != Downloads.Impl.VISIBILITY_HIDDEN;
}
private boolean isCompleteAndVisible(DownloadInfo download) {
return download.mStatus >= 200
- && download.mVisibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED;
+ && download.mVisibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED;
}
/*
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java
index d97d6189..9336b737 100644
--- a/src/com/android/providers/downloads/DownloadProvider.java
+++ b/src/com/android/providers/downloads/DownloadProvider.java
@@ -16,6 +16,7 @@
package com.android.providers.downloads;
+import android.app.DownloadManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -25,10 +26,8 @@ import android.content.UriMatcher;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.database.CrossProcessCursor;
import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.CursorWrapper;
+import android.database.DatabaseUtils;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
@@ -45,11 +44,11 @@ import com.google.common.annotations.VisibleForTesting;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
@@ -59,7 +58,7 @@ public final class DownloadProvider extends ContentProvider {
/** Database filename */
private static final String DB_NAME = "downloads.db";
/** Current database version */
- private static final int DB_VERSION = 106;
+ private static final int DB_VERSION = 107;
/** Name of table in the database */
private static final String DB_TABLE = "downloads";
@@ -80,6 +79,11 @@ public final class DownloadProvider extends ContentProvider {
private static final int ALL_DOWNLOADS_ID = 4;
/** URI matcher constant for the URI of a download's request headers */
private static final int REQUEST_HEADERS_URI = 5;
+ /** URI matcher constant for the public URI returned by
+ * {@link DownloadManager#getUriForDownloadedFile(long)} if the given downloaded file
+ * is publicly accessible.
+ */
+ private static final int PUBLIC_DOWNLOAD_ID = 6;
static {
sURIMatcher.addURI("downloads", "my_downloads", MY_DOWNLOADS);
sURIMatcher.addURI("downloads", "my_downloads/#", MY_DOWNLOADS_ID);
@@ -97,6 +101,9 @@ public final class DownloadProvider extends ContentProvider {
sURIMatcher.addURI("downloads",
"download/#/" + Downloads.Impl.RequestHeaders.URI_SEGMENT,
REQUEST_HEADERS_URI);
+ sURIMatcher.addURI("downloads",
+ Downloads.Impl.PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT + "/#",
+ PUBLIC_DOWNLOAD_ID);
}
/** Different base URIs that could be used to access an individual download */
@@ -135,6 +142,8 @@ public final class DownloadProvider extends ContentProvider {
sAppReadableColumnsSet.add(sAppReadableColumnsArray[i]);
}
}
+ private static final List<String> downloadManagerColumnsList =
+ Arrays.asList(DownloadManager.UNDERLYING_COLUMNS);
/** The database that lies underneath this content provider */
private SQLiteOpenHelper mOpenHelper = null;
@@ -279,6 +288,10 @@ public final class DownloadProvider extends ContentProvider {
"BOOLEAN NOT NULL DEFAULT 0");
break;
+ case 107:
+ addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ERROR_MSG, "TEXT");
+ break;
+
default:
throw new IllegalStateException("Don't know how to upgrade to " + version);
}
@@ -425,6 +438,15 @@ public final class DownloadProvider extends ContentProvider {
case MY_DOWNLOADS_ID: {
return DOWNLOAD_TYPE;
}
+ case PUBLIC_DOWNLOAD_ID: {
+ // return the mimetype of this id from the database
+ final String id = getDownloadIdFromUri(uri);
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ return DatabaseUtils.stringForQuery(db,
+ "SELECT " + Downloads.Impl.COLUMN_MIME_TYPE + " FROM " + DB_TABLE +
+ " WHERE " + Downloads.Impl._ID + " = ?",
+ new String[]{id});
+ }
default: {
if (Constants.LOGV) {
Log.v(Constants.TAG, "calling getType on an unknown URI: " + uri);
@@ -645,6 +667,7 @@ public final class DownloadProvider extends ContentProvider {
values.remove(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES);
values.remove(Downloads.Impl.COLUMN_ALLOW_ROAMING);
values.remove(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI);
+ values.remove(Downloads.Impl.COLUMN_MEDIA_SCANNED);
Iterator<Map.Entry<String, Object>> iterator = values.valueSet().iterator();
while (iterator.hasNext()) {
String key = iterator.next().getKey();
@@ -720,8 +743,10 @@ public final class DownloadProvider extends ContentProvider {
if (projection == null) {
projection = sAppReadableColumnsArray;
} else {
+ // check the validity of the columns in projection
for (int i = 0; i < projection.length; ++i) {
- if (!sAppReadableColumnsSet.contains(projection[i])) {
+ if (!sAppReadableColumnsSet.contains(projection[i]) &&
+ !downloadManagerColumnsList.contains(projection[i])) {
throw new IllegalArgumentException(
"column " + projection[i] + " is not allowed in queries");
}
@@ -737,10 +762,6 @@ public final class DownloadProvider extends ContentProvider {
fullSelection.getParameters(), null, null, sort);
if (ret != null) {
- ret = new ReadOnlyCursorWrapper(ret);
- }
-
- if (ret != null) {
ret.setNotificationUri(getContext().getContentResolver(), uri);
if (Constants.LOGVV) {
Log.v(Constants.TAG,
@@ -831,9 +852,8 @@ public final class DownloadProvider extends ContentProvider {
+ getDownloadIdFromUri(uri);
String[] projection = new String[] {Downloads.Impl.RequestHeaders.COLUMN_HEADER,
Downloads.Impl.RequestHeaders.COLUMN_VALUE};
- Cursor cursor = db.query(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, projection, where,
- null, null, null, null);
- return new ReadOnlyCursorWrapper(cursor);
+ return db.query(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, projection, where,
+ null, null, null, null);
}
/**
@@ -972,7 +992,8 @@ public final class DownloadProvider extends ContentProvider {
int uriMatch) {
SqlSelection selection = new SqlSelection();
selection.appendClause(where, whereArgs);
- if (uriMatch == MY_DOWNLOADS_ID || uriMatch == ALL_DOWNLOADS_ID) {
+ if (uriMatch == MY_DOWNLOADS_ID || uriMatch == ALL_DOWNLOADS_ID ||
+ uriMatch == PUBLIC_DOWNLOAD_ID) {
selection.appendClause(Downloads.Impl._ID + " = ?", getDownloadIdFromUri(uri));
}
if ((uriMatch == MY_DOWNLOADS || uriMatch == MY_DOWNLOADS_ID)
@@ -1128,34 +1149,4 @@ public final class DownloadProvider extends ContentProvider {
to.put(key, defaultValue);
}
}
-
- private class ReadOnlyCursorWrapper extends CursorWrapper implements CrossProcessCursor {
- public ReadOnlyCursorWrapper(Cursor cursor) {
- super(cursor);
- mCursor = (CrossProcessCursor) cursor;
- }
-
- public boolean deleteRow() {
- throw new SecurityException("Download manager cursors are read-only");
- }
-
- public boolean commitUpdates() {
- throw new SecurityException("Download manager cursors are read-only");
- }
-
- public void fillWindow(int pos, CursorWindow window) {
- mCursor.fillWindow(pos, window);
- }
-
- public CursorWindow getWindow() {
- return mCursor.getWindow();
- }
-
- public boolean onMove(int oldPosition, int newPosition) {
- return mCursor.onMove(oldPosition, newPosition);
- }
-
- private CrossProcessCursor mCursor;
- }
-
}
diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java
index c41895b9..33066393 100644
--- a/src/com/android/providers/downloads/DownloadReceiver.java
+++ b/src/com/android/providers/downloads/DownloadReceiver.java
@@ -41,6 +41,7 @@ public class DownloadReceiver extends BroadcastReceiver {
@VisibleForTesting
SystemFacade mSystemFacade = null;
+ @Override
public void onReceive(Context context, Intent intent) {
if (mSystemFacade == null) {
mSystemFacade = new RealSystemFacade(context);
@@ -169,11 +170,21 @@ public class DownloadReceiver extends BroadcastReceiver {
if (isPublicApi) {
appIntent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED);
appIntent.setPackage(pckg);
+ // send id of the items clicked on.
+ if (intent.getBooleanExtra("multiple", false)) {
+ // broadcast received saying click occurred on a notification with multiple titles.
+ // don't include any ids at all - let the caller query all downloads belonging to it
+ // TODO modify the broadcast to include ids of those multiple notifications.
+ } else {
+ appIntent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
+ new long[] {
+ cursor.getLong(cursor.getColumnIndexOrThrow(Downloads.Impl._ID))});
+ }
} else { // legacy behavior
if (clazz == null) {
return;
}
- appIntent = new Intent(Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
+ appIntent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED);
appIntent.setClassName(pckg, clazz);
if (intent.getBooleanExtra("multiple", true)) {
appIntent.setData(Downloads.Impl.CONTENT_URI);
diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java
index 169ef970..f93c5c2e 100644
--- a/src/com/android/providers/downloads/DownloadService.java
+++ b/src/com/android/providers/downloads/DownloadService.java
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
import android.media.IMediaScannerListener;
import android.media.IMediaScannerService;
import android.net.Uri;
@@ -44,7 +45,6 @@ import com.google.android.collect.Maps;
import com.google.common.annotations.VisibleForTesting;
import java.io.File;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
@@ -114,6 +114,7 @@ public class DownloadService extends Service {
* Receives notification when the data in the observed content
* provider changes.
*/
+ @Override
public void onChange(final boolean selfChange) {
if (Constants.LOGVV) {
Log.v(Constants.TAG, "Service ContentObserver received notification");
@@ -188,6 +189,7 @@ public class DownloadService extends Service {
*
* @throws UnsupportedOperationException
*/
+ @Override
public IBinder onBind(Intent i) {
throw new UnsupportedOperationException("Cannot bind to Download Manager Service");
}
@@ -195,6 +197,7 @@ public class DownloadService extends Service {
/**
* Initializes the service when it is first created
*/
+ @Override
public void onCreate() {
super.onCreate();
if (Constants.LOGVV) {
@@ -232,6 +235,7 @@ public class DownloadService extends Service {
/**
* Cleans up when the service is destroyed
*/
+ @Override
public void onDestroy() {
getContentResolver().unregisterContentObserver(mObserver);
if (Constants.LOGVV) {
@@ -258,6 +262,7 @@ public class DownloadService extends Service {
super("Download Service");
}
+ @Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -363,24 +368,23 @@ public class DownloadService extends Service {
if (info.shouldScanFile()) {
// initiate rescan of the file to - which will populate
// mediaProviderUri column in this row
- if (!scanFile(info, true, false)) {
+ if (!scanFile(info, false, true)) {
throw new IllegalStateException("scanFile failed!");
}
- } else {
- // this file should NOT be scanned. delete the file.
- Helpers.deleteFile(getContentResolver(), info.mId, info.mFileName,
- info.mMimeType);
+ continue;
}
} else {
// yes it has mediaProviderUri column already filled in.
- // delete it from MediaProvider database and then from downloads table
- // in DownProvider database (the order of deletion is important).
+ // delete it from MediaProvider database.
getContentResolver().delete(Uri.parse(info.mMediaProviderUri), null,
null);
- getContentResolver().delete(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
- Downloads.Impl._ID + " = ? ",
- new String[]{String.valueOf(info.mId)});
}
+ // delete the file
+ deleteFileIfExists(info.mFileName);
+ // delete from the downloads db
+ getContentResolver().delete(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
+ Downloads.Impl._ID + " = ? ",
+ new String[]{String.valueOf(info.mId)});
}
}
}
@@ -463,29 +467,41 @@ public class DownloadService extends Service {
* Drops old rows from the database to prevent it from growing too large
*/
private void trimDatabase() {
- Cursor cursor = getContentResolver().query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
- new String[] { Downloads.Impl._ID },
- Downloads.Impl.COLUMN_STATUS + " >= '200'", null,
- Downloads.Impl.COLUMN_LAST_MODIFICATION);
- if (cursor == null) {
- // This isn't good - if we can't do basic queries in our database, nothing's gonna work
- Log.e(Constants.TAG, "null cursor in trimDatabase");
- return;
- }
- if (cursor.moveToFirst()) {
- int numDelete = cursor.getCount() - Constants.MAX_DOWNLOADS;
- int columnId = cursor.getColumnIndexOrThrow(Downloads.Impl._ID);
- while (numDelete > 0) {
- Uri downloadUri = ContentUris.withAppendedId(
- Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, cursor.getLong(columnId));
- getContentResolver().delete(downloadUri, null, null);
- if (!cursor.moveToNext()) {
- break;
+ Cursor cursor = null;
+ try {
+ cursor = getContentResolver().query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
+ new String[] { Downloads.Impl._ID },
+ Downloads.Impl.COLUMN_STATUS + " >= '200'", null,
+ Downloads.Impl.COLUMN_LAST_MODIFICATION);
+ if (cursor == null) {
+ // This isn't good - if we can't do basic queries in our database, nothing's gonna work
+ Log.e(Constants.TAG, "null cursor in trimDatabase");
+ return;
+ }
+ if (cursor.moveToFirst()) {
+ int numDelete = cursor.getCount() - Constants.MAX_DOWNLOADS;
+ int columnId = cursor.getColumnIndexOrThrow(Downloads.Impl._ID);
+ while (numDelete > 0) {
+ Uri downloadUri = ContentUris.withAppendedId(
+ Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, cursor.getLong(columnId));
+ getContentResolver().delete(downloadUri, null, null);
+ if (!cursor.moveToNext()) {
+ break;
+ }
+ numDelete--;
}
- numDelete--;
+ }
+ } catch (SQLiteException e) {
+ // trimming the database raised an exception. alright, ignore the exception
+ // and return silently. trimming database is not exactly a critical operation
+ // and there is no need to propagate the exception.
+ Log.w(Constants.TAG, "trimDatabase failed with exception: " + e.getMessage());
+ return;
+ } finally {
+ if (cursor != null) {
+ cursor.close();
}
}
- cursor.close();
}
/**
@@ -580,22 +596,28 @@ public class DownloadService extends Service {
mMediaScannerService.requestScanFile(info.mFileName, info.mMimeType,
new IMediaScannerListener.Stub() {
public void scanCompleted(String path, Uri uri) {
- if (uri != null && updateDatabase) {
- // file is scanned and mediaprovider returned uri. store it in downloads
- // table (i.e., update this downloaded file's row)
+ if (updateDatabase) {
+ // Mark this as 'scanned' in the database
+ // so that it is NOT subject to re-scanning by MediaScanner
+ // next time this database row row is encountered
ContentValues values = new ContentValues();
values.put(Constants.MEDIA_SCANNED, 1);
- values.put(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
- uri.toString());
+ if (uri != null) {
+ values.put(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
+ uri.toString());
+ }
getContentResolver().update(key, values, null, null);
- } else if (uri == null && deleteFile) {
- // callback returned NO uri..that means this file doesn't
- // exist in MediaProvider. but it still needs to be deleted
- // TODO don't scan files that are not scannable by MediaScanner.
- // create a public method in MediaFile.java to return false
- // if the given file's mimetype is not any of the types
- // the mediaprovider is interested in.
- Helpers.deleteFile(resolver, id, path, mimeType);
+ } else if (deleteFile) {
+ if (uri != null) {
+ // use the Uri returned to delete it from the MediaProvider
+ getContentResolver().delete(uri, null, null);
+ }
+ // delete the file and delete its row from the downloads db
+ deleteFileIfExists(path);
+ getContentResolver().delete(
+ Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
+ Downloads.Impl._ID + " = ? ",
+ new String[]{String.valueOf(id)});
}
}
});
@@ -606,4 +628,15 @@ public class DownloadService extends Service {
}
}
}
+
+ private void deleteFileIfExists(String path) {
+ try {
+ if (!TextUtils.isEmpty(path)) {
+ File file = new File(path);
+ file.delete();
+ }
+ } catch (Exception e) {
+ Log.w(Constants.TAG, "file: '" + path + "' couldn't be deleted", e);
+ }
+ }
}
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 0da950ba..a1d91019 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -24,7 +24,6 @@ import android.content.Intent;
import android.drm.mobile1.DrmRawContent;
import android.net.http.AndroidHttpClient;
import android.net.Proxy;
-import android.net.Uri;
import android.os.FileUtils;
import android.os.PowerManager;
import android.os.Process;
@@ -150,6 +149,7 @@ public class DownloadThread extends Thread {
AndroidHttpClient client = null;
PowerManager.WakeLock wakeLock = null;
int finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;
+ String errorMsg = null;
try {
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -189,11 +189,12 @@ public class DownloadThread extends Thread {
finalStatus = Downloads.Impl.STATUS_SUCCESS;
} catch (StopRequest error) {
// remove the cause before printing, in case it contains PII
- Log.w(Constants.TAG,
- "Aborting request for download " + mInfo.mId + ": " + error.getMessage());
+ errorMsg = "Aborting request for download " + mInfo.mId + ": " + error.getMessage();
+ Log.w(Constants.TAG, errorMsg);
finalStatus = error.mFinalStatus;
// fall through to finally block
} catch (Throwable ex) { //sometimes the socket code throws unchecked exceptions
+ errorMsg = "Exception for id " + mInfo.mId + ": " + ex.getMessage();
Log.w(Constants.TAG, "Exception for id " + mInfo.mId + ": " + ex);
finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;
// falls through to the code that reports an error
@@ -209,7 +210,7 @@ public class DownloadThread extends Thread {
cleanupDestination(state, finalStatus);
notifyDownloadCompleted(finalStatus, state.mCountRetry, state.mRetryAfter,
state.mRedirectCount, state.mGotData, state.mFilename,
- state.mNewUri, state.mMimeType);
+ state.mNewUri, state.mMimeType, errorMsg);
mInfo.mHasActiveThread = false;
}
}
@@ -688,7 +689,8 @@ public class DownloadThread extends Thread {
} else {
finalStatus = Downloads.Impl.STATUS_UNHANDLED_HTTP_CODE;
}
- throw new StopRequest(finalStatus, "http error " + statusCode);
+ throw new StopRequest(finalStatus, "http error " + statusCode + ", mContinuingDownload: " +
+ innerState.mContinuingDownload);
}
/**
@@ -863,9 +865,10 @@ public class DownloadThread extends Thread {
*/
private void notifyDownloadCompleted(
int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
- String filename, String uri, String mimeType) {
+ String filename, String uri, String mimeType, String errorMsg) {
notifyThroughDatabase(
- status, countRetry, retryAfter, redirectCount, gotData, filename, uri, mimeType);
+ status, countRetry, retryAfter, redirectCount, gotData, filename, uri, mimeType,
+ errorMsg);
if (Downloads.Impl.isStatusCompleted(status)) {
mInfo.sendIntentIfRequested();
}
@@ -873,7 +876,7 @@ public class DownloadThread extends Thread {
private void notifyThroughDatabase(
int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
- String filename, String uri, String mimeType) {
+ String filename, String uri, String mimeType, String errorMsg) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_STATUS, status);
values.put(Downloads.Impl._DATA, filename);
@@ -890,7 +893,11 @@ public class DownloadThread extends Thread {
} else {
values.put(Constants.FAILED_CONNECTIONS, mInfo.mNumFailed + 1);
}
-
+ // STOPSHIP begin delete the following lines
+ if (!TextUtils.isEmpty(errorMsg)) {
+ values.put(Downloads.Impl.COLUMN_ERROR_MSG, errorMsg);
+ }
+ // STOPSHIP end
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
}
diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java
index a20a7592..59cc97cf 100644
--- a/src/com/android/providers/downloads/Helpers.java
+++ b/src/com/android/providers/downloads/Helpers.java
@@ -16,7 +16,6 @@
package com.android.providers.downloads;
-import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
@@ -99,25 +98,22 @@ public class Helpers {
boolean isPublicApi) throws GenerateSaveFileError {
checkCanHandleDownload(context, mimeType, destination, isPublicApi);
if (destination == Downloads.Impl.DESTINATION_FILE_URI) {
- return getPathForFileUri(hint, contentLength);
+ String path = verifyFileUri(hint, contentLength);
+ String c = getFullPath(path, mimeType, destination, null);
+ return c;
} else {
return chooseFullPath(context, url, hint, contentDisposition, contentLocation, mimeType,
destination, contentLength);
}
}
- private static String getPathForFileUri(String hint, long contentLength)
+ private static String verifyFileUri(String hint, long contentLength)
throws GenerateSaveFileError {
if (!isExternalMediaMounted()) {
throw new GenerateSaveFileError(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR,
"external media not mounted");
}
String path = Uri.parse(hint).getPath();
- if (new File(path).exists()) {
- Log.d(Constants.TAG, "File already exists: " + path);
- throw new GenerateSaveFileError(Downloads.Impl.STATUS_FILE_ALREADY_EXISTS_ERROR,
- "requested destination file already exists");
- }
if (getAvailableBytes(getFilesystemRoot(path)) < contentLength) {
throw new GenerateSaveFileError(Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR,
"insufficient space on external storage");
@@ -148,11 +144,15 @@ public class Helpers {
File base = locateDestinationDirectory(context, mimeType, destination, contentLength);
String filename = chooseFilename(url, hint, contentDisposition, contentLocation,
destination);
+ return getFullPath(filename, mimeType, destination, base);
+ }
+ private static String getFullPath(String filename, String mimeType, int destination,
+ File base) throws GenerateSaveFileError {
// Split filename between base and extension
// Add an extension if filename does not have one
String extension = null;
- int dotIndex = filename.indexOf('.');
+ int dotIndex = filename.lastIndexOf('.');
if (dotIndex < 0) {
extension = chooseExtensionFromMimeType(mimeType, true);
} else {
@@ -162,12 +162,13 @@ public class Helpers {
boolean recoveryDir = Constants.RECOVERY_DIRECTORY.equalsIgnoreCase(filename + extension);
- filename = base.getPath() + File.separator + filename;
+ if (base != null) {
+ filename = base.getPath() + File.separator + filename;
+ }
if (Constants.LOGVV) {
Log.v(Constants.TAG, "target file: " + filename + extension);
}
-
return chooseUniqueFilename(destination, filename, extension, recoveryDir);
}
@@ -850,19 +851,4 @@ public class Helpers {
}
return sb.toString();
}
-
- /*
- * Delete the given file from device
- * and delete its row from the downloads database.
- */
- /* package */ static void deleteFile(ContentResolver resolver, long id, String path, String mimeType) {
- try {
- File file = new File(path);
- file.delete();
- } catch (Exception e) {
- Log.w(Constants.TAG, "file: '" + path + "' couldn't be deleted", e);
- }
- resolver.delete(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, Downloads.Impl._ID + " = ? ",
- new String[]{String.valueOf(id)});
- }
}
diff --git a/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java b/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java
index 2674e907..76339415 100644
--- a/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java
+++ b/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java
@@ -57,7 +57,7 @@ public class PublicApiAccessTest extends AndroidTestCase {
@Override
protected void tearDown() throws Exception {
if (mContentResolver != null) {
- mContentResolver.delete(Downloads.CONTENT_URI, null, null);
+ mContentResolver.delete(Downloads.Impl.CONTENT_URI, null, null);
}
super.tearDown();
}
diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java
index d04fd2de..5283d425 100644
--- a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java
@@ -59,6 +59,14 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
protected MockContentResolverWithNotify mResolver;
protected TestContext mTestContext;
protected FakeSystemFacade mSystemFacade;
+ protected static String STRING_1K;
+ static {
+ StringBuilder buff = new StringBuilder();
+ for (int i = 0; i < 1024; i++) {
+ buff.append("a" + i % 26);
+ }
+ STRING_1K = buff.toString();
+ }
static class MockContentResolverWithNotify extends MockContentResolver {
public boolean mNotifyWasCalled = false;
@@ -161,6 +169,7 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
@Override
protected void tearDown() throws Exception {
cleanUpDownloads();
+ mServer.shutdown();
super.tearDown();
}
@@ -189,8 +198,8 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
if (mResolver == null) {
return;
}
- String[] columns = new String[] {Downloads._DATA};
- Cursor cursor = mResolver.query(Downloads.CONTENT_URI, columns, null, null, null);
+ String[] columns = new String[] {Downloads.Impl._DATA};
+ Cursor cursor = mResolver.query(Downloads.Impl.CONTENT_URI, columns, null, null, null);
try {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String filePath = cursor.getString(0);
@@ -201,11 +210,11 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
} finally {
cursor.close();
}
- mResolver.delete(Downloads.CONTENT_URI, null, null);
+ mResolver.delete(Downloads.Impl.CONTENT_URI, null, null);
}
/**
- * Enqueue a response from the MockWebServer.
+ * Enqueue a String response from the MockWebServer.
*/
MockResponse enqueueResponse(int status, String body) {
MockResponse response = new MockResponse()
@@ -216,6 +225,18 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
mServer.enqueue(response);
return response;
}
+ /**
+ * Enqueue a byte[] response from the MockWebServer.
+ */
+ MockResponse enqueueResponse(int status, byte[] body) {
+ MockResponse response = new MockResponse()
+ .setResponseCode(status)
+ .setBody(body)
+ .addHeader("Content-type", "text/plain")
+ .setCloseConnectionAfter(true);
+ mServer.enqueue(response);
+ return response;
+ }
MockResponse enqueueEmptyResponse(int status) {
return enqueueResponse(status, "");
diff --git a/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java b/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
index ed443b01..c38c2f1d 100644
--- a/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
+++ b/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
@@ -20,6 +20,8 @@ import android.app.DownloadManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+import android.provider.Downloads;
+import android.util.Log;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -41,6 +43,22 @@ public abstract class AbstractPublicApiTest extends AbstractDownloadManagerFunct
return (int) getLongField(DownloadManager.COLUMN_STATUS);
}
+ public int getStatusIfExists() {
+ Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
+ try {
+ if (cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ return (int) cursor.getLong(cursor.getColumnIndexOrThrow(
+ DownloadManager.COLUMN_STATUS));
+ } else {
+ // the row doesn't exist
+ return -1;
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
String getStringField(String field) {
Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
try {
@@ -79,6 +97,63 @@ public abstract class AbstractPublicApiTest extends AbstractDownloadManagerFunct
runService();
assertEquals(status, getStatus());
}
+
+ // max time to wait before giving up on the current download operation.
+ private static final int MAX_TIME_TO_WAIT_FOR_OPERATION = 5;
+ // while waiting for the above time period, sleep this long to yield to the
+ // download thread
+ private static final int TIME_TO_SLEEP = 1000;
+
+ int runUntilDone() throws InterruptedException {
+ int sleepCounter = MAX_TIME_TO_WAIT_FOR_OPERATION * 1000 / TIME_TO_SLEEP;
+ for (int i = 0; i < sleepCounter; i++) {
+ int status = getStatusIfExists();
+ if (status == -1 || Downloads.Impl.isStatusCompleted(getStatus())) {
+ // row doesn't exist or the download is done
+ return status;
+ }
+ // download not done yet. sleep a while and try again
+ Thread.sleep(TIME_TO_SLEEP);
+ }
+ return 0; // failed
+ }
+
+ // waits until progress_so_far is >= (progress)%
+ boolean runUntilProgress(int progress) throws InterruptedException {
+ int sleepCounter = MAX_TIME_TO_WAIT_FOR_OPERATION * 1000 / TIME_TO_SLEEP;
+ int numBytesReceivedSoFar = 0;
+ int totalBytes = 0;
+ for (int i = 0; i < sleepCounter; i++) {
+ Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
+ try {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ numBytesReceivedSoFar = cursor.getInt(
+ cursor.getColumnIndexOrThrow(
+ DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
+ totalBytes = cursor.getInt(
+ cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
+ } finally {
+ cursor.close();
+ }
+ Log.i(LOG_TAG, "in runUntilProgress, numBytesReceivedSoFar: " +
+ numBytesReceivedSoFar + ", totalBytes: " + totalBytes);
+ if (totalBytes == 0) {
+ fail("total_bytes should not be zero");
+ return false;
+ } else {
+ if (numBytesReceivedSoFar * 100 / totalBytes >= progress) {
+ // progress_so_far is >= progress%. we are done
+ return true;
+ }
+ }
+ // download not done yet. sleep a while and try again
+ Thread.sleep(TIME_TO_SLEEP);
+ }
+ Log.i(LOG_TAG, "FAILED in runUntilProgress, numBytesReceivedSoFar: " +
+ numBytesReceivedSoFar + ", totalBytes: " + totalBytes);
+ return false; // failed
+ }
}
protected static final String PACKAGE_NAME = "my.package.name";
diff --git a/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java
index 0cb63e0f..7a2bfdff 100644
--- a/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java
@@ -41,15 +41,15 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
super(new FakeSystemFacade());
}
- public void testBasicRequest() throws Exception {
+ public void testDownloadTextFile() throws Exception {
enqueueResponse(HTTP_OK, FILE_CONTENT);
String path = "/download_manager_test_path";
Uri downloadUri = requestDownload(path);
- assertEquals(Downloads.STATUS_PENDING, getDownloadStatus(downloadUri));
+ assertEquals(Downloads.Impl.STATUS_PENDING, getDownloadStatus(downloadUri));
assertTrue(mTestContext.mHasServiceBeenStarted);
- runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
+ runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
RecordedRequest request = takeRequest();
assertEquals("GET", request.getMethod());
assertEquals(path, request.getPath());
@@ -61,9 +61,9 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
public void testDownloadToCache() throws Exception {
enqueueResponse(HTTP_OK, FILE_CONTENT);
Uri downloadUri = requestDownload("/path");
- updateDownload(downloadUri, Downloads.COLUMN_DESTINATION,
- Integer.toString(Downloads.DESTINATION_CACHE_PARTITION));
- runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
+ updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION,
+ Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION));
+ runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
assertEquals(FILE_CONTENT, getDownloadContents(downloadUri));
assertStartsWith(Environment.getDownloadCacheDirectory().getPath(),
getDownloadFilename(downloadUri));
@@ -76,18 +76,18 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
// for a normal download, roaming is fine
enqueueResponse(HTTP_OK, FILE_CONTENT);
Uri downloadUri = requestDownload("/path");
- runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
+ runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
// when roaming is disallowed, the download should pause...
downloadUri = requestDownload("/path");
- updateDownload(downloadUri, Downloads.COLUMN_DESTINATION,
- Integer.toString(Downloads.DESTINATION_CACHE_PARTITION_NOROAMING));
+ updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION,
+ Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING));
runUntilStatus(downloadUri, Downloads.Impl.STATUS_WAITING_FOR_NETWORK);
// ...and pick up when we're off roaming
enqueueResponse(HTTP_OK, FILE_CONTENT);
mSystemFacade.mIsRoaming = false;
- runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
+ runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
}
/**
@@ -108,11 +108,11 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
}
protected int getDownloadStatus(Uri downloadUri) {
- return Integer.valueOf(getDownloadField(downloadUri, Downloads.COLUMN_STATUS));
+ return Integer.valueOf(getDownloadField(downloadUri, Downloads.Impl.COLUMN_STATUS));
}
private String getDownloadFilename(Uri downloadUri) {
- return getDownloadField(downloadUri, Downloads._DATA);
+ return getDownloadField(downloadUri, Downloads.Impl._DATA);
}
private String getDownloadField(Uri downloadUri, String column) {
@@ -132,9 +132,9 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
*/
private Uri requestDownload(String path) throws MalformedURLException {
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_URI, getServerUri(path));
- values.put(Downloads.COLUMN_DESTINATION, Downloads.DESTINATION_EXTERNAL);
- return mResolver.insert(Downloads.CONTENT_URI, values);
+ values.put(Downloads.Impl.COLUMN_URI, getServerUri(path));
+ values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_EXTERNAL);
+ return mResolver.insert(Downloads.Impl.CONTENT_URI, values);
}
/**
diff --git a/tests/src/com/android/providers/downloads/FakeSystemFacade.java b/tests/src/com/android/providers/downloads/FakeSystemFacade.java
index 5263015c..9620ffc3 100644
--- a/tests/src/com/android/providers/downloads/FakeSystemFacade.java
+++ b/tests/src/com/android/providers/downloads/FakeSystemFacade.java
@@ -23,12 +23,16 @@ public class FakeSystemFacade implements SystemFacade {
Map<Long,Notification> mActiveNotifications = new HashMap<Long,Notification>();
List<Notification> mCanceledNotifications = new ArrayList<Notification>();
Queue<Thread> mStartedThreads = new LinkedList<Thread>();
+ private boolean returnActualTime = false;
void incrementTimeMillis(long delta) {
mTimeMillis += delta;
}
public long currentTimeMillis() {
+ if (returnActualTime) {
+ return System.currentTimeMillis();
+ }
return mTimeMillis;
}
@@ -81,9 +85,18 @@ public class FakeSystemFacade implements SystemFacade {
}
}
+ public boolean startThreadsWithoutWaiting = false;
+ public void setStartThreadsWithoutWaiting(boolean flag) {
+ this.startThreadsWithoutWaiting = flag;
+ }
+
@Override
public void startThread(Thread thread) {
- mStartedThreads.add(thread);
+ if (startThreadsWithoutWaiting) {
+ thread.start();
+ } else {
+ mStartedThreads.add(thread);
+ }
}
public void runAllThreads() {
@@ -91,4 +104,8 @@ public class FakeSystemFacade implements SystemFacade {
mStartedThreads.poll().run();
}
}
+
+ public void setReturnActualTime(boolean flag) {
+ returnActualTime = flag;
+ }
}
diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
index cad01df6..5d149308 100644
--- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
@@ -16,6 +16,7 @@
package com.android.providers.downloads;
+
import android.app.DownloadManager;
import android.content.Intent;
import android.database.Cursor;
@@ -53,17 +54,18 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
+ "download_manager_functional_test");
if (mTestDirectory.exists()) {
- mTestDirectory.delete();
- }
- if (!mTestDirectory.mkdir()) {
- throw new RuntimeException("Couldn't create test directory: "
- + mTestDirectory.getPath());
+ for (File file : mTestDirectory.listFiles()) {
+ file.delete();
+ }
+ } else {
+ mTestDirectory.mkdir();
}
+ mSystemFacade.setStartThreadsWithoutWaiting(false);
}
@Override
protected void tearDown() throws Exception {
- if (mTestDirectory != null) {
+ if (mTestDirectory != null && mTestDirectory.exists()) {
for (File file : mTestDirectory.listFiles()) {
file.delete();
}
@@ -184,6 +186,18 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
return response;
}
+ // enqueue a huge response to keep the receiveing thread in DownloadThread.java busy for a while
+ // give enough time to do something (cancel/remove etc) on that downloadrequest
+ // while it is in progress
+ private void enqueueContinuingResponse() {
+ int numPackets = 100;
+ int contentLength = STRING_1K.length() * numPackets;
+ enqueueResponse(HTTP_OK, STRING_1K)
+ .addHeader("Content-length", contentLength)
+ .addHeader("Etag", ETAG)
+ .setNumPackets(numPackets);
+ }
+
public void testFiltering() throws Exception {
enqueueEmptyResponse(HTTP_OK);
Download download1 = enqueueRequest(getRequest());
@@ -301,7 +315,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
}
private Uri getExternalUri() {
- return Uri.fromFile(mTestDirectory).buildUpon().appendPath("testfile").build();
+ return Uri.fromFile(mTestDirectory).buildUpon().appendPath("testfile.txt").build();
}
public void testRequestHeaders() throws Exception {
@@ -379,14 +393,22 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
}
public void testCancel() throws Exception {
- enqueuePartialResponse(0, 5);
+ mSystemFacade.setStartThreadsWithoutWaiting(true);
+ // return 'real time' from FakeSystemFacade so that DownloadThread will report progress
+ mSystemFacade.setReturnActualTime(true);
+ enqueueContinuingResponse();
Download download = enqueueRequest(getRequest());
- download.runUntilStatus(DownloadManager.STATUS_PAUSED);
-
+ startService(null);
+ // give the download time to get started and progress to 1% completion
+ // before cancelling it.
+ boolean rslt = download.runUntilProgress(1);
+ assertTrue(rslt);
mManager.remove(download.mId);
- mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
- runService();
- // if the cancel didn't work, we should get an unexpected request to the HTTP server
+ startService(null);
+ int status = download.runUntilDone();
+ // make sure the row is gone from the database
+ assertEquals(-1, status);
+ mSystemFacade.setReturnActualTime(false);
}
public void testDownloadCompleteBroadcast() throws Exception {
@@ -524,14 +546,15 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
}
public void testExistingFile() throws Exception {
+ // download a file which already exists.
+ // downloadservice should simply create filename with "-" and a number attached
+ // at the end; i.e., download shouldnot fail.
Uri destination = getExternalUri();
new File(destination.getPath()).createNewFile();
enqueueEmptyResponse(HTTP_OK);
Download download = enqueueRequest(getRequest().setDestinationUri(destination));
- download.runUntilStatus(DownloadManager.STATUS_FAILED);
- assertEquals(DownloadManager.ERROR_FILE_ALREADY_EXISTS,
- download.getLongField(DownloadManager.COLUMN_REASON));
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
}
public void testEmptyFields() throws Exception {
diff --git a/tests/src/tests/http/MockResponse.java b/tests/src/tests/http/MockResponse.java
index 4cda92d2..aec5490c 100644
--- a/tests/src/tests/http/MockResponse.java
+++ b/tests/src/tests/http/MockResponse.java
@@ -36,6 +36,7 @@ public class MockResponse {
private Map<String, String> headers = new HashMap<String, String>();
private byte[] body = EMPTY_BODY;
private boolean closeConnectionAfter = false;
+ private int numPackets = 0;
public MockResponse() {
addHeader("Content-Length", 0);
@@ -133,4 +134,14 @@ public class MockResponse {
this.closeConnectionAfter = closeConnectionAfter;
return this;
}
+
+ public int getNumPackets() {
+ return numPackets;
+ }
+
+ public MockResponse setNumPackets(int numPackets) {
+ this.numPackets = numPackets;
+ return this;
+ }
+
}
diff --git a/tests/src/tests/http/MockWebServer.java b/tests/src/tests/http/MockWebServer.java
index 11c8063e..6096783d 100644
--- a/tests/src/tests/http/MockWebServer.java
+++ b/tests/src/tests/http/MockWebServer.java
@@ -16,6 +16,9 @@
package tests.http;
+import android.text.TextUtils;
+import android.util.Log;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@@ -59,6 +62,7 @@ public final class MockWebServer {
private final Queue<Future<?>> futures = new LinkedList<Future<?>>();
private int port = -1;
+ private ServerSocket serverSocket;
public int getPort() {
if (port == -1) {
@@ -111,26 +115,35 @@ public final class MockWebServer {
* down.
*/
public void play() throws IOException {
- final ServerSocket ss = new ServerSocket(0);
- ss.setReuseAddress(true);
- port = ss.getLocalPort();
+ serverSocket = new ServerSocket(0);
+ serverSocket.setReuseAddress(true);
+ port = serverSocket.getLocalPort();
submitCallable(new Callable<Void>() {
public Void call() throws Exception {
int count = 0;
while (true) {
if (count > 0 && responseQueue.isEmpty()) {
- ss.close();
+ serverSocket.close();
executor.shutdown();
return null;
}
- serveConnection(ss.accept());
+ serveConnection(serverSocket.accept());
count++;
}
}
});
}
+ /**
+ * shutdown the webserver
+ */
+ public void shutdown() throws IOException {
+ responseQueue.clear();
+ serverSocket.close();
+ executor.shutdown();
+ }
+
private void serveConnection(final Socket s) {
submitCallable(new Callable<Void>() {
public Void call() throws Exception {
@@ -148,8 +161,7 @@ public final class MockWebServer {
}
}
requestQueue.add(request);
- MockResponse response = computeResponse(request);
- writeResponse(out, response);
+ MockResponse response = sendResponse(out, request);
if (response.shouldCloseConnectionAfter()) {
break;
}
@@ -241,7 +253,6 @@ public final class MockWebServer {
} else {
throw new UnsupportedOperationException("Unexpected method: " + request);
}
-
return new RecordedRequest(request, headers, chunkSizes,
requestBody.numBytesReceived, requestBody.toByteArray(), sequenceNumber);
}
@@ -249,14 +260,32 @@ public final class MockWebServer {
/**
* Returns a response to satisfy {@code request}.
*/
- private MockResponse computeResponse(RecordedRequest request) throws InterruptedException {
+ private MockResponse sendResponse(OutputStream out, RecordedRequest request)
+ throws InterruptedException, IOException {
if (responseQueue.isEmpty()) {
throw new IllegalStateException("Unexpected request: " + request);
}
- return responseQueue.take();
- }
+ MockResponse response = responseQueue.take();
+ writeResponse(out, response, false);
+ if (response.getNumPackets() > 0) {
+ // there are continuing packets to send as part of this response.
+ for (int i = 0; i < response.getNumPackets(); i++) {
+ writeResponse(out, response, true);
+ // delay sending next continuing response just a little bit
+ Thread.sleep(100);
+ }
+ }
+ return response;
+ }
- private void writeResponse(OutputStream out, MockResponse response) throws IOException {
+ private void writeResponse(OutputStream out, MockResponse response,
+ boolean continuingPacket) throws IOException {
+ if (continuingPacket) {
+ // this is a continuing response - just send the body - no headers, status
+ out.write(response.getBody());
+ out.flush();
+ return;
+ }
out.write((response.getStatus() + "\r\n").getBytes(ASCII));
for (String header : response.getHeaders()) {
out.write((header + "\r\n").getBytes(ASCII));
diff --git a/ui/AndroidManifest.xml b/ui/AndroidManifest.xml
index c2c93241..80510ed4 100644
--- a/ui/AndroidManifest.xml
+++ b/ui/AndroidManifest.xml
@@ -8,7 +8,7 @@
<application android:process="android.process.media"
android:label="@string/app_label"
- android:icon="@drawable/ic_launcher_download">
+ android:icon="@mipmap/ic_launcher_download">
<activity android:name=".DownloadList"
android:launchMode="singleTop">
<intent-filter>
diff --git a/ui/res/drawable-hdpi/ic_launcher_download.png b/ui/res/mipmap-hdpi/ic_launcher_download.png
index 308835cd..308835cd 100644
--- a/ui/res/drawable-hdpi/ic_launcher_download.png
+++ b/ui/res/mipmap-hdpi/ic_launcher_download.png
Binary files differ
diff --git a/ui/res/drawable-mdpi/ic_launcher_download.png b/ui/res/mipmap-mdpi/ic_launcher_download.png
index 6dd4ba35..6dd4ba35 100644
--- a/ui/res/drawable-mdpi/ic_launcher_download.png
+++ b/ui/res/mipmap-mdpi/ic_launcher_download.png
Binary files differ
diff --git a/ui/src/com/android/providers/downloads/ui/DownloadList.java b/ui/src/com/android/providers/downloads/ui/DownloadList.java
index 0ab3f936..133b0bfe 100644
--- a/ui/src/com/android/providers/downloads/ui/DownloadList.java
+++ b/ui/src/com/android/providers/downloads/ui/DownloadList.java
@@ -33,7 +33,6 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.Downloads;
-import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -572,31 +571,10 @@ public class DownloadList extends Activity
* Delete a download from the Download Manager.
*/
private void deleteDownload(long downloadId) {
- if (moveToDownload(downloadId)) {
- int status = mDateSortedCursor.getInt(mStatusColumnId);
- boolean isComplete = status == DownloadManager.STATUS_SUCCESSFUL
- || status == DownloadManager.STATUS_FAILED;
- String localUri = mDateSortedCursor.getString(mLocalUriColumnId);
- if (isComplete && localUri != null) {
- String path = Uri.parse(localUri).getPath();
- if (path.startsWith(Environment.getExternalStorageDirectory().getPath())) {
- String mediaProviderUri = mDateSortedCursor.getString(mMediaProviderUriId);
- if (TextUtils.isEmpty(mediaProviderUri)) {
- // downloads database doesn't have the mediaprovider_uri. It means
- // this download occurred before mediaprovider_uri column existed
- // in downloads table. Since MediaProvider needs the mediaprovider_uri to
- // delete this download, just set the 'deleted' flag to 1 on this row
- // in the database. DownloadService, upon seeing this flag set to 1, will
- // re-scan the file and get the MediaProviderUri and then delete the file
- mDownloadManager.markRowDeleted(downloadId);
- return;
- } else {
- getContentResolver().delete(Uri.parse(mediaProviderUri), null, null);
- }
- }
- }
- }
- mDownloadManager.remove(downloadId);
+ // let DownloadService do the job of cleaning up the downloads db, mediaprovider db,
+ // and removal of file from sdcard
+ // TODO do the following in asynctask - not on main thread.
+ mDownloadManager.markRowDeleted(downloadId);
}
@Override